Merge "Add VVM carrier config to public API." into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index 80798bc..dea5255 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -215,6 +215,8 @@
public static final class R.attr {
ctor public R.attr();
+ field public static final int __removeBeforeMRelease_leftIndents = 16844016; // 0x10104f0
+ field public static final int __removeBeforeMRelease_rightIndents = 16844017; // 0x10104f1
field public static final int __reserved0 = 16844020; // 0x10104f4
field public static final int __reserved1 = 16844019; // 0x10104f3
field public static final int __reserved2 = 16843999; // 0x10104df
@@ -801,7 +803,6 @@
field public static final int layout_x = 16843135; // 0x101017f
field public static final int layout_y = 16843136; // 0x1010180
field public static final int left = 16843181; // 0x10101ad
- field public static final int leftIndents = 16844016; // 0x10104f0
field public static final int letterSpacing = 16843958; // 0x10104b6
field public static final int lineSpacingExtra = 16843287; // 0x1010217
field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
@@ -826,6 +827,7 @@
field public static final int listViewWhiteStyle = 16842869; // 0x1010075
field public static final int lockTaskMode = 16844015; // 0x10104ef
field public static final int logo = 16843454; // 0x10102be
+ field public static final int logoDescription = 16844026; // 0x10104fa
field public static final int longClickable = 16842982; // 0x10100e6
field public static final int loopViews = 16843527; // 0x1010307
field public static final int manageSpaceActivity = 16842756; // 0x1010004
@@ -1026,7 +1028,6 @@
field public static final int reversible = 16843851; // 0x101044b
field public static final int revisionCode = 16843989; // 0x10104d5
field public static final int right = 16843183; // 0x10101af
- field public static final int rightIndents = 16844017; // 0x10104f1
field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
field public static final int ringtoneType = 16843257; // 0x10101f9
field public static final int rotation = 16843558; // 0x1010326
@@ -1178,6 +1179,7 @@
field public static final int submitBackground = 16843912; // 0x1010488
field public static final int subtitle = 16843473; // 0x10102d1
field public static final int subtitleTextAppearance = 16843823; // 0x101042f
+ field public static final int subtitleTextColor = 16844028; // 0x10104fc
field public static final int subtitleTextStyle = 16843513; // 0x10102f9
field public static final int subtypeExtraValue = 16843674; // 0x101039a
field public static final int subtypeId = 16843713; // 0x10103c1
@@ -1308,6 +1310,7 @@
field public static final int title = 16843233; // 0x10101e1
field public static final int titleCondensed = 16843234; // 0x10101e2
field public static final int titleTextAppearance = 16843822; // 0x101042e
+ field public static final int titleTextColor = 16844027; // 0x10104fb
field public static final int titleTextStyle = 16843512; // 0x10102f8
field public static final int toAlpha = 16843211; // 0x10101cb
field public static final int toDegrees = 16843188; // 0x10101b4
@@ -2109,22 +2112,6 @@
field public static final int Theme_Light_Panel = 16973914; // 0x103005a
field public static final int Theme_Light_WallpaperSettings = 16973922; // 0x1030062
field public static final int Theme_Material = 16974372; // 0x1030224
- field public static final int Theme_Material_DayNight = 16974548; // 0x10302d4
- field public static final int Theme_Material_DayNight_DarkActionBar = 16974549; // 0x10302d5
- field public static final int Theme_Material_DayNight_Dialog = 16974550; // 0x10302d6
- field public static final int Theme_Material_DayNight_DialogWhenLarge = 16974556; // 0x10302dc
- field public static final int Theme_Material_DayNight_DialogWhenLarge_DarkActionBar = 16974568; // 0x10302e8
- field public static final int Theme_Material_DayNight_DialogWhenLarge_NoActionBar = 16974557; // 0x10302dd
- field public static final int Theme_Material_DayNight_Dialog_Alert = 16974551; // 0x10302d7
- field public static final int Theme_Material_DayNight_Dialog_MinWidth = 16974552; // 0x10302d8
- field public static final int Theme_Material_DayNight_Dialog_NoActionBar = 16974553; // 0x10302d9
- field public static final int Theme_Material_DayNight_Dialog_NoActionBar_MinWidth = 16974554; // 0x10302da
- field public static final int Theme_Material_DayNight_Dialog_Presentation = 16974555; // 0x10302db
- field public static final int Theme_Material_DayNight_NoActionBar = 16974558; // 0x10302de
- field public static final int Theme_Material_DayNight_NoActionBar_Fullscreen = 16974559; // 0x10302df
- field public static final int Theme_Material_DayNight_NoActionBar_Overscan = 16974560; // 0x10302e0
- field public static final int Theme_Material_DayNight_NoActionBar_TranslucentDecor = 16974561; // 0x10302e1
- field public static final int Theme_Material_DayNight_Panel = 16974562; // 0x10302e2
field public static final int Theme_Material_Dialog = 16974373; // 0x1030225
field public static final int Theme_Material_DialogWhenLarge = 16974379; // 0x103022b
field public static final int Theme_Material_DialogWhenLarge_NoActionBar = 16974380; // 0x103022c
@@ -2138,7 +2125,6 @@
field public static final int Theme_Material_Light_DarkActionBar = 16974392; // 0x1030238
field public static final int Theme_Material_Light_Dialog = 16974393; // 0x1030239
field public static final int Theme_Material_Light_DialogWhenLarge = 16974399; // 0x103023f
- field public static final int Theme_Material_Light_DialogWhenLarge_DarkActionBar = 16974567; // 0x10302e7
field public static final int Theme_Material_Light_DialogWhenLarge_NoActionBar = 16974400; // 0x1030240
field public static final int Theme_Material_Light_Dialog_Alert = 16974394; // 0x103023a
field public static final int Theme_Material_Light_Dialog_MinWidth = 16974395; // 0x103023b
@@ -2594,6 +2580,21 @@
field public static final int Widget_Toolbar = 16974311; // 0x10301e7
field public static final int Widget_Toolbar_Button_Navigation = 16974312; // 0x10301e8
field public static final int Widget_WebView = 16973875; // 0x1030033
+ field public static final int __reserved10 = 16974550; // 0x10302d6
+ field public static final int __reserved11 = 16974551; // 0x10302d7
+ field public static final int __reserved12 = 16974552; // 0x10302d8
+ field public static final int __reserved13 = 16974553; // 0x10302d9
+ field public static final int __reserved14 = 16974554; // 0x10302da
+ field public static final int __reserved15 = 16974555; // 0x10302db
+ field public static final int __reserved16 = 16974556; // 0x10302dc
+ field public static final int __reserved17 = 16974557; // 0x10302dd
+ field public static final int __reserved18 = 16974558; // 0x10302de
+ field public static final int __reserved19 = 16974559; // 0x10302df
+ field public static final int __reserved20 = 16974560; // 0x10302e0
+ field public static final int __reserved21 = 16974561; // 0x10302e1
+ field public static final int __reserved22 = 16974562; // 0x10302e2
+ field public static final int __reserved8 = 16974548; // 0x10302d4
+ field public static final int __reserved9 = 16974549; // 0x10302d5
}
public static final class R.transition {
@@ -3758,7 +3759,7 @@
method public void requestUsageTimeReport(android.app.PendingIntent);
method public android.os.Bundle toBundle();
method public void update(android.app.ActivityOptions);
- field public static final java.lang.String EXTRA_USAGE_TIME_REPORT = "android.usage_time";
+ field public static final java.lang.String EXTRA_USAGE_TIME_REPORT = "android.activity.usage_time";
field public static final java.lang.String EXTRA_USAGE_TIME_REPORT_PACKAGES = "android.usage_time_packages";
}
@@ -5194,6 +5195,7 @@
method public void send(int, android.app.PendingIntent.OnFinished, android.os.Handler) throws android.app.PendingIntent.CanceledException;
method public void send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler) throws android.app.PendingIntent.CanceledException;
method public void send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler, java.lang.String) throws android.app.PendingIntent.CanceledException;
+ method public void send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler, java.lang.String, android.os.Bundle) throws android.app.PendingIntent.CanceledException;
method public static void writePendingIntentOrNullToParcel(android.app.PendingIntent, android.os.Parcel);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.PendingIntent> CREATOR;
@@ -5848,7 +5850,6 @@
field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME";
- field public static final java.lang.String EXTRA_PROVISIONING_RESET_PROTECTION_PARAMETERS = "android.app.extra.PROVISIONING_RESET_PROTECTION_PARAMETERS";
field public static final java.lang.String EXTRA_PROVISIONING_SKIP_ENCRYPTION = "android.app.extra.PROVISIONING_SKIP_ENCRYPTION";
field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.PROVISIONING_TIME_ZONE";
field public static final java.lang.String EXTRA_PROVISIONING_WIFI_HIDDEN = "android.app.extra.PROVISIONING_WIFI_HIDDEN";
@@ -12302,7 +12303,6 @@
method public android.graphics.drawable.Drawable.ConstantState getConstantState();
method public android.graphics.drawable.Drawable getCurrent();
method public android.graphics.Rect getDirtyBounds();
- method public boolean getDither();
method public void getHotspotBounds(android.graphics.Rect);
method public int getIntrinsicHeight();
method public int getIntrinsicWidth();
@@ -12319,6 +12319,7 @@
method public void inflate(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public void invalidateSelf();
method public boolean isAutoMirrored();
+ method public boolean isDither();
method public boolean isFilterBitmap();
method public boolean isStateful();
method public final boolean isVisible();
@@ -26057,6 +26058,7 @@
field public static final java.lang.String EXTRA_EXCLUDE_SELF = "android.provider.extra.EXCLUDE_SELF";
field public static final java.lang.String EXTRA_INFO = "info";
field public static final java.lang.String EXTRA_LOADING = "loading";
+ field public static final java.lang.String EXTRA_PROMPT = "android.provider.extra.PROMPT";
field public static final java.lang.String PROVIDER_INTERFACE = "android.content.action.DOCUMENTS_PROVIDER";
}
@@ -27918,8 +27920,6 @@
public static final class ScriptGroup.Binding {
ctor public ScriptGroup.Binding(android.renderscript.Script.FieldID, java.lang.Object);
- method public android.renderscript.Script.FieldID getField();
- method public java.lang.Object getValue();
}
public static final deprecated class ScriptGroup.Builder {
@@ -28909,6 +28909,7 @@
method public void onDestroy();
method public boolean[] onGetSupportedCommands(java.lang.String[]);
method public void onHandleAssist(android.os.Bundle, android.app.assist.AssistStructure, android.app.assist.AssistContent);
+ method public void onHandleScreenshot(android.graphics.Bitmap);
method public void onHide();
method public boolean onKeyDown(int, android.view.KeyEvent);
method public boolean onKeyLongPress(int, android.view.KeyEvent);
@@ -28931,6 +28932,7 @@
method public void startVoiceActivity(android.content.Intent);
field public static final int SHOW_SOURCE_ASSIST_GESTURE = 4; // 0x4
field public static final int SHOW_WITH_ASSIST = 1; // 0x1
+ field public static final int SHOW_WITH_SCREENSHOT = 2; // 0x2
}
public static final class VoiceInteractionSession.AbortVoiceRequest extends android.service.voice.VoiceInteractionSession.Request {
@@ -30620,12 +30622,17 @@
field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
field public static final java.lang.String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
field public static final java.lang.String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
+ field public static final java.lang.String KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY = "cdma_nonroaming_networks_string_array";
+ field public static final java.lang.String KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY = "cdma_roaming_networks_string_array";
field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
field public static final java.lang.String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool";
field public static final java.lang.String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_vibration_bool";
+ field public static final java.lang.String KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY = "gsm_nonroaming_networks_string_array";
+ field public static final java.lang.String KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY = "gsm_roaming_networks_string_array";
field public static final java.lang.String KEY_HAS_IN_CALL_NOISE_SUPPRESSION_BOOL = "has_in_call_noise_suppression_bool";
field public static final java.lang.String KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool";
+ field public static final java.lang.String KEY_HIDE_SIM_LOCK_SETTINGS_BOOL = "hide_sim_lock_settings_bool";
field public static final java.lang.String KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL = "ignore_sim_network_locked_events_bool";
field public static final java.lang.String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
field public static final java.lang.String KEY_MMS_ALIAS_MAX_CHARS_INT = "aliasMaxChars";
@@ -36812,6 +36819,8 @@
method public boolean onRequestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
method public boolean onStartNestedScroll(android.view.View, android.view.View, int);
method public void onStopNestedScroll(android.view.View);
+ method public void onViewAdded(android.view.View);
+ method public void onViewRemoved(android.view.View);
method public void recomputeViewAttributes(android.view.View);
method public void removeAllViews();
method public void removeAllViewsInLayout();
@@ -41564,7 +41573,6 @@
method public int getInputType();
method public final android.text.method.KeyListener getKeyListener();
method public final android.text.Layout getLayout();
- method public int[] getLeftIndents();
method public float getLetterSpacing();
method public int getLineBounds(int, android.graphics.Rect);
method public int getLineCount();
@@ -41587,7 +41595,6 @@
method public android.text.TextPaint getPaint();
method public int getPaintFlags();
method public java.lang.String getPrivateImeOptions();
- method public int[] getRightIndents();
method public int getSelectionEnd();
method public int getSelectionStart();
method public int getShadowColor();
@@ -41667,7 +41674,6 @@
method public void setImeActionLabel(java.lang.CharSequence, int);
method public void setImeOptions(int);
method public void setIncludeFontPadding(boolean);
- method public void setIndents(int[], int[]);
method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public void setInputType(int);
method public void setKeyListener(android.text.method.KeyListener);
diff --git a/api/system-current.txt b/api/system-current.txt
index 0dff6d9..d0225e1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -96,6 +96,7 @@
field public static final java.lang.String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES";
field public static final java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
field public static final java.lang.String GET_APP_OPS_STATS = "android.permission.GET_APP_OPS_STATS";
+ field public static final java.lang.String GET_PACKAGE_IMPORTANCE = "android.permission.GET_PACKAGE_IMPORTANCE";
field public static final java.lang.String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
field public static final deprecated java.lang.String GET_TASKS = "android.permission.GET_TASKS";
field public static final java.lang.String GET_TOP_ACTIVITY_INFO = "android.permission.GET_TOP_ACTIVITY_INFO";
@@ -290,6 +291,8 @@
public static final class R.attr {
ctor public R.attr();
+ field public static final int __removeBeforeMRelease_leftIndents = 16844016; // 0x10104f0
+ field public static final int __removeBeforeMRelease_rightIndents = 16844017; // 0x10104f1
field public static final int __reserved0 = 16844020; // 0x10104f4
field public static final int __reserved1 = 16844019; // 0x10104f3
field public static final int __reserved2 = 16843999; // 0x10104df
@@ -876,7 +879,6 @@
field public static final int layout_x = 16843135; // 0x101017f
field public static final int layout_y = 16843136; // 0x1010180
field public static final int left = 16843181; // 0x10101ad
- field public static final int leftIndents = 16844016; // 0x10104f0
field public static final int letterSpacing = 16843958; // 0x10104b6
field public static final int lineSpacingExtra = 16843287; // 0x1010217
field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
@@ -901,6 +903,7 @@
field public static final int listViewWhiteStyle = 16842869; // 0x1010075
field public static final int lockTaskMode = 16844015; // 0x10104ef
field public static final int logo = 16843454; // 0x10102be
+ field public static final int logoDescription = 16844026; // 0x10104fa
field public static final int longClickable = 16842982; // 0x10100e6
field public static final int loopViews = 16843527; // 0x1010307
field public static final int manageSpaceActivity = 16842756; // 0x1010004
@@ -1101,7 +1104,6 @@
field public static final int reversible = 16843851; // 0x101044b
field public static final int revisionCode = 16843989; // 0x10104d5
field public static final int right = 16843183; // 0x10101af
- field public static final int rightIndents = 16844017; // 0x10104f1
field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
field public static final int ringtoneType = 16843257; // 0x10101f9
field public static final int rotation = 16843558; // 0x1010326
@@ -1257,6 +1259,7 @@
field public static final int submitBackground = 16843912; // 0x1010488
field public static final int subtitle = 16843473; // 0x10102d1
field public static final int subtitleTextAppearance = 16843823; // 0x101042f
+ field public static final int subtitleTextColor = 16844028; // 0x10104fc
field public static final int subtitleTextStyle = 16843513; // 0x10102f9
field public static final int subtypeExtraValue = 16843674; // 0x101039a
field public static final int subtypeId = 16843713; // 0x10103c1
@@ -1387,6 +1390,7 @@
field public static final int title = 16843233; // 0x10101e1
field public static final int titleCondensed = 16843234; // 0x10101e2
field public static final int titleTextAppearance = 16843822; // 0x101042e
+ field public static final int titleTextColor = 16844027; // 0x10104fb
field public static final int titleTextStyle = 16843512; // 0x10102f8
field public static final int toAlpha = 16843211; // 0x10101cb
field public static final int toDegrees = 16843188; // 0x10101b4
@@ -2191,22 +2195,6 @@
field public static final int Theme_Light_Panel = 16973914; // 0x103005a
field public static final int Theme_Light_WallpaperSettings = 16973922; // 0x1030062
field public static final int Theme_Material = 16974372; // 0x1030224
- field public static final int Theme_Material_DayNight = 16974548; // 0x10302d4
- field public static final int Theme_Material_DayNight_DarkActionBar = 16974549; // 0x10302d5
- field public static final int Theme_Material_DayNight_Dialog = 16974550; // 0x10302d6
- field public static final int Theme_Material_DayNight_DialogWhenLarge = 16974556; // 0x10302dc
- field public static final int Theme_Material_DayNight_DialogWhenLarge_DarkActionBar = 16974568; // 0x10302e8
- field public static final int Theme_Material_DayNight_DialogWhenLarge_NoActionBar = 16974557; // 0x10302dd
- field public static final int Theme_Material_DayNight_Dialog_Alert = 16974551; // 0x10302d7
- field public static final int Theme_Material_DayNight_Dialog_MinWidth = 16974552; // 0x10302d8
- field public static final int Theme_Material_DayNight_Dialog_NoActionBar = 16974553; // 0x10302d9
- field public static final int Theme_Material_DayNight_Dialog_NoActionBar_MinWidth = 16974554; // 0x10302da
- field public static final int Theme_Material_DayNight_Dialog_Presentation = 16974555; // 0x10302db
- field public static final int Theme_Material_DayNight_NoActionBar = 16974558; // 0x10302de
- field public static final int Theme_Material_DayNight_NoActionBar_Fullscreen = 16974559; // 0x10302df
- field public static final int Theme_Material_DayNight_NoActionBar_Overscan = 16974560; // 0x10302e0
- field public static final int Theme_Material_DayNight_NoActionBar_TranslucentDecor = 16974561; // 0x10302e1
- field public static final int Theme_Material_DayNight_Panel = 16974562; // 0x10302e2
field public static final int Theme_Material_Dialog = 16974373; // 0x1030225
field public static final int Theme_Material_DialogWhenLarge = 16974379; // 0x103022b
field public static final int Theme_Material_DialogWhenLarge_NoActionBar = 16974380; // 0x103022c
@@ -2220,7 +2208,6 @@
field public static final int Theme_Material_Light_DarkActionBar = 16974392; // 0x1030238
field public static final int Theme_Material_Light_Dialog = 16974393; // 0x1030239
field public static final int Theme_Material_Light_DialogWhenLarge = 16974399; // 0x103023f
- field public static final int Theme_Material_Light_DialogWhenLarge_DarkActionBar = 16974567; // 0x10302e7
field public static final int Theme_Material_Light_DialogWhenLarge_NoActionBar = 16974400; // 0x1030240
field public static final int Theme_Material_Light_Dialog_Alert = 16974394; // 0x103023a
field public static final int Theme_Material_Light_Dialog_MinWidth = 16974395; // 0x103023b
@@ -2676,6 +2663,21 @@
field public static final int Widget_Toolbar = 16974311; // 0x10301e7
field public static final int Widget_Toolbar_Button_Navigation = 16974312; // 0x10301e8
field public static final int Widget_WebView = 16973875; // 0x1030033
+ field public static final int __reserved10 = 16974550; // 0x10302d6
+ field public static final int __reserved11 = 16974551; // 0x10302d7
+ field public static final int __reserved12 = 16974552; // 0x10302d8
+ field public static final int __reserved13 = 16974553; // 0x10302d9
+ field public static final int __reserved14 = 16974554; // 0x10302da
+ field public static final int __reserved15 = 16974555; // 0x10302db
+ field public static final int __reserved16 = 16974556; // 0x10302dc
+ field public static final int __reserved17 = 16974557; // 0x10302dd
+ field public static final int __reserved18 = 16974558; // 0x10302de
+ field public static final int __reserved19 = 16974559; // 0x10302df
+ field public static final int __reserved20 = 16974560; // 0x10302e0
+ field public static final int __reserved21 = 16974561; // 0x10302e1
+ field public static final int __reserved22 = 16974562; // 0x10302e2
+ field public static final int __reserved8 = 16974548; // 0x10302d4
+ field public static final int __reserved9 = 16974549; // 0x10302d5
}
public static final class R.transition {
@@ -3851,7 +3853,7 @@
method public void requestUsageTimeReport(android.app.PendingIntent);
method public android.os.Bundle toBundle();
method public void update(android.app.ActivityOptions);
- field public static final java.lang.String EXTRA_USAGE_TIME_REPORT = "android.usage_time";
+ field public static final java.lang.String EXTRA_USAGE_TIME_REPORT = "android.activity.usage_time";
field public static final java.lang.String EXTRA_USAGE_TIME_REPORT_PACKAGES = "android.usage_time_packages";
}
@@ -4183,6 +4185,12 @@
method public int getWidth();
}
+ public class BroadcastOptions {
+ method public static android.app.BroadcastOptions makeBasic();
+ method public void setTemporaryAppWhitelistDuration(long);
+ method public android.os.Bundle toBundle();
+ }
+
public class DatePickerDialog extends android.app.AlertDialog implements android.widget.DatePicker.OnDateChangedListener android.content.DialogInterface.OnClickListener {
ctor public DatePickerDialog(android.content.Context, android.app.DatePickerDialog.OnDateSetListener, int, int, int);
ctor public DatePickerDialog(android.content.Context, int, android.app.DatePickerDialog.OnDateSetListener, int, int, int);
@@ -5289,6 +5297,7 @@
method public void send(int, android.app.PendingIntent.OnFinished, android.os.Handler) throws android.app.PendingIntent.CanceledException;
method public void send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler) throws android.app.PendingIntent.CanceledException;
method public void send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler, java.lang.String) throws android.app.PendingIntent.CanceledException;
+ method public void send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler, java.lang.String, android.os.Bundle) throws android.app.PendingIntent.CanceledException;
method public static void writePendingIntentOrNullToParcel(android.app.PendingIntent, android.os.Parcel);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.PendingIntent> CREATOR;
@@ -5959,7 +5968,6 @@
field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME";
- field public static final java.lang.String EXTRA_PROVISIONING_RESET_PROTECTION_PARAMETERS = "android.app.extra.PROVISIONING_RESET_PROTECTION_PARAMETERS";
field public static final java.lang.String EXTRA_PROVISIONING_SKIP_ENCRYPTION = "android.app.extra.PROVISIONING_SKIP_ENCRYPTION";
field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.PROVISIONING_TIME_ZONE";
field public static final java.lang.String EXTRA_PROVISIONING_WIFI_HIDDEN = "android.app.extra.PROVISIONING_WIFI_HIDDEN";
@@ -7963,10 +7971,12 @@
method public abstract void revokeUriPermission(android.net.Uri, int);
method public abstract void sendBroadcast(android.content.Intent);
method public abstract void sendBroadcast(android.content.Intent, java.lang.String);
+ method public abstract void sendBroadcast(android.content.Intent, java.lang.String, android.os.Bundle);
method public abstract void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
method public abstract void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String);
method public abstract void sendOrderedBroadcast(android.content.Intent, java.lang.String);
method public abstract void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ method public abstract void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.os.Bundle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
method public abstract void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
method public abstract deprecated void sendStickyBroadcast(android.content.Intent);
method public abstract deprecated void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
@@ -8140,10 +8150,12 @@
method public void revokeUriPermission(android.net.Uri, int);
method public void sendBroadcast(android.content.Intent);
method public void sendBroadcast(android.content.Intent, java.lang.String);
+ method public void sendBroadcast(android.content.Intent, java.lang.String, android.os.Bundle);
method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String);
method public void sendOrderedBroadcast(android.content.Intent, java.lang.String);
method public void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ method public void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.os.Bundle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
method public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
method public deprecated void sendStickyBroadcast(android.content.Intent);
method public deprecated void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
@@ -12617,7 +12629,6 @@
method public android.graphics.drawable.Drawable.ConstantState getConstantState();
method public android.graphics.drawable.Drawable getCurrent();
method public android.graphics.Rect getDirtyBounds();
- method public boolean getDither();
method public void getHotspotBounds(android.graphics.Rect);
method public int getIntrinsicHeight();
method public int getIntrinsicWidth();
@@ -12634,6 +12645,7 @@
method public void inflate(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public void invalidateSelf();
method public boolean isAutoMirrored();
+ method public boolean isDither();
method public boolean isFilterBitmap();
method public boolean isStateful();
method public final boolean isVisible();
@@ -27991,6 +28003,7 @@
field public static final java.lang.String EXTRA_EXCLUDE_SELF = "android.provider.extra.EXCLUDE_SELF";
field public static final java.lang.String EXTRA_INFO = "info";
field public static final java.lang.String EXTRA_LOADING = "loading";
+ field public static final java.lang.String EXTRA_PROMPT = "android.provider.extra.PROMPT";
field public static final java.lang.String PROVIDER_INTERFACE = "android.content.action.DOCUMENTS_PROVIDER";
}
@@ -29955,8 +29968,6 @@
public static final class ScriptGroup.Binding {
ctor public ScriptGroup.Binding(android.renderscript.Script.FieldID, java.lang.Object);
- method public android.renderscript.Script.FieldID getField();
- method public java.lang.Object getValue();
}
public static final deprecated class ScriptGroup.Builder {
@@ -30903,7 +30914,6 @@
method public abstract byte[] read() throws android.os.RemoteException;
method public abstract void setOemUnlockEnabled(boolean) throws android.os.RemoteException;
method public abstract void wipe() throws android.os.RemoteException;
- method public abstract void wipeIfAllowed(android.os.Bundle, android.app.PendingIntent) throws android.os.RemoteException;
method public abstract int write(byte[]) throws android.os.RemoteException;
}
@@ -30915,14 +30925,7 @@
method public byte[] read();
method public void setOemUnlockEnabled(boolean);
method public void wipe();
- method public void wipeIfAllowed(android.os.Bundle, android.app.PendingIntent);
method public int write(byte[]);
- field public static final java.lang.String ACTION_WIPE_IF_ALLOWED = "android.service.persistentdata.action.WIPE_IF_ALLOWED";
- field public static final java.lang.String EXTRA_WIPE_IF_ALLOWED_CALLBACK = "android.service.persistentdata.extra.WIPE_IF_ALLOWED_CALLBACK";
- field public static final int STATUS_ERROR_NETWORK_ERROR = 2; // 0x2
- field public static final int STATUS_ERROR_NOT_COMPLIANT = 3; // 0x3
- field public static final int STATUS_ERROR_REMOTE_EXCEPTION = 1; // 0x1
- field public static final int STATUS_SUCCESS = 0; // 0x0
}
}
@@ -31046,6 +31049,7 @@
method public void onDestroy();
method public boolean[] onGetSupportedCommands(java.lang.String[]);
method public void onHandleAssist(android.os.Bundle, android.app.assist.AssistStructure, android.app.assist.AssistContent);
+ method public void onHandleScreenshot(android.graphics.Bitmap);
method public void onHide();
method public boolean onKeyDown(int, android.view.KeyEvent);
method public boolean onKeyLongPress(int, android.view.KeyEvent);
@@ -31068,6 +31072,7 @@
method public void startVoiceActivity(android.content.Intent);
field public static final int SHOW_SOURCE_ASSIST_GESTURE = 4; // 0x4
field public static final int SHOW_WITH_ASSIST = 1; // 0x1
+ field public static final int SHOW_WITH_SCREENSHOT = 2; // 0x2
}
public static final class VoiceInteractionSession.AbortVoiceRequest extends android.service.voice.VoiceInteractionSession.Request {
@@ -32840,12 +32845,17 @@
field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
field public static final java.lang.String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
field public static final java.lang.String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
+ field public static final java.lang.String KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY = "cdma_nonroaming_networks_string_array";
+ field public static final java.lang.String KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY = "cdma_roaming_networks_string_array";
field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
field public static final java.lang.String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool";
field public static final java.lang.String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_vibration_bool";
+ field public static final java.lang.String KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY = "gsm_nonroaming_networks_string_array";
+ field public static final java.lang.String KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY = "gsm_roaming_networks_string_array";
field public static final java.lang.String KEY_HAS_IN_CALL_NOISE_SUPPRESSION_BOOL = "has_in_call_noise_suppression_bool";
field public static final java.lang.String KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool";
+ field public static final java.lang.String KEY_HIDE_SIM_LOCK_SETTINGS_BOOL = "hide_sim_lock_settings_bool";
field public static final java.lang.String KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL = "ignore_sim_network_locked_events_bool";
field public static final java.lang.String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
field public static final java.lang.String KEY_MMS_ALIAS_MAX_CHARS_INT = "aliasMaxChars";
@@ -34022,10 +34032,12 @@
method public void revokeUriPermission(android.net.Uri, int);
method public void sendBroadcast(android.content.Intent);
method public void sendBroadcast(android.content.Intent, java.lang.String);
+ method public void sendBroadcast(android.content.Intent, java.lang.String, android.os.Bundle);
method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String);
method public void sendOrderedBroadcast(android.content.Intent, java.lang.String);
method public void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ method public void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.os.Bundle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
method public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
method public void sendStickyBroadcast(android.content.Intent);
method public void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
@@ -39088,6 +39100,8 @@
method public boolean onRequestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
method public boolean onStartNestedScroll(android.view.View, android.view.View, int);
method public void onStopNestedScroll(android.view.View);
+ method public void onViewAdded(android.view.View);
+ method public void onViewRemoved(android.view.View);
method public void recomputeViewAttributes(android.view.View);
method public void removeAllViews();
method public void removeAllViewsInLayout();
@@ -44154,7 +44168,6 @@
method public int getInputType();
method public final android.text.method.KeyListener getKeyListener();
method public final android.text.Layout getLayout();
- method public int[] getLeftIndents();
method public float getLetterSpacing();
method public int getLineBounds(int, android.graphics.Rect);
method public int getLineCount();
@@ -44177,7 +44190,6 @@
method public android.text.TextPaint getPaint();
method public int getPaintFlags();
method public java.lang.String getPrivateImeOptions();
- method public int[] getRightIndents();
method public int getSelectionEnd();
method public int getSelectionStart();
method public int getShadowColor();
@@ -44257,7 +44269,6 @@
method public void setImeActionLabel(java.lang.CharSequence, int);
method public void setImeOptions(int);
method public void setIncludeFontPadding(boolean);
- method public void setIndents(int[], int[]);
method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public void setInputType(int);
method public void setKeyListener(android.text.method.KeyListener);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index bf3b455..69ba27c 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -1002,7 +1002,7 @@
IntentReceiver receiver = new IntentReceiver();
System.out.println("Broadcasting: " + intent);
mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, mReceiverPermission,
- android.app.AppOpsManager.OP_NONE, true, false, mUserId);
+ android.app.AppOpsManager.OP_NONE, null, true, false, mUserId);
receiver.waitForFinish();
}
@@ -1658,7 +1658,7 @@
Intent intent = new Intent(
"com.android.server.task.controllers.IdleController.ACTION_TRIGGER_IDLE");
mAm.broadcastIntent(null, intent, null, null, 0, null, null, null,
- android.app.AppOpsManager.OP_NONE, true, false, UserHandle.USER_ALL);
+ android.app.AppOpsManager.OP_NONE, null, true, false, UserHandle.USER_ALL);
}
private void runScreenCompat() throws Exception {
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 1faf41b..2be44bc 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -1812,7 +1812,7 @@
private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
@Override
public int send(int code, Intent intent, String resolvedType,
- IIntentReceiver finishedReceiver, String requiredPermission) {
+ IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
try {
mResult.offer(intent, 5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 6ae21eb..680feae 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -108,7 +108,7 @@
try {
getDefault().broadcastIntent(
null, intent, null, null, Activity.RESULT_OK, null, null,
- null /*permission*/, appOp, false, true, userId);
+ null /*permission*/, appOp, null, false, true, userId);
} catch (RemoteException ex) {
}
}
@@ -458,12 +458,13 @@
Bundle resultExtras = data.readBundle();
String perm = data.readString();
int appOp = data.readInt();
+ Bundle options = data.readBundle();
boolean serialized = data.readInt() != 0;
boolean sticky = data.readInt() != 0;
int userId = data.readInt();
int res = broadcastIntent(app, intent, resolvedType, resultTo,
resultCode, resultData, resultExtras, perm, appOp,
- serialized, sticky, userId);
+ options, serialized, sticky, userId);
reply.writeNoException();
reply.writeInt(res);
return true;
@@ -2991,9 +2992,9 @@
reply.recycle();
}
public int broadcastIntent(IApplicationThread caller,
- Intent intent, String resolvedType, IIntentReceiver resultTo,
+ Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle map,
- String requiredPermission, int appOp, boolean serialized,
+ String requiredPermission, int appOp, Bundle options, boolean serialized,
boolean sticky, int userId) throws RemoteException
{
Parcel data = Parcel.obtain();
@@ -3008,6 +3009,7 @@
data.writeBundle(map);
data.writeString(requiredPermission);
data.writeInt(appOp);
+ data.writeBundle(options);
data.writeInt(serialized ? 1 : 0);
data.writeInt(sticky ? 1 : 0);
data.writeInt(userId);
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 6fb997e..2406985 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -43,7 +43,7 @@
* A long in the extras delivered by {@link #requestUsageTimeReport} that contains
* the total time (in ms) the user spent in the app flow.
*/
- public static final String EXTRA_USAGE_TIME_REPORT = "android.usage_time";
+ public static final String EXTRA_USAGE_TIME_REPORT = "android.activity.usage_time";
/**
* A Bundle in the extras delivered by {@link #requestUsageTimeReport} that contains
@@ -56,67 +56,67 @@
* The package name that created the options.
* @hide
*/
- public static final String KEY_PACKAGE_NAME = "android:packageName";
+ public static final String KEY_PACKAGE_NAME = "android:activity.packageName";
/**
* Type of animation that arguments specify.
* @hide
*/
- public static final String KEY_ANIM_TYPE = "android:animType";
+ public static final String KEY_ANIM_TYPE = "android:activity.animType";
/**
* Custom enter animation resource ID.
* @hide
*/
- public static final String KEY_ANIM_ENTER_RES_ID = "android:animEnterRes";
+ public static final String KEY_ANIM_ENTER_RES_ID = "android:activity.animEnterRes";
/**
* Custom exit animation resource ID.
* @hide
*/
- public static final String KEY_ANIM_EXIT_RES_ID = "android:animExitRes";
+ public static final String KEY_ANIM_EXIT_RES_ID = "android:activity.animExitRes";
/**
* Custom in-place animation resource ID.
* @hide
*/
- public static final String KEY_ANIM_IN_PLACE_RES_ID = "android:animInPlaceRes";
+ public static final String KEY_ANIM_IN_PLACE_RES_ID = "android:activity.animInPlaceRes";
/**
* Bitmap for thumbnail animation.
* @hide
*/
- public static final String KEY_ANIM_THUMBNAIL = "android:animThumbnail";
+ public static final String KEY_ANIM_THUMBNAIL = "android:activity.animThumbnail";
/**
* Start X position of thumbnail animation.
* @hide
*/
- public static final String KEY_ANIM_START_X = "android:animStartX";
+ public static final String KEY_ANIM_START_X = "android:activity.animStartX";
/**
* Start Y position of thumbnail animation.
* @hide
*/
- public static final String KEY_ANIM_START_Y = "android:animStartY";
+ public static final String KEY_ANIM_START_Y = "android:activity.animStartY";
/**
* Initial width of the animation.
* @hide
*/
- public static final String KEY_ANIM_WIDTH = "android:animWidth";
+ public static final String KEY_ANIM_WIDTH = "android:activity.animWidth";
/**
* Initial height of the animation.
* @hide
*/
- public static final String KEY_ANIM_HEIGHT = "android:animHeight";
+ public static final String KEY_ANIM_HEIGHT = "android:activity.animHeight";
/**
* Callback for when animation is started.
* @hide
*/
- public static final String KEY_ANIM_START_LISTENER = "android:animStartListener";
+ public static final String KEY_ANIM_START_LISTENER = "android:activity.animStartListener";
/**
* For Activity transitions, the calling Activity's TransitionListener used to
@@ -124,15 +124,18 @@
* complete.
*/
private static final String KEY_TRANSITION_COMPLETE_LISTENER
- = "android:transitionCompleteListener";
+ = "android:activity.transitionCompleteListener";
- private static final String KEY_TRANSITION_IS_RETURNING = "android:transitionIsReturning";
- private static final String KEY_TRANSITION_SHARED_ELEMENTS = "android:sharedElementNames";
- private static final String KEY_RESULT_DATA = "android:resultData";
- private static final String KEY_RESULT_CODE = "android:resultCode";
- private static final String KEY_EXIT_COORDINATOR_INDEX = "android:exitCoordinatorIndex";
+ private static final String KEY_TRANSITION_IS_RETURNING
+ = "android:activity.transitionIsReturning";
+ private static final String KEY_TRANSITION_SHARED_ELEMENTS
+ = "android:activity.sharedElementNames";
+ private static final String KEY_RESULT_DATA = "android:activity.resultData";
+ private static final String KEY_RESULT_CODE = "android:activity.resultCode";
+ private static final String KEY_EXIT_COORDINATOR_INDEX
+ = "android:activity.exitCoordinatorIndex";
- private static final String KEY_USAGE_TIME_REPORT = "android:usageTimeReport";
+ private static final String KEY_USAGE_TIME_REPORT = "android:activity.usageTimeReport";
/** @hide */
public static final int ANIM_NONE = 0;
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
new file mode 100644
index 0000000..1f378da
--- /dev/null
+++ b/core/java/android/app/BroadcastOptions.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.annotation.SystemApi;
+import android.os.Bundle;
+
+/**
+ * Helper class for building an options Bundle that can be used with
+ * {@link android.content.Context#sendBroadcast(android.content.Intent)
+ * Context.sendBroadcast(Intent)} and related methods.
+ * {@hide}
+ */
+@SystemApi
+public class BroadcastOptions {
+ private long mTemporaryAppWhitelistDuration;
+
+ /**
+ * How long to temporarily put an app on the power whitelist when executing this broadcast
+ * to it.
+ * @hide
+ */
+ public static final String KEY_TEMPORARY_APP_WHITELIST_DURATION
+ = "android:broadcast.temporaryAppWhitelistDuration";
+
+ public static BroadcastOptions makeBasic() {
+ BroadcastOptions opts = new BroadcastOptions();
+ return opts;
+ }
+
+ private BroadcastOptions() {
+ }
+
+ /** @hide */
+ public BroadcastOptions(Bundle opts) {
+ mTemporaryAppWhitelistDuration = opts.getLong(KEY_TEMPORARY_APP_WHITELIST_DURATION);
+ }
+
+ /**
+ * Set a duration for which the system should temporary place an application on the
+ * power whitelist when this broadcast is being delivered to it.
+ * @param duration The duration in milliseconds; 0 means to not place on whitelist.
+ */
+ public void setTemporaryAppWhitelistDuration(long duration) {
+ mTemporaryAppWhitelistDuration = duration;
+ }
+
+ /**
+ * Return {@link #setTemporaryAppWhitelistDuration}.
+ * @hide
+ */
+ public long getTemporaryAppWhitelistDuration() {
+ return mTemporaryAppWhitelistDuration;
+ }
+
+ /**
+ * Returns the created options as a Bundle, which can be passed to
+ * {@link android.content.Context#sendBroadcast(android.content.Intent)
+ * Context.sendBroadcast(Intent)} and related methods.
+ * Note that the returned Bundle is still owned by the ActivityOptions
+ * object; you must not modify it, but can supply it to the sendBroadcast
+ * methods that take an options Bundle.
+ */
+ public Bundle toBundle() {
+ Bundle b = new Bundle();
+ if (mTemporaryAppWhitelistDuration > 0) {
+ b.putLong(KEY_TEMPORARY_APP_WHITELIST_DURATION, mTemporaryAppWhitelistDuration);
+ }
+ return b.isEmpty() ? null : b;
+ }
+}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index be36af7..0420fb6 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -46,7 +46,6 @@
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
-import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
@@ -676,8 +675,8 @@
+ " Is this really what you want?");
}
mMainThread.getInstrumentation().execStartActivity(
- getOuterContext(), mMainThread.getApplicationThread(), null,
- (Activity)null, intent, -1, options);
+ getOuterContext(), mMainThread.getApplicationThread(), null,
+ (Activity) null, intent, -1, options);
}
/** @hide */
@@ -710,8 +709,8 @@
+ " Is this really what you want?");
}
mMainThread.getInstrumentation().execStartActivitiesAsUser(
- getOuterContext(), mMainThread.getApplicationThread(), null,
- (Activity)null, intents, options, userHandle.getIdentifier());
+ getOuterContext(), mMainThread.getApplicationThread(), null,
+ (Activity) null, intents, options, userHandle.getIdentifier());
}
@Override
@@ -724,8 +723,8 @@
+ " Is this really what you want?");
}
mMainThread.getInstrumentation().execStartActivities(
- getOuterContext(), mMainThread.getApplicationThread(), null,
- (Activity)null, intents, options);
+ getOuterContext(), mMainThread.getApplicationThread(), null,
+ (Activity) null, intents, options);
}
@Override
@@ -766,9 +765,9 @@
try {
intent.prepareToLeaveProcess();
ActivityManagerNative.getDefault().broadcastIntent(
- mMainThread.getApplicationThread(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, false, false,
- getUserId());
+ mMainThread.getApplicationThread(), intent, resolvedType, null,
+ Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
+ getUserId());
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
@@ -781,9 +780,24 @@
try {
intent.prepareToLeaveProcess();
ActivityManagerNative.getDefault().broadcastIntent(
- mMainThread.getApplicationThread(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, receiverPermission, AppOpsManager.OP_NONE,
- false, false, getUserId());
+ mMainThread.getApplicationThread(), intent, resolvedType, null,
+ Activity.RESULT_OK, null, null, receiverPermission, AppOpsManager.OP_NONE,
+ null, false, false, getUserId());
+ } catch (RemoteException e) {
+ throw new RuntimeException("Failure from system", e);
+ }
+ }
+
+ @Override
+ public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
+ warnIfCallingFromSystemProcess();
+ String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
+ try {
+ intent.prepareToLeaveProcess();
+ ActivityManagerNative.getDefault().broadcastIntent(
+ mMainThread.getApplicationThread(), intent, resolvedType, null,
+ Activity.RESULT_OK, null, null, receiverPermission, AppOpsManager.OP_NONE,
+ options, false, false, getUserId());
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
@@ -796,25 +810,24 @@
try {
intent.prepareToLeaveProcess();
ActivityManagerNative.getDefault().broadcastIntent(
- mMainThread.getApplicationThread(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, receiverPermission, appOp, false, false,
- getUserId());
+ mMainThread.getApplicationThread(), intent, resolvedType, null,
+ Activity.RESULT_OK, null, null, receiverPermission, appOp, null, false, false,
+ getUserId());
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
}
@Override
- public void sendOrderedBroadcast(Intent intent,
- String receiverPermission) {
+ public void sendOrderedBroadcast(Intent intent, String receiverPermission) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess();
ActivityManagerNative.getDefault().broadcastIntent(
- mMainThread.getApplicationThread(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, receiverPermission, AppOpsManager.OP_NONE, true, false,
- getUserId());
+ mMainThread.getApplicationThread(), intent, resolvedType, null,
+ Activity.RESULT_OK, null, null, receiverPermission, AppOpsManager.OP_NONE,
+ null, true, false, getUserId());
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
@@ -826,7 +839,16 @@
Handler scheduler, int initialCode, String initialData,
Bundle initialExtras) {
sendOrderedBroadcast(intent, receiverPermission, AppOpsManager.OP_NONE,
- resultReceiver, scheduler, initialCode, initialData, initialExtras);
+ resultReceiver, scheduler, initialCode, initialData, initialExtras, null);
+ }
+
+ @Override
+ public void sendOrderedBroadcast(Intent intent,
+ String receiverPermission, Bundle options, BroadcastReceiver resultReceiver,
+ Handler scheduler, int initialCode, String initialData,
+ Bundle initialExtras) {
+ sendOrderedBroadcast(intent, receiverPermission, AppOpsManager.OP_NONE,
+ resultReceiver, scheduler, initialCode, initialData, initialExtras, options);
}
@Override
@@ -834,6 +856,14 @@
String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData,
Bundle initialExtras) {
+ sendOrderedBroadcast(intent, receiverPermission, appOp,
+ resultReceiver, scheduler, initialCode, initialData, initialExtras, null);
+ }
+
+ void sendOrderedBroadcast(Intent intent,
+ String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
+ Handler scheduler, int initialCode, String initialData,
+ Bundle initialExtras, Bundle options) {
warnIfCallingFromSystemProcess();
IIntentReceiver rd = null;
if (resultReceiver != null) {
@@ -858,7 +888,7 @@
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, rd,
initialCode, initialData, initialExtras, receiverPermission, appOp,
- true, false, getUserId());
+ options, true, false, getUserId());
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
@@ -871,7 +901,7 @@
intent.prepareToLeaveProcess();
ActivityManagerNative.getDefault().broadcastIntent(mMainThread.getApplicationThread(),
intent, resolvedType, null, Activity.RESULT_OK, null, null, null,
- AppOpsManager.OP_NONE, false, false, user.getIdentifier());
+ AppOpsManager.OP_NONE, null, false, false, user.getIdentifier());
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
@@ -891,7 +921,7 @@
intent.prepareToLeaveProcess();
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, receiverPermission, appOp, false, false,
+ Activity.RESULT_OK, null, null, receiverPermission, appOp, null, false, false,
user.getIdentifier());
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
@@ -934,7 +964,7 @@
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, rd,
initialCode, initialData, initialExtras, receiverPermission,
- appOp, true, false, user.getIdentifier());
+ appOp, null, true, false, user.getIdentifier());
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
@@ -949,7 +979,7 @@
intent.prepareToLeaveProcess();
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, false, true,
+ Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, true,
getUserId());
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
@@ -986,7 +1016,7 @@
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, rd,
initialCode, initialData, initialExtras, null,
- AppOpsManager.OP_NONE, true, true, getUserId());
+ AppOpsManager.OP_NONE, null, true, true, getUserId());
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
@@ -1017,7 +1047,7 @@
intent.prepareToLeaveProcess();
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, false, true, user.getIdentifier());
+ Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, true, user.getIdentifier());
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
@@ -1052,7 +1082,7 @@
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, rd,
initialCode, initialData, initialExtras, null,
- AppOpsManager.OP_NONE, true, true, user.getIdentifier());
+ AppOpsManager.OP_NONE, null, true, true, user.getIdentifier());
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 9311e5e..e7f7e13 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -107,7 +107,7 @@
public int broadcastIntent(IApplicationThread caller, Intent intent,
String resolvedType, IIntentReceiver resultTo, int resultCode,
String resultData, Bundle map, String requiredPermission,
- int appOp, boolean serialized, boolean sticky, int userId) throws RemoteException;
+ int appOp, Bundle options, boolean serialized, boolean sticky, int userId) throws RemoteException;
public void unbroadcastIntent(IApplicationThread caller, Intent intent, int userId) throws RemoteException;
public void finishReceiver(IBinder who, int resultCode, String resultData, Bundle map,
boolean abortBroadcast, int flags) throws RemoteException;
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 33a47b24..5a0d246 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1371,6 +1371,9 @@
when = parcel.readLong();
if (parcel.readInt() != 0) {
mSmallIcon = Icon.CREATOR.createFromParcel(parcel);
+ if (mSmallIcon.getType() == Icon.TYPE_RESOURCE) {
+ icon = mSmallIcon.getResId();
+ }
}
number = parcel.readInt();
if (parcel.readInt() != 0) {
@@ -1588,13 +1591,17 @@
}
/**
- * Flatten this notification from a parcel.
+ * Flatten this notification into a parcel.
*/
public void writeToParcel(Parcel parcel, int flags)
{
parcel.writeInt(1);
parcel.writeLong(when);
+ if (mSmallIcon == null && icon != 0) {
+ // you snuck an icon in here without using the builder; let's try to keep it
+ mSmallIcon = Icon.createWithResource("", icon);
+ }
if (mSmallIcon != null) {
parcel.writeInt(1);
mSmallIcon.writeToParcel(parcel, 0);
@@ -2791,7 +2798,10 @@
return this;
}
- private void setFlag(int mask, boolean value) {
+ /**
+ * @hide
+ */
+ public void setFlag(int mask, boolean value) {
if (value) {
mFlags |= mask;
} else {
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 0904e21..605c006 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -25,6 +25,7 @@
import android.content.pm.ParceledListSlice;
import android.graphics.drawable.Icon;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -216,6 +217,12 @@
}
}
fixLegacySmallIcon(notification, pkg);
+ if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
+ if (notification.getSmallIcon() == null) {
+ throw new IllegalArgumentException("Invalid notification (no valid small icon): "
+ + notification);
+ }
+ }
if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
Notification stripped = notification.clone();
Builder.stripForDelivery(stripped);
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 031854a..c42ba65 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -613,7 +613,7 @@
* is no longer allowing more intents to be sent through it.
*/
public void send() throws CanceledException {
- send(null, 0, null, null, null, null);
+ send(null, 0, null, null, null, null, null);
}
/**
@@ -627,7 +627,7 @@
* is no longer allowing more intents to be sent through it.
*/
public void send(int code) throws CanceledException {
- send(null, code, null, null, null, null);
+ send(null, code, null, null, null, null, null);
}
/**
@@ -646,9 +646,9 @@
* @throws CanceledException Throws CanceledException if the PendingIntent
* is no longer allowing more intents to be sent through it.
*/
- public void send(Context context, int code, Intent intent)
+ public void send(Context context, int code, @Nullable Intent intent)
throws CanceledException {
- send(context, code, intent, null, null, null);
+ send(context, code, intent, null, null, null, null);
}
/**
@@ -667,9 +667,9 @@
* @throws CanceledException Throws CanceledException if the PendingIntent
* is no longer allowing more intents to be sent through it.
*/
- public void send(int code, OnFinished onFinished, Handler handler)
+ public void send(int code, @Nullable OnFinished onFinished, @Nullable Handler handler)
throws CanceledException {
- send(null, code, null, onFinished, handler, null);
+ send(null, code, null, onFinished, handler, null, null);
}
/**
@@ -705,9 +705,9 @@
* @throws CanceledException Throws CanceledException if the PendingIntent
* is no longer allowing more intents to be sent through it.
*/
- public void send(Context context, int code, Intent intent,
- OnFinished onFinished, Handler handler) throws CanceledException {
- send(context, code, intent, onFinished, handler, null);
+ public void send(Context context, int code, @Nullable Intent intent,
+ @Nullable OnFinished onFinished, @Nullable Handler handler) throws CanceledException {
+ send(context, code, intent, onFinished, handler, null, null);
}
/**
@@ -748,8 +748,56 @@
* @throws CanceledException Throws CanceledException if the PendingIntent
* is no longer allowing more intents to be sent through it.
*/
- public void send(Context context, int code, Intent intent,
- OnFinished onFinished, Handler handler, String requiredPermission)
+ public void send(Context context, int code, @Nullable Intent intent,
+ @Nullable OnFinished onFinished, @Nullable Handler handler,
+ @Nullable String requiredPermission)
+ throws CanceledException {
+ send(context, code, intent, onFinished, handler, requiredPermission, null);
+ }
+
+ /**
+ * Perform the operation associated with this PendingIntent, allowing the
+ * caller to specify information about the Intent to use and be notified
+ * when the send has completed.
+ *
+ * <p>For the intent parameter, a PendingIntent
+ * often has restrictions on which fields can be supplied here, based on
+ * how the PendingIntent was retrieved in {@link #getActivity},
+ * {@link #getBroadcast}, or {@link #getService}.
+ *
+ * @param context The Context of the caller. This may be null if
+ * <var>intent</var> is also null.
+ * @param code Result code to supply back to the PendingIntent's target.
+ * @param intent Additional Intent data. See {@link Intent#fillIn
+ * Intent.fillIn()} for information on how this is applied to the
+ * original Intent. Use null to not modify the original Intent.
+ * If flag {@link #FLAG_IMMUTABLE} was set when this pending intent was
+ * created, this argument will be ignored.
+ * @param onFinished The object to call back on when the send has
+ * completed, or null for no callback.
+ * @param handler Handler identifying the thread on which the callback
+ * should happen. If null, the callback will happen from the thread
+ * pool of the process.
+ * @param requiredPermission Name of permission that a recipient of the PendingIntent
+ * is required to hold. This is only valid for broadcast intents, and
+ * corresponds to the permission argument in
+ * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}.
+ * If null, no permission is required.
+ * @param options Additional options the caller would like to provide to modify the sending
+ * behavior. May be built from an {@link ActivityOptions} to apply to an activity start.
+ *
+ * @see #send()
+ * @see #send(int)
+ * @see #send(Context, int, Intent)
+ * @see #send(int, android.app.PendingIntent.OnFinished, Handler)
+ * @see #send(Context, int, Intent, OnFinished, Handler)
+ *
+ * @throws CanceledException Throws CanceledException if the PendingIntent
+ * is no longer allowing more intents to be sent through it.
+ */
+ public void send(Context context, int code, @Nullable Intent intent,
+ @Nullable OnFinished onFinished, @Nullable Handler handler,
+ @Nullable String requiredPermission, @Nullable Bundle options)
throws CanceledException {
try {
String resolvedType = intent != null ?
@@ -759,7 +807,7 @@
onFinished != null
? new FinishedDispatcher(this, onFinished, handler)
: null,
- requiredPermission);
+ requiredPermission, options);
if (res < 0) {
throw new CanceledException();
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index ed20086..b9862ca 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -552,19 +552,6 @@
= "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_SIGNATURE_CHECKSUM";
/**
- * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that
- * holds data needed by the system to wipe factory reset protection. The data needed to wipe
- * the device depend on the installed factory reset protection implementation. For example,
- * if an account is needed to unlock a device, this extra may contain data used to
- * authenticate that account.
- *
- * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
- * provisioning via an NFC bump.
- */
- public static final String EXTRA_PROVISIONING_RESET_PROTECTION_PARAMETERS
- = "android.app.extra.PROVISIONING_RESET_PROTECTION_PARAMETERS";
-
- /**
* This MIME type is used for starting the Device Owner provisioning that does not require
* provisioning features introduced in Android API level
* {@link android.os.Build.VERSION_CODES#MNC} or later levels.
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 1205708..278c9d6 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -20,6 +20,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ParceledListSlice;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Process;
@@ -753,16 +754,16 @@
}
try {
- List<AppWidgetProviderInfo> providers = mService.getInstalledProvidersForProfile(
+ ParceledListSlice<AppWidgetProviderInfo> providers = mService.getInstalledProvidersForProfile(
categoryFilter, profile.getIdentifier());
if (providers == null) {
return Collections.emptyList();
}
- for (AppWidgetProviderInfo info : providers) {
+ for (AppWidgetProviderInfo info : providers.getList()) {
// Converting complex to dp.
convertSizesToPixels(info);
}
- return providers;
+ return providers.getList();
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 83ce087..675515b 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1517,6 +1517,38 @@
@Nullable String receiverPermission);
/**
+ * Broadcast the given intent to all interested BroadcastReceivers, allowing
+ * an optional required permission to be enforced. This
+ * call is asynchronous; it returns immediately, and you will continue
+ * executing while the receivers are run. No results are propagated from
+ * receivers and receivers can not abort the broadcast. If you want
+ * to allow receivers to propagate results or abort the broadcast, you must
+ * send an ordered broadcast using
+ * {@link #sendOrderedBroadcast(Intent, String)}.
+ *
+ * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
+ *
+ * @param intent The Intent to broadcast; all receivers matching this
+ * Intent will receive the broadcast.
+ * @param receiverPermission (optional) String naming a permission that
+ * a receiver must hold in order to receive your broadcast.
+ * If null, no permission is required.
+ * @param options (optional) Additional sending options, generated from a
+ * {@link android.app.BroadcastOptions}.
+ *
+ * @see android.content.BroadcastReceiver
+ * @see #registerReceiver
+ * @see #sendBroadcast(Intent)
+ * @see #sendOrderedBroadcast(Intent, String)
+ * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
+ * @hide
+ */
+ @SystemApi
+ public abstract void sendBroadcast(Intent intent,
+ @Nullable String receiverPermission,
+ @Nullable Bundle options);
+
+ /**
* Like {@link #sendBroadcast(Intent, String)}, but also allows specification
* of an associated app op as per {@link android.app.AppOpsManager}.
* @hide
@@ -1588,11 +1620,60 @@
* @see android.app.Activity#RESULT_OK
*/
public abstract void sendOrderedBroadcast(@NonNull Intent intent,
- @Nullable String receiverPermission, BroadcastReceiver resultReceiver,
+ @Nullable String receiverPermission, @Nullable BroadcastReceiver resultReceiver,
@Nullable Handler scheduler, int initialCode, @Nullable String initialData,
@Nullable Bundle initialExtras);
/**
+ * Version of {@link #sendBroadcast(Intent)} that allows you to
+ * receive data back from the broadcast. This is accomplished by
+ * supplying your own BroadcastReceiver when calling, which will be
+ * treated as a final receiver at the end of the broadcast -- its
+ * {@link BroadcastReceiver#onReceive} method will be called with
+ * the result values collected from the other receivers. The broadcast will
+ * be serialized in the same way as calling
+ * {@link #sendOrderedBroadcast(Intent, String)}.
+ *
+ * <p>Like {@link #sendBroadcast(Intent)}, this method is
+ * asynchronous; it will return before
+ * resultReceiver.onReceive() is called.
+ *
+ * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
+ *
+ *
+ * @param intent The Intent to broadcast; all receivers matching this
+ * Intent will receive the broadcast.
+ * @param receiverPermission String naming a permissions that
+ * a receiver must hold in order to receive your broadcast.
+ * If null, no permission is required.
+ * @param options (optional) Additional sending options, generated from a
+ * {@link android.app.BroadcastOptions}.
+ * @param resultReceiver Your own BroadcastReceiver to treat as the final
+ * receiver of the broadcast.
+ * @param scheduler A custom Handler with which to schedule the
+ * resultReceiver callback; if null it will be
+ * scheduled in the Context's main thread.
+ * @param initialCode An initial value for the result code. Often
+ * Activity.RESULT_OK.
+ * @param initialData An initial value for the result data. Often
+ * null.
+ * @param initialExtras An initial value for the result extras. Often
+ * null.
+ * @see #sendBroadcast(Intent)
+ * @see #sendBroadcast(Intent, String)
+ * @see #sendOrderedBroadcast(Intent, String)
+ * @see android.content.BroadcastReceiver
+ * @see #registerReceiver
+ * @see android.app.Activity#RESULT_OK
+ * @hide
+ */
+ @SystemApi
+ public abstract void sendOrderedBroadcast(@NonNull Intent intent,
+ @Nullable String receiverPermission, @Nullable Bundle options,
+ @Nullable BroadcastReceiver resultReceiver, @Nullable Handler scheduler,
+ int initialCode, @Nullable String initialData, @Nullable Bundle initialExtras);
+
+ /**
* Like {@link #sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler,
* int, String, android.os.Bundle)}, but also allows specification
* of an associated app op as per {@link android.app.AppOpsManager}.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index fb9e194..4e7c832 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -16,6 +16,7 @@
package android.content;
+import android.annotation.SystemApi;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
@@ -401,6 +402,13 @@
}
/** @hide */
+ @SystemApi
+ @Override
+ public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
+ mBase.sendBroadcast(intent, receiverPermission, options);
+ }
+
+ /** @hide */
@Override
public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
mBase.sendBroadcast(intent, receiverPermission, appOp);
@@ -423,6 +431,18 @@
}
/** @hide */
+ @SystemApi
+ @Override
+ public void sendOrderedBroadcast(
+ Intent intent, String receiverPermission, Bundle options, BroadcastReceiver resultReceiver,
+ Handler scheduler, int initialCode, String initialData,
+ Bundle initialExtras) {
+ mBase.sendOrderedBroadcast(intent, receiverPermission,
+ options, resultReceiver, scheduler, initialCode,
+ initialData, initialExtras);
+ }
+
+ /** @hide */
@Override
public void sendOrderedBroadcast(
Intent intent, String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
diff --git a/core/java/android/content/IIntentSender.aidl b/core/java/android/content/IIntentSender.aidl
index 7dbd6f2..f3affa7 100644
--- a/core/java/android/content/IIntentSender.aidl
+++ b/core/java/android/content/IIntentSender.aidl
@@ -18,9 +18,10 @@
import android.content.IIntentReceiver;
import android.content.Intent;
+import android.os.Bundle;
/** @hide */
interface IIntentSender {
int send(int code, in Intent intent, String resolvedType,
- IIntentReceiver finishedReceiver, String requiredPermission);
+ IIntentReceiver finishedReceiver, String requiredPermission, in Bundle options);
}
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index 166495b..13a767e 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -195,7 +195,7 @@
onFinished != null
? new FinishedDispatcher(this, onFinished, handler)
: null,
- requiredPermission);
+ requiredPermission, null);
if (res < 0) {
throw new SendIntentException();
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index bd50ca0..dd1c5c2 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2900,7 +2900,7 @@
*
* @return A List<ResolveInfo> containing one entry for each matching
* Receiver. These are ordered from first to last in priority. If
- * there are no matching receivers, an empty list is returned.
+ * there are no matching receivers, an empty list or {@code null} is returned.
*
* @see #MATCH_DEFAULT_ONLY
* @see #GET_INTENT_FILTERS
@@ -2936,7 +2936,7 @@
* ServiceInfo. These are ordered from best to worst match -- that
* is, the first item in the list is what is returned by
* resolveService(). If there are no matching services, an empty
- * list is returned.
+ * list or {@code null} is returned.
*
* @see #GET_INTENT_FILTERS
* @see #GET_RESOLVED_FILTER
@@ -2955,7 +2955,7 @@
* ServiceInfo. These are ordered from best to worst match -- that
* is, the first item in the list is what is returned by
* resolveService(). If there are no matching services, an empty
- * list is returned.
+ * list or {@code null} is returned.
*
* @see #GET_INTENT_FILTERS
* @see #GET_RESOLVED_FILTER
@@ -2977,7 +2977,7 @@
* @param flags Additional option flags.
* @return A List<ResolveInfo> containing one entry for each matching
* ProviderInfo. These are ordered from best to worst match. If
- * there are no matching providers, an empty list is returned.
+ * there are no matching providers, an empty list or {@code null} is returned.
* @see #GET_INTENT_FILTERS
* @see #GET_RESOLVED_FILTER
*/
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index a1ebe6a..83128c3 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -537,12 +537,16 @@
CameraAccessException pendingException = null;
Surface input = null;
try {
- // configure streams and then block until IDLE
+ // configure streams and then block until IDLE
configureSuccess = configureStreamsChecked(inputConfig, outputConfigurations,
isConstrainedHighSpeed);
- if (inputConfig != null) {
+ if (configureSuccess == true && inputConfig != null) {
input = new Surface();
- mRemoteDevice.getInputSurface(/*out*/input);
+ try {
+ mRemoteDevice.getInputSurface(/*out*/input);
+ } catch (CameraRuntimeException e) {
+ e.asChecked();
+ }
}
} catch (CameraAccessException e) {
configureSuccess = false;
@@ -2049,6 +2053,8 @@
// Prepare the Request builders: need carry over the request controls.
// First, create a request builder that will only include preview or recording target.
CameraMetadataNative requestMetadata = new CameraMetadataNative(request.getNativeCopy());
+ // Note that after this step, the requestMetadata is mutated (swapped) and can not be used
+ // for next request builder creation.
CaptureRequest.Builder singleTargetRequestBuilder = new CaptureRequest.Builder(
requestMetadata, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE);
@@ -2069,6 +2075,9 @@
// Second, Create a request builder that will include both preview and recording targets.
CaptureRequest.Builder doubleTargetRequestBuilder = null;
if (outputSurfaces.size() == 2) {
+ // Have to create a new copy, the original one was mutated after a new
+ // CaptureRequest.Builder creation.
+ requestMetadata = new CameraMetadataNative(request.getNativeCopy());
doubleTargetRequestBuilder = new CaptureRequest.Builder(
requestMetadata, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE);
doubleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT,
diff --git a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
index d461bca..1aee794 100644
--- a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
+++ b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
@@ -138,8 +138,8 @@
* errors, then add them to the top switch statement
*/
if (errorFlag < 0) {
- throw new UnsupportedOperationException(String.format("Unknown error %d",
- errorFlag));
+ throw new CameraRuntimeException(CAMERA_ERROR,
+ String.format("Unknown camera device error %d", errorFlag));
}
}
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index ecc3fb4..3f40484 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -61,6 +61,17 @@
public static final int FIREWALL_RULE_ALLOW = 1;
public static final int FIREWALL_RULE_DENY = 2;
+ public static final int FIREWALL_TYPE_WHITELIST = 0;
+ public static final int FIREWALL_TYPE_BLACKLIST = 1;
+
+ public static final int FIREWALL_CHAIN_NONE = 0;
+ public static final int FIREWALL_CHAIN_DOZABLE = 1;
+ public static final int FIREWALL_CHAIN_STANDBY = 2;
+
+ public static final String FIREWALL_CHAIN_NAME_NONE = "none";
+ public static final String FIREWALL_CHAIN_NAME_DOZABLE = "dozable";
+ public static final String FIREWALL_CHAIN_NAME_STANDBY = "standby";
+
private static final boolean ALLOW_PLATFORM_APP_POLICY = true;
/**
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index d165240..eb6e1c2 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1165,25 +1165,23 @@
public static final int EVENT_USER_FOREGROUND = 0x0008;
// Event for connectivity changed.
public static final int EVENT_CONNECTIVITY_CHANGED = 0x0009;
- // Event for significant motion taking us out of idle mode.
- public static final int EVENT_SIGNIFICANT_MOTION = 0x000a;
// Event for becoming active taking us out of idle mode.
- public static final int EVENT_ACTIVE = 0x000b;
+ public static final int EVENT_ACTIVE = 0x000a;
// Event for a package being installed.
- public static final int EVENT_PACKAGE_INSTALLED = 0x000c;
+ public static final int EVENT_PACKAGE_INSTALLED = 0x000b;
// Event for a package being uninstalled.
- public static final int EVENT_PACKAGE_UNINSTALLED = 0x000d;
+ public static final int EVENT_PACKAGE_UNINSTALLED = 0x000c;
// Event for a package being uninstalled.
- public static final int EVENT_ALARM = 0x000e;
+ public static final int EVENT_ALARM = 0x000d;
// Record that we have decided we need to collect new stats data.
- public static final int EVENT_COLLECT_EXTERNAL_STATS = 0x000f;
+ public static final int EVENT_COLLECT_EXTERNAL_STATS = 0x000e;
// Event for a package becoming inactive due to being unused for a period of time.
- public static final int EVENT_PACKAGE_INACTIVE = 0x0010;
+ public static final int EVENT_PACKAGE_INACTIVE = 0x000f;
// Event for a package becoming active due to an interaction.
- public static final int EVENT_PACKAGE_ACTIVE = 0x0011;
+ public static final int EVENT_PACKAGE_ACTIVE = 0x0010;
// Number of event types.
- public static final int EVENT_COUNT = 0x0012;
+ public static final int EVENT_COUNT = 0x0011;
// Mask to extract out only the type part of the event.
public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH);
@@ -1840,12 +1838,12 @@
public static final String[] HISTORY_EVENT_NAMES = new String[] {
"null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn",
- "motion", "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active"
+ "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active"
};
public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
"Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn",
- "Esm", "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa"
+ "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa"
};
/**
@@ -4017,8 +4015,10 @@
if (userCpuTimeUs > 0 || systemCpuTimeUs > 0) {
sb.setLength(0);
sb.append(prefix);
- sb.append(" Total cpu time: ");
- formatTimeMs(sb, (userCpuTimeUs + systemCpuTimeUs) / 1000);
+ sb.append(" Total cpu time: u=");
+ formatTimeMs(sb, userCpuTimeUs / 1000);
+ sb.append("s=");
+ formatTimeMs(sb, systemCpuTimeUs / 1000);
pw.println(sb.toString());
}
diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl
index 268295d..fe4aa13 100644
--- a/core/java/android/os/IDeviceIdleController.aidl
+++ b/core/java/android/os/IDeviceIdleController.aidl
@@ -28,4 +28,5 @@
int[] getAppIdTempWhitelist();
boolean isPowerSaveWhitelistApp(String name);
void addPowerSaveTempWhitelistApp(String name, long duration, int userId);
+ void exitIdle(String reason);
}
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index b29e8d0..8114155 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -342,7 +342,9 @@
void setFirewallInterfaceRule(String iface, boolean allow);
void setFirewallEgressSourceRule(String addr, boolean allow);
void setFirewallEgressDestRule(String addr, int port, boolean allow);
- void setFirewallUidRule(int uid, int rule);
+ void setFirewallUidRule(int chain, int uid, int rule);
+ void setFirewallUidRules(int chain, in int[] uids, in int[] rules);
+ void setFirewallChainEnabled(int chain, boolean enable);
/**
* Set all packets from users in ranges to go through VPN specified by netId.
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 30535ff..c7ba607 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -107,6 +107,11 @@
*/
public static final String EXTRA_ORIENTATION = "android.content.extra.ORIENTATION";
+ /**
+ * Overrides the default prompt text in DocumentsUI when set in an intent.
+ */
+ public static final String EXTRA_PROMPT = "android.provider.extra.PROMPT";
+
/** {@hide} */
public static final String ACTION_MANAGE_ROOT = "android.provider.action.MANAGE_ROOT";
/** {@hide} */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 3e9c9de..56cd1a7 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7133,6 +7133,29 @@
public static final String APP_IDLE_CONSTANTS = "app_idle_constants";
/**
+ * Alarm manager specific settings.
+ * This is encoded as a key=value list, separated by commas. Ex:
+ *
+ * "min_futurity=5000,allow_while_idle_short_time=4500"
+ *
+ * The following keys are supported:
+ *
+ * <pre>
+ * min_futurity (long)
+ * min_interval (long)
+ * allow_while_idle_short_time (long)
+ * allow_while_idle_long_time (long)
+ * allow_while_idle_whitelist_duration (long)
+ * </pre>
+ *
+ * <p>
+ * Type: string
+ * @hide
+ * @see com.android.server.AlarmManagerService.Constants
+ */
+ public static final String ALARM_MANAGER_CONSTANTS = "alarm_manager_constants";
+
+ /**
* Get the key that retrieves a bluetooth headset's priority.
* @hide
*/
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 6e40c6c..e4fab12 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -81,9 +81,8 @@
public static final int KM_TAG_ASSOCIATED_DATA = KM_BYTES | 1000;
public static final int KM_TAG_NONCE = KM_BYTES | 1001;
- public static final int KM_TAG_AEAD_TAG = KM_BYTES | 1002;
- public static final int KM_TAG_AUTH_TOKEN = KM_BYTES | 1003;
- public static final int KM_TAG_MAC_LENGTH = KM_INT | 1004;
+ public static final int KM_TAG_AUTH_TOKEN = KM_BYTES | 1002;
+ public static final int KM_TAG_MAC_LENGTH = KM_INT | 1003;
// Algorithm values.
public static final int KM_ALGORITHM_RSA = 1;
diff --git a/core/java/android/security/keymaster/OperationResult.java b/core/java/android/security/keymaster/OperationResult.java
index 911a05a..30659662 100644
--- a/core/java/android/security/keymaster/OperationResult.java
+++ b/core/java/android/security/keymaster/OperationResult.java
@@ -35,15 +35,28 @@
public static final Parcelable.Creator<OperationResult> CREATOR = new
Parcelable.Creator<OperationResult>() {
+ @Override
public OperationResult createFromParcel(Parcel in) {
return new OperationResult(in);
}
+ @Override
public OperationResult[] newArray(int length) {
return new OperationResult[length];
}
};
+ public OperationResult(
+ int resultCode, IBinder token, long operationHandle, int inputConsumed, byte[] output,
+ KeymasterArguments outParams) {
+ this.resultCode = resultCode;
+ this.token = token;
+ this.operationHandle = operationHandle;
+ this.inputConsumed = inputConsumed;
+ this.output = output;
+ this.outParams = outParams;
+ }
+
protected OperationResult(Parcel in) {
resultCode = in.readInt();
token = in.readStrongBinder();
diff --git a/core/java/android/service/persistentdata/IPersistentDataBlockService.aidl b/core/java/android/service/persistentdata/IPersistentDataBlockService.aidl
index 0071a33..52db223 100644
--- a/core/java/android/service/persistentdata/IPersistentDataBlockService.aidl
+++ b/core/java/android/service/persistentdata/IPersistentDataBlockService.aidl
@@ -16,8 +16,6 @@
package android.service.persistentdata;
-import android.app.PendingIntent;
-import android.os.Bundle;
import android.os.ParcelFileDescriptor;
/**
@@ -32,7 +30,6 @@
int write(in byte[] data);
byte[] read();
void wipe();
- void wipeIfAllowed(in Bundle bundle, in PendingIntent pi);
int getDataBlockSize();
long getMaximumDataBlockSize();
diff --git a/core/java/android/service/persistentdata/PersistentDataBlockManager.java b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
index 31570c6..0ffdf68 100644
--- a/core/java/android/service/persistentdata/PersistentDataBlockManager.java
+++ b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
@@ -17,8 +17,6 @@
package android.service.persistentdata;
import android.annotation.SystemApi;
-import android.app.PendingIntent;
-import android.os.Bundle;
import android.os.RemoteException;
import android.util.Slog;
@@ -43,56 +41,6 @@
@SystemApi
public class PersistentDataBlockManager {
private static final String TAG = PersistentDataBlockManager.class.getSimpleName();
-
- /**
- * Broadcast action that will be called when the {@link #wipeIfAllowed(Bundle,PendingIntent)}
- * method is called. A broadcast with this action will be sent to the package allowed to write
- * to the persistent data block. Packages receiving this broadcasts should respond by using the
- * {@link android.app.PendingIntent} sent in the {@link #EXTRA_WIPE_IF_ALLOWED_CALLBACK} extra.
- */
- public static final String ACTION_WIPE_IF_ALLOWED
- = "android.service.persistentdata.action.WIPE_IF_ALLOWED";
-
- /**
- * A {@link android.os.Parcelable} extra of type {@link android.app.PendingIntent} used to
- * response to {@link #wipeIfAllowed(Bundle,PendingIntent)}. This extra will set in broadcasts
- * with an action of {@link #ACTION_WIPE_IF_ALLOWED}.
- */
- public static final String EXTRA_WIPE_IF_ALLOWED_CALLBACK
- = "android.service.persistentdata.extra.WIPE_IF_ALLOWED_CALLBACK";
-
- /**
- * Result code indicating that the data block was wiped.
- *
- * <p>This value is set as result code of the {@link android.app.PendingIntent} argument to
- * {@link #wipeIfAllowed(Bundle,PendingIntent)}
- */
- public static final int STATUS_SUCCESS = 0;
-
- /**
- * Result code indicating that a remote exception was received while processing the request.
- *
- * <p>This value is set as result code of the {@link android.app.PendingIntent} argument to
- * {@link #wipeIfAllowed(Bundle,PendingIntent)}
- */
- public static final int STATUS_ERROR_REMOTE_EXCEPTION = 1;
-
- /**
- * Result code indicating that a network error occurred while processing the request.
- *
- * <p>This value is set as result code of the {@link android.app.PendingIntent} argument to
- * {@link #wipeIfAllowed(Bundle,PendingIntent)}
- */
- public static final int STATUS_ERROR_NETWORK_ERROR = 2;
-
- /**
- * Result code indicating that the data block could not be cleared with the provided data.
- *
- * <p>This value is set as result code of the {@link android.app.PendingIntent} argument to
- * {@link #wipeIfAllowed(Bundle,PendingIntent)}
- */
- public static final int STATUS_ERROR_NOT_COMPLIANT = 3;
-
private IPersistentDataBlockService sService;
public PersistentDataBlockManager(IPersistentDataBlockService service) {
@@ -170,28 +118,6 @@
}
/**
- * Attempt to wipe the data block by sending a broadcast to the package allowed to modify the
- * datablock. The allowed package can refuse to wipe the data block based on the contents of
- * the specified bundle. This bundle may contain data used by the allowed package to wipe the
- * partition such as account credentials or an authorization token.
- * @param bundle data used to wipe the data block. The contents of this bundle depend on the
- * allowed package receiving the data.
- * @param pi intent called when attempt finished. The result code of this intent will be set
- * to one of {@link #STATUS_SUCCESS}, {@link #STATUS_ERROR_REMOTE_EXCEPTION},
- * {@link #STATUS_ERROR_NETWORK_ERROR}, or {@link #STATUS_ERROR_NOT_COMPLIANT}.
- */
- public void wipeIfAllowed(Bundle bundle, PendingIntent pi) {
- if (pi == null) {
- throw new NullPointerException();
- }
- try {
- sService.wipeIfAllowed(bundle, pi);
- } catch (RemoteException e) {
- onError("wiping persistent partition");
- }
- }
-
- /**
* Writes a byte enabling or disabling the ability to "OEM unlock" the device.
*/
public void setOemUnlockEnabled(boolean enabled) {
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index d5ee7e7..39dd29b 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -80,7 +80,6 @@
public static final int SHOW_WITH_ASSIST = 1<<0;
/**
- * @hide
* Flag received in {@link #onShow}: originator requested that the session be started with
* a screen shot of the currently focused activity.
*/
@@ -1098,7 +1097,8 @@
WindowManager.LayoutParams.TYPE_VOICE_INTERACTION, Gravity.BOTTOM, true);
mWindow.getWindow().addFlags(
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED |
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
+ WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
initViews();
mWindow.getWindow().setLayout(MATCH_PARENT, MATCH_PARENT);
mWindow.setToken(mToken);
@@ -1143,7 +1143,7 @@
mContentFrame.addView(view, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
-
+ mContentFrame.requestApplyInsets();
}
/** @hide */
@@ -1162,7 +1162,6 @@
onHandleAssist(data);
}
- /** @hide */
public void onHandleScreenshot(Bitmap screenshot) {
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 73cfd8c..2e2ba88 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -4148,24 +4148,38 @@
mOnHierarchyChangeListener = listener;
}
- /**
- * @hide
- */
- protected void onViewAdded(View child) {
+ void dispatchViewAdded(View child) {
+ onViewAdded(child);
if (mOnHierarchyChangeListener != null) {
mOnHierarchyChangeListener.onChildViewAdded(this, child);
}
}
/**
- * @hide
+ * Called when a new child is added to this ViewGroup. Overrides should always
+ * call super.onViewAdded.
+ *
+ * @param child the added child view
*/
- protected void onViewRemoved(View child) {
+ public void onViewAdded(View child) {
+ }
+
+ void dispatchViewRemoved(View child) {
+ onViewRemoved(child);
if (mOnHierarchyChangeListener != null) {
mOnHierarchyChangeListener.onChildViewRemoved(this, child);
}
}
+ /**
+ * Called when a child view is removed from this ViewGroup. Overrides should always
+ * call super.onViewRemoved.
+ *
+ * @param child the removed child view
+ */
+ public void onViewRemoved(View child) {
+ }
+
private void clearCachedLayoutMode() {
if (!hasBooleanFlag(FLAG_LAYOUT_MODE_WAS_EXPLICITLY_SET)) {
mLayoutMode = LAYOUT_MODE_UNDEFINED;
@@ -4292,7 +4306,7 @@
child.resetRtlProperties();
}
- onViewAdded(child);
+ dispatchViewAdded(child);
if ((child.mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE) {
mGroupFlags |= FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE;
@@ -4554,7 +4568,7 @@
}
}
- onViewRemoved(view);
+ dispatchViewRemoved(view);
if (view.getVisibility() != View.GONE) {
notifySubtreeAccessibilityStateChangedIfNeeded();
@@ -4646,7 +4660,7 @@
needGlobalAttributesUpdate(false);
- onViewRemoved(view);
+ dispatchViewRemoved(view);
}
removeFromArray(start, count);
@@ -4729,7 +4743,7 @@
childHasTransientStateChanged(view, false);
}
- onViewRemoved(view);
+ dispatchViewRemoved(view);
view.mParent = null;
children[i] = null;
@@ -4788,7 +4802,7 @@
childHasTransientStateChanged(child, false);
}
- onViewRemoved(child);
+ dispatchViewRemoved(child);
}
/**
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index db78ec5..b49cbc6 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -186,7 +186,9 @@
if (DEBUG) {
Log.i(LOG_TAG, "Window cache miss");
}
+ final long identityToken = Binder.clearCallingIdentity();
window = connection.getWindow(accessibilityWindowId);
+ Binder.restoreCallingIdentity(identityToken);
if (window != null) {
sAccessibilityCache.addWindow(window);
return window;
@@ -222,7 +224,9 @@
if (DEBUG) {
Log.i(LOG_TAG, "Windows cache miss");
}
+ final long identityToken = Binder.clearCallingIdentity();
windows = connection.getWindows();
+ Binder.restoreCallingIdentity(identityToken);
if (windows != null) {
final int windowCount = windows.size();
for (int i = 0; i < windowCount; i++) {
@@ -282,9 +286,11 @@
}
}
final int interactionId = mInteractionIdCounter.getAndIncrement();
+ final long identityToken = Binder.clearCallingIdentity();
final boolean success = connection.findAccessibilityNodeInfoByAccessibilityId(
accessibilityWindowId, accessibilityNodeId, interactionId, this,
prefetchFlags, Thread.currentThread().getId());
+ Binder.restoreCallingIdentity(identityToken);
// If the scale is zero the call has failed.
if (success) {
List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
@@ -328,9 +334,11 @@
IAccessibilityServiceConnection connection = getConnection(connectionId);
if (connection != null) {
final int interactionId = mInteractionIdCounter.getAndIncrement();
+ final long identityToken = Binder.clearCallingIdentity();
final boolean success = connection.findAccessibilityNodeInfosByViewId(
accessibilityWindowId, accessibilityNodeId, viewId, interactionId, this,
Thread.currentThread().getId());
+ Binder.restoreCallingIdentity(identityToken);
if (success) {
List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
interactionId);
@@ -374,9 +382,11 @@
IAccessibilityServiceConnection connection = getConnection(connectionId);
if (connection != null) {
final int interactionId = mInteractionIdCounter.getAndIncrement();
+ final long identityToken = Binder.clearCallingIdentity();
final boolean success = connection.findAccessibilityNodeInfosByText(
accessibilityWindowId, accessibilityNodeId, text, interactionId, this,
Thread.currentThread().getId());
+ Binder.restoreCallingIdentity(identityToken);
if (success) {
List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
interactionId);
@@ -419,9 +429,11 @@
IAccessibilityServiceConnection connection = getConnection(connectionId);
if (connection != null) {
final int interactionId = mInteractionIdCounter.getAndIncrement();
+ final long identityToken = Binder.clearCallingIdentity();
final boolean success = connection.findFocus(accessibilityWindowId,
accessibilityNodeId, focusType, interactionId, this,
Thread.currentThread().getId());
+ Binder.restoreCallingIdentity(identityToken);
if (success) {
AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
interactionId);
@@ -461,9 +473,11 @@
IAccessibilityServiceConnection connection = getConnection(connectionId);
if (connection != null) {
final int interactionId = mInteractionIdCounter.getAndIncrement();
+ final long identityToken = Binder.clearCallingIdentity();
final boolean success = connection.focusSearch(accessibilityWindowId,
accessibilityNodeId, direction, interactionId, this,
Thread.currentThread().getId());
+ Binder.restoreCallingIdentity(identityToken);
if (success) {
AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
interactionId);
@@ -502,9 +516,11 @@
IAccessibilityServiceConnection connection = getConnection(connectionId);
if (connection != null) {
final int interactionId = mInteractionIdCounter.getAndIncrement();
+ final long identityToken = Binder.clearCallingIdentity();
final boolean success = connection.performAccessibilityAction(
accessibilityWindowId, accessibilityNodeId, action, arguments,
interactionId, this, Thread.currentThread().getId());
+ Binder.restoreCallingIdentity(identityToken);
if (success) {
return getPerformAccessibilityActionResultAndClear(interactionId);
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 0001860..a96bf71 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -3113,9 +3113,7 @@
}
private boolean performStylusButtonPressAction(MotionEvent ev) {
- if (ev.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS
- && ev.isButtonPressed(MotionEvent.BUTTON_SECONDARY)
- && mChoiceMode == CHOICE_MODE_MULTIPLE_MODAL && mChoiceActionMode == null) {
+ if (mChoiceMode == CHOICE_MODE_MULTIPLE_MODAL && mChoiceActionMode == null) {
final View child = getChildAt(mMotionPosition - mFirstPosition);
if (child != null) {
final int longPressPosition = mMotionPosition;
@@ -3785,7 +3783,7 @@
}
if (mTouchMode == TOUCH_MODE_DOWN && mMotionPosition != INVALID_POSITION
- && (performButtonActionOnTouchDown(ev) || performStylusButtonPressAction(ev))) {
+ && performButtonActionOnTouchDown(ev)) {
removeCallbacks(mPendingCheckForTap);
}
}
@@ -3828,11 +3826,6 @@
mTouchMode = TOUCH_MODE_DONE_WAITING;
updateSelectorState();
} else if (motionView != null) {
- if (performStylusButtonPressAction(ev)) {
- removeCallbacks(mPendingCheckForTap);
- removeCallbacks(mPendingCheckForLongPress);
- }
-
// Still within bounds, update the hotspot.
final float[] point = mTmpPoint;
point[0] = x;
@@ -4072,7 +4065,7 @@
public boolean onGenericMotionEvent(MotionEvent event) {
if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
switch (event.getAction()) {
- case MotionEvent.ACTION_SCROLL: {
+ case MotionEvent.ACTION_SCROLL:
if (mTouchMode == TOUCH_MODE_REST) {
final float vscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
if (vscroll != 0) {
@@ -4082,9 +4075,22 @@
}
}
}
- }
+ break;
+
+ case MotionEvent.ACTION_BUTTON_PRESS:
+ int actionButton = event.getActionButton();
+ if ((actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
+ || actionButton == MotionEvent.BUTTON_SECONDARY)
+ && (mTouchMode == TOUCH_MODE_DOWN || mTouchMode == TOUCH_MODE_TAP)) {
+ if (performStylusButtonPressAction(event)) {
+ removeCallbacks(mPendingCheckForLongPress);
+ removeCallbacks(mPendingCheckForTap);
+ }
+ }
+ break;
}
}
+
return super.onGenericMotionEvent(event);
}
@@ -6575,13 +6581,14 @@
* @return A view from the ScrapViews collection. These are unordered.
*/
View getScrapView(int position) {
+ final int whichScrap = mAdapter.getItemViewType(position);
+ if (whichScrap < 0) {
+ return null;
+ }
if (mViewTypeCount == 1) {
return retrieveFromScrap(mCurrentScrap, position);
- } else {
- final int whichScrap = mAdapter.getItemViewType(position);
- if (whichScrap >= 0 && whichScrap < mScrapViews.length) {
- return retrieveFromScrap(mScrapViews[whichScrap], position);
- }
+ } else if (whichScrap < mScrapViews.length) {
+ return retrieveFromScrap(mScrapViews[whichScrap], position);
}
return null;
}
diff --git a/core/java/android/widget/Chronometer.java b/core/java/android/widget/Chronometer.java
index a15080e..ebb54ff 100644
--- a/core/java/android/widget/Chronometer.java
+++ b/core/java/android/widget/Chronometer.java
@@ -17,6 +17,7 @@
package android.widget;
import android.content.Context;
+import android.content.res.Resources;
import android.content.res.TypedArray;
import android.os.Handler;
import android.os.Message;
@@ -24,6 +25,7 @@
import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.accessibility.AccessibilityEvent;
import android.widget.RemoteViews.RemoteView;
import java.util.Formatter;
@@ -58,6 +60,7 @@
}
private long mBase;
+ private long mNow; // the currently displayed time
private boolean mVisible;
private boolean mStarted;
private boolean mRunning;
@@ -224,6 +227,7 @@
}
private synchronized void updateText(long now) {
+ mNow = now;
long seconds = now - mBase;
seconds /= 1000;
String text = DateUtils.formatElapsedTime(mRecycle, seconds);
@@ -279,6 +283,60 @@
}
}
+ private static final int MIN_IN_SEC = 60;
+ private static final int HOUR_IN_SEC = MIN_IN_SEC*60;
+ private static String formatDuration(long ms) {
+ final Resources res = Resources.getSystem();
+ final StringBuilder text = new StringBuilder();
+
+ int duration = (int) (ms / DateUtils.SECOND_IN_MILLIS);
+ if (duration < 0) {
+ duration = -duration;
+ }
+
+ int h = 0;
+ int m = 0;
+
+ if (duration >= HOUR_IN_SEC) {
+ h = duration / HOUR_IN_SEC;
+ duration -= h * HOUR_IN_SEC;
+ }
+ if (duration >= MIN_IN_SEC) {
+ m = duration / MIN_IN_SEC;
+ duration -= m * MIN_IN_SEC;
+ }
+ int s = duration;
+
+ try {
+ if (h > 0) {
+ text.append(res.getQuantityString(
+ com.android.internal.R.plurals.duration_hours, h, h));
+ }
+ if (m > 0) {
+ if (text.length() > 0) {
+ text.append(' ');
+ }
+ text.append(res.getQuantityString(
+ com.android.internal.R.plurals.duration_minutes, m, m));
+ }
+
+ if (text.length() > 0) {
+ text.append(' ');
+ }
+ text.append(res.getQuantityString(
+ com.android.internal.R.plurals.duration_seconds, s, s));
+ } catch (Resources.NotFoundException e) {
+ // Ignore; plurals throws an exception for an untranslated quantity for a given locale.
+ return null;
+ }
+ return text.toString();
+ }
+
+ @Override
+ public CharSequence getContentDescription() {
+ return formatDuration(mNow - mBase);
+ }
+
@Override
public CharSequence getAccessibilityClassName() {
return Chronometer.class.getName();
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index d0b6160..9ca59f1 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3568,13 +3568,24 @@
}
protected void updateDrawable() {
+ if (mIsDragging) {
+ // Don't update drawable during dragging.
+ return;
+ }
final int offset = getCurrentCursorOffset();
final boolean isRtlCharAtOffset = mTextView.getLayout().isRtlCharAt(offset);
final Drawable oldDrawable = mDrawable;
mDrawable = isRtlCharAtOffset ? mDrawableRtl : mDrawableLtr;
mHotspotX = getHotspotX(mDrawable, isRtlCharAtOffset);
mHorizontalGravity = getHorizontalGravity(isRtlCharAtOffset);
- if (oldDrawable != mDrawable) {
+ final Layout layout = mTextView.getLayout();
+ if (layout != null && oldDrawable != mDrawable && isShowing()) {
+ // Update popup window position.
+ mPositionX = (int) (layout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX -
+ getHorizontalOffset() + getCursorOffset());
+ mPositionX += mTextView.viewportToContentHorizontalOffset();
+ mPositionHasChanged = true;
+ updatePosition(mLastParentX, mLastParentY, false, false);
postInvalidate();
}
}
@@ -3848,10 +3859,12 @@
case MotionEvent.ACTION_UP:
filterOnTouchUp();
mIsDragging = false;
+ updateDrawable();
break;
case MotionEvent.ACTION_CANCEL:
mIsDragging = false;
+ updateDrawable();
break;
}
return true;
@@ -4144,6 +4157,11 @@
offset = adjustedOffset;
}
positionCursor = true;
+ } else if (adjustedOffset < mPreviousOffset) {
+ // Handle has jumped to the start of the word, and the user is moving
+ // their finger towards the handle, the delta should be updated.
+ mTouchWordDelta = mTextView.convertToLocalHorizontalCoordinate(x)
+ - layout.getPrimaryHorizontal(mPreviousOffset);
}
}
@@ -4278,6 +4296,11 @@
offset = adjustedOffset;
}
positionCursor = true;
+ } else if (adjustedOffset > mPreviousOffset) {
+ // Handle has jumped to the end of the word, and the user is moving
+ // their finger towards the handle, the delta should be updated.
+ mTouchWordDelta = layout.getPrimaryHorizontal(mPreviousOffset)
+ - mTextView.convertToLocalHorizontalCoordinate(x);
}
}
@@ -4421,6 +4444,10 @@
// Indicates whether the user is selecting text and using the drag accelerator.
private boolean mDragAcceleratorActive;
private boolean mHaventMovedEnoughToStartDrag;
+ // The line that a selection happened most recently with the drag accelerator.
+ private int mLineSelectionIsOn = -1;
+ // Whether the drag accelerator has selected past the initial line.
+ private boolean mSwitchedLines = false;
SelectionModifierCursorController() {
resetTouchOffsets();
@@ -4473,6 +4500,7 @@
// Start location of selection.
mStartOffset = mTextView.getOffsetForPosition(mLastDownPositionX,
mLastDownPositionY);
+ mLineSelectionIsOn = mTextView.getLineAtCoordinate(mLastDownPositionY);
// Don't show the handles until user has lifted finger.
hide();
@@ -4556,17 +4584,35 @@
break;
}
- if (mStartOffset != -1) {
+ if (mStartOffset != -1 && mTextView.getLayout() != null) {
if (!mHaventMovedEnoughToStartDrag) {
- // Offset the finger by the same vertical offset as the handles. This
- // improves visibility of the content being selected by shifting
- // the finger below the content.
- final float fingerOffset = (mStartHandle != null)
- ? mStartHandle.getIdealVerticalOffset()
- : touchSlop;
- int offset =
- mTextView.getOffsetForPosition(eventX, eventY - fingerOffset);
+
+ float y = eventY;
+ if (mSwitchedLines) {
+ // Offset the finger by the same vertical offset as the handles.
+ // This improves visibility of the content being selected by
+ // shifting the finger below the content, this is applied once
+ // the user has switched lines.
+ final float fingerOffset = (mStartHandle != null)
+ ? mStartHandle.getIdealVerticalOffset()
+ : touchSlop;
+ y = eventY - fingerOffset;
+ }
+
+ final int currLine = getCurrentLineAdjustedForSlop(
+ mTextView.getLayout(),
+ mLineSelectionIsOn, y);
+ if (!mSwitchedLines && currLine != mLineSelectionIsOn) {
+ // Break early here, we want to offset the finger position from
+ // the selection highlight, once the user moved their finger
+ // to a different line we should apply the offset and *not* switch
+ // lines until recomputing the position with the finger offset.
+ mSwitchedLines = true;
+ break;
+ }
+
int startOffset;
+ int offset = mTextView.getOffsetAtCoordinate(currLine, eventX);
// Snap to word boundaries.
if (mStartOffset < offset) {
// Expanding with end handle.
@@ -4577,6 +4623,7 @@
offset = getWordStart(offset);
startOffset = getWordEnd(mStartOffset);
}
+ mLineSelectionIsOn = currLine;
Selection.setSelection((Spannable) mTextView.getText(),
startOffset, offset);
}
@@ -4613,6 +4660,7 @@
startSelectionActionMode();
mDragAcceleratorActive = false;
mStartOffset = -1;
+ mSwitchedLines = false;
}
break;
}
@@ -4642,6 +4690,7 @@
mMinTouchOffset = mMaxTouchOffset = -1;
mStartOffset = -1;
mDragAcceleratorActive = false;
+ mSwitchedLines = false;
}
/**
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index 6cc4bda..258424a 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -935,22 +935,14 @@
super.onDebugDraw(canvas);
}
- // Add/remove
-
- /**
- * @hide
- */
@Override
- protected void onViewAdded(View child) {
+ public void onViewAdded(View child) {
super.onViewAdded(child);
invalidateStructure();
}
- /**
- * @hide
- */
@Override
- protected void onViewRemoved(View child) {
+ public void onViewRemoved(View child) {
super.onViewRemoved(child);
invalidateStructure();
}
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 6b28f89..e0b2395 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -216,7 +216,7 @@
protected boolean verifyDrawable(Drawable dr) {
return mDrawable == dr || super.verifyDrawable(dr);
}
-
+
@Override
public void jumpDrawablesToCurrentState() {
super.jumpDrawablesToCurrentState();
@@ -226,6 +226,15 @@
@Override
public void invalidateDrawable(Drawable dr) {
if (dr == mDrawable) {
+ if (dr != null) {
+ // update cached drawable dimensions if they've changed
+ final int w = dr.getIntrinsicWidth();
+ final int h = dr.getIntrinsicHeight();
+ if (w != mDrawableWidth || h != mDrawableHeight) {
+ mDrawableWidth = w;
+ mDrawableHeight = h;
+ }
+ }
/* we invalidate the whole view in this case because it's very
* hard to know where the drawable actually is. This is made
* complicated because of the offsets and transformations that
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index affc5da..339038e 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -522,7 +522,7 @@
View baselineView = null;
LayoutParams baselineParams = null;
for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
+ final View child = views[i];
if (child.getVisibility() != GONE) {
final LayoutParams childParams = (LayoutParams) child.getLayoutParams();
if (baselineView == null || baselineParams == null
@@ -548,9 +548,9 @@
if (offsetHorizontalAxis) {
for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
+ final View child = views[i];
if (child.getVisibility() != GONE) {
- LayoutParams params = (LayoutParams) child.getLayoutParams();
+ final LayoutParams params = (LayoutParams) child.getLayoutParams();
final int[] rules = params.getRules(layoutDirection);
if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_HORIZONTAL] != 0) {
centerHorizontal(child, params, width);
@@ -578,9 +578,9 @@
if (offsetVerticalAxis) {
for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
+ final View child = views[i];
if (child.getVisibility() != GONE) {
- LayoutParams params = (LayoutParams) child.getLayoutParams();
+ final LayoutParams params = (LayoutParams) child.getLayoutParams();
final int[] rules = params.getRules(layoutDirection);
if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_VERTICAL] != 0) {
centerVertical(child, params, height);
@@ -607,9 +607,9 @@
final int verticalOffset = contentBounds.top - top;
if (horizontalOffset != 0 || verticalOffset != 0) {
for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
+ final View child = views[i];
if (child.getVisibility() != GONE && child != ignore) {
- LayoutParams params = (LayoutParams) child.getLayoutParams();
+ final LayoutParams params = (LayoutParams) child.getLayoutParams();
if (horizontalGravity) {
params.mLeft += horizontalOffset;
params.mRight += horizontalOffset;
@@ -626,9 +626,9 @@
if (isLayoutRtl()) {
final int offsetWidth = myWidth - width;
for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
+ final View child = views[i];
if (child.getVisibility() != GONE) {
- LayoutParams params = (LayoutParams) child.getLayoutParams();
+ final LayoutParams params = (LayoutParams) child.getLayoutParams();
params.mLeft -= offsetWidth;
params.mRight -= offsetWidth;
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 78b5d5d..c538dc2 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -241,8 +241,6 @@
* @attr ref android.R.styleable#TextView_fontFeatureSettings
* @attr ref android.R.styleable#TextView_breakStrategy
* @attr ref android.R.styleable#TextView_hyphenationFrequency
- * @attr ref android.R.styleable#TextView_leftIndents
- * @attr ref android.R.styleable#TextView_rightIndents
*/
@RemoteView
public class TextView extends View implements ViewTreeObserver.OnPreDrawListener {
@@ -559,8 +557,6 @@
private int mBreakStrategy;
private int mHyphenationFrequency;
- private int[] mLeftIndents;
- private int[] mRightIndents;
private int mMaximum = Integer.MAX_VALUE;
private int mMaxMode = LINES;
@@ -1165,16 +1161,6 @@
case com.android.internal.R.styleable.TextView_hyphenationFrequency:
mHyphenationFrequency = a.getInt(attr, Layout.HYPHENATION_FREQUENCY_NONE);
break;
-
- case com.android.internal.R.styleable.TextView_leftIndents:
- TypedArray margins = res.obtainTypedArray(a.getResourceId(attr, View.NO_ID));
- mLeftIndents = parseDimensionArray(margins);
- break;
-
- case com.android.internal.R.styleable.TextView_rightIndents:
- margins = res.obtainTypedArray(a.getResourceId(attr, View.NO_ID));
- mRightIndents = parseDimensionArray(margins);
- break;
}
}
a.recycle();
@@ -3095,51 +3081,6 @@
}
/**
- * Set indents. Arguments are arrays holding an indent amount, one per line, measured in
- * pixels. For lines past the last element in the array, the last element repeats.
- *
- * @param leftIndents array of indent values for left margin, in pixels
- * @param rightIndents array of indent values for right margin, in pixels
- *
- * @see #getLeftIndents()
- * @see #getRightIndents()
- *
- * @attr ref android.R.styleable#TextView_leftIndents
- * @attr ref android.R.styleable#TextView_rightIndents
- */
- public void setIndents(@Nullable int[] leftIndents, @Nullable int[] rightIndents) {
- mLeftIndents = leftIndents;
- mRightIndents = rightIndents;
- if (mLayout != null) {
- nullLayouts();
- requestLayout();
- invalidate();
- }
- }
-
- /**
- * Get left indents. See {#link setMargins} for more details.
- *
- * @return left indents
- * @see #setIndents(int[], int[])
- * @attr ref android.R.styleable#TextView_leftIndents
- */
- public int[] getLeftIndents() {
- return mLeftIndents;
- }
-
- /**
- * Get right indents. See {#link setMargins} for more details.
- *
- * @return right indents
- * @see #setIndents(int[], int[])
- * @attr ref android.R.styleable#TextView_rightIndents
- */
- public int[] getRightIndents() {
- return mRightIndents;
- }
-
- /**
* Sets font feature settings. The format is the same as the CSS
* font-feature-settings attribute:
* http://dev.w3.org/csswg/css-fonts/#propdef-font-feature-settings
@@ -6685,9 +6626,6 @@
.setIncludePad(mIncludePad)
.setBreakStrategy(mBreakStrategy)
.setHyphenationFrequency(mHyphenationFrequency);
- if (mLeftIndents != null || mRightIndents != null) {
- builder.setIndents(mLeftIndents, mRightIndents);
- }
if (shouldEllipsize) {
builder.setEllipsize(mEllipsize)
.setEllipsizedWidth(ellipsisWidth)
@@ -6776,9 +6714,6 @@
.setIncludePad(mIncludePad)
.setBreakStrategy(mBreakStrategy)
.setHyphenationFrequency(mHyphenationFrequency);
- if (mLeftIndents != null || mRightIndents != null) {
- builder.setIndents(mLeftIndents, mRightIndents);
- }
if (shouldEllipsize) {
builder.setEllipsize(effectiveEllipsize)
.setEllipsizedWidth(ellipsisWidth)
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 2ea2667..471ea9b 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -273,6 +273,24 @@
if (!TextUtils.isEmpty(navDesc)) {
setNavigationContentDescription(navDesc);
}
+
+ final Drawable logo = a.getDrawable(R.styleable.Toolbar_logo);
+ if (logo != null) {
+ setLogo(logo);
+ }
+
+ final CharSequence logoDesc = a.getText(R.styleable.Toolbar_logoDescription);
+ if (!TextUtils.isEmpty(logoDesc)) {
+ setLogoDescription(logoDesc);
+ }
+
+ if (a.hasValue(R.styleable.Toolbar_titleTextColor)) {
+ setTitleTextColor(a.getColor(R.styleable.Toolbar_titleTextColor, 0xffffffff));
+ }
+
+ if (a.hasValue(R.styleable.Toolbar_subtitleTextColor)) {
+ setSubtitleTextColor(a.getColor(R.styleable.Toolbar_subtitleTextColor, 0xffffffff));
+ }
a.recycle();
}
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 929cacd..6f0cec6 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -116,7 +116,7 @@
void noteWifiRadioPowerState(int powerState, long timestampNs);
void noteNetworkInterfaceType(String iface, int type);
void noteNetworkStatsEnabled();
- void noteDeviceIdleMode(boolean enabled, boolean fromActive, boolean fromMotion);
+ void noteDeviceIdleMode(boolean enabled, String activeReason, int activeUid);
void setBatteryState(int status, int health, int plugType, int level, int temp, int volt);
long getAwakeTimeBattery();
long getAwakeTimePlugged();
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
index 7d3db02..5a195cb 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
@@ -20,6 +20,7 @@
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
+import android.content.pm.ParceledListSlice;
import android.appwidget.AppWidgetProviderInfo;
import com.android.internal.appwidget.IAppWidgetHost;
import android.os.Bundle;
@@ -54,7 +55,7 @@
in RemoteViews views);
void updateAppWidgetProvider(in ComponentName provider, in RemoteViews views);
void notifyAppWidgetViewDataChanged(String packageName, in int[] appWidgetIds, int viewId);
- List<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
+ ParceledListSlice getInstalledProvidersForProfile(int categoryFilter,
int profileId);
AppWidgetProviderInfo getAppWidgetInfo(String callingPackage, int appWidgetId);
boolean hasBindAppWidgetPermission(in String packageName, int userId);
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index 230d96d..03f2e3a 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -26,6 +26,13 @@
* @hide
*/
public class MetricsLogger implements MetricsConstants {
+ public static final int VOLUME_DIALOG = 207;
+ public static final int VOLUME_DIALOG_DETAILS = 208;
+ public static final int ACTION_VOLUME_SLIDER = 209;
+ public static final int ACTION_VOLUME_STREAM = 210;
+ public static final int ACTION_VOLUME_KEY = 211;
+ public static final int ACTION_VOLUME_ICON = 212;
+ public static final int ACTION_RINGER_MODE = 213;
// Temporary constants go here, to await migration to MetricsConstants.
public static void visible(Context context, int category) throws IllegalArgumentException {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 07d1fc8..229079f 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -95,7 +95,8 @@
public final class BatteryStatsImpl extends BatteryStats {
private static final String TAG = "BatteryStatsImpl";
private static final boolean DEBUG = false;
- private static final boolean DEBUG_ENERGY = false;
+ public static final boolean DEBUG_ENERGY = false;
+ private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY || false;
private static final boolean DEBUG_HISTORY = false;
private static final boolean USE_OLD_HISTORY = false; // for debugging.
@@ -105,7 +106,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 127 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 128 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -151,6 +152,9 @@
BatteryCallback cb = mCallback;
switch (msg.what) {
case MSG_UPDATE_WAKELOCKS:
+ synchronized (BatteryStatsImpl.this) {
+ updateCpuTimeLocked();
+ }
if (cb != null) {
cb.batteryNeedsCpuUpdate();
}
@@ -178,6 +182,7 @@
public interface ExternalStatsSync {
void scheduleSync(String reason);
+ void scheduleWifiSync(String reason);
}
public final MyHandler mHandler;
@@ -2503,12 +2508,11 @@
boolean unpluggedScreenOff = unplugged && screenOff;
if (unpluggedScreenOff != mOnBatteryScreenOffTimeBase.isRunning()) {
updateKernelWakelocksLocked();
- requestWakelockCpuUpdate();
- if (!unpluggedScreenOff) {
- // We are switching to no longer tracking wake locks, but we want
- // the next CPU update we receive to take them in to account.
- mDistributeWakelockCpu = true;
+ if (DEBUG_ENERGY_CPU) {
+ Slog.d(TAG, "Updating cpu time because screen is now " +
+ (unpluggedScreenOff ? "off" : "on"));
}
+ updateCpuTimeLocked();
mOnBatteryScreenOffTimeBase.setRunning(unpluggedScreenOff, uptime, realtime);
}
}
@@ -2772,10 +2776,14 @@
mWakeLockNesting++;
}
if (uid >= 0) {
- //if (uid == 0) {
- // Slog.wtf(TAG, "Acquiring wake lock from root: " + name);
- //}
- requestWakelockCpuUpdate();
+ if (mOnBatteryScreenOffTimeBase.isRunning()) {
+ // We only update the cpu time when a wake lock is acquired if the screen is off.
+ // If the screen is on, we don't distribute the power amongst partial wakelocks.
+ if (DEBUG_ENERGY_CPU) {
+ Slog.d(TAG, "Updating cpu time because of +wake_lock");
+ }
+ requestWakelockCpuUpdate();
+ }
getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime);
}
}
@@ -2805,7 +2813,12 @@
}
}
if (uid >= 0) {
- requestWakelockCpuUpdate();
+ if (mOnBatteryScreenOffTimeBase.isRunning()) {
+ if (DEBUG_ENERGY_CPU) {
+ Slog.d(TAG, "Updating cpu time because of -wake_lock");
+ }
+ requestWakelockCpuUpdate();
+ }
getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime);
}
}
@@ -2874,46 +2887,14 @@
addHistoryRecordLocked(elapsedRealtime, uptime);
}
- public int startAddingCpuLocked() {
+ public boolean startAddingCpuLocked() {
mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
-
- if (!mOnBatteryInternal) {
- return -1;
- }
-
- final int N = mPartialTimers.size();
- if (N == 0) {
- mLastPartialTimers.clear();
- mDistributeWakelockCpu = false;
- return 0;
- }
-
- if (!mOnBatteryScreenOffTimeBase.isRunning() && !mDistributeWakelockCpu) {
- return 0;
- }
-
- mDistributeWakelockCpu = false;
-
- // How many timers should consume CPU? Only want to include ones
- // that have already been in the list.
- for (int i=0; i<N; i++) {
- StopwatchTimer st = mPartialTimers.get(i);
- if (st.mInList) {
- Uid uid = st.mUid;
- // We don't include the system UID, because it so often
- // holds wake locks at one request or another of an app.
- if (uid != null && uid.mUid != Process.SYSTEM_UID) {
- return 50;
- }
- }
- }
-
- return 0;
+ return mOnBatteryInternal;
}
- public void finishAddingCpuLocked(int perc, int remainUTime, int remainSTtime,
- int totalUTime, int totalSTime, int statUserTime, int statSystemTime,
- int statIOWaitTime, int statIrqTime, int statSoftIrqTime, int statIdleTime) {
+ public void finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime,
+ int statSystemTime, int statIOWaitTime, int statIrqTime,
+ int statSoftIrqTime, int statIdleTime) {
if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime
+ " user=" + statUserTime + " sys=" + statSystemTime
+ " io=" + statIOWaitTime + " irq=" + statIrqTime
@@ -2926,70 +2907,6 @@
mCurStepStatIrqTime += statIrqTime;
mCurStepStatSoftIrqTime += statSoftIrqTime;
mCurStepStatIdleTime += statIdleTime;
-
- final int N = mPartialTimers.size();
- if (perc != 0) {
- int num = 0;
- for (int i=0; i<N; i++) {
- StopwatchTimer st = mPartialTimers.get(i);
- if (st.mInList) {
- Uid uid = st.mUid;
- // We don't include the system UID, because it so often
- // holds wake locks at one request or another of an app.
- if (uid != null && uid.mUid != Process.SYSTEM_UID) {
- num++;
- }
- }
- }
- if (num != 0) {
- for (int i=0; i<N; i++) {
- StopwatchTimer st = mPartialTimers.get(i);
- if (st.mInList) {
- Uid uid = st.mUid;
- if (uid != null && uid.mUid != Process.SYSTEM_UID) {
- int myUTime = remainUTime/num;
- int mySTime = remainSTtime/num;
- remainUTime -= myUTime;
- remainSTtime -= mySTime;
- num--;
- Uid.Proc proc = uid.getProcessStatsLocked("*wakelock*");
- proc.addCpuTimeLocked(myUTime, mySTime);
- }
- }
- }
- }
-
- // Just in case, collect any lost CPU time.
- if (remainUTime != 0 || remainSTtime != 0) {
- Uid uid = getUidStatsLocked(Process.SYSTEM_UID);
- if (uid != null) {
- Uid.Proc proc = uid.getProcessStatsLocked("*lost*");
- proc.addCpuTimeLocked(remainUTime, remainSTtime);
- }
- }
- }
-
- final int NL = mLastPartialTimers.size();
- boolean diff = N != NL;
- for (int i=0; i<NL && !diff; i++) {
- diff |= mPartialTimers.get(i) != mLastPartialTimers.get(i);
- }
- if (!diff) {
- for (int i=0; i<NL; i++) {
- mPartialTimers.get(i).mInList = true;
- }
- return;
- }
-
- for (int i=0; i<NL; i++) {
- mLastPartialTimers.get(i).mInList = false;
- }
- mLastPartialTimers.clear();
- for (int i=0; i<N; i++) {
- StopwatchTimer st = mPartialTimers.get(i);
- st.mInList = true;
- mLastPartialTimers.add(st);
- }
}
public void noteProcessDiedLocked(int uid, int pid) {
@@ -3271,11 +3188,11 @@
}
}
- public void noteDeviceIdleModeLocked(boolean enabled, boolean fromActive, boolean fromMotion) {
+ public void noteDeviceIdleModeLocked(boolean enabled, String activeReason, int activeUid) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
boolean nowIdling = enabled;
- if (mDeviceIdling && !enabled && !fromActive && !fromMotion) {
+ if (mDeviceIdling && !enabled && activeReason == null) {
// We don't go out of general idling mode until explicitly taken out of
// device idle through going active or significant motion.
nowIdling = true;
@@ -3293,14 +3210,8 @@
}
if (mDeviceIdleModeEnabled != enabled) {
mDeviceIdleModeEnabled = enabled;
- if (fromMotion) {
- addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SIGNIFICANT_MOTION,
- "", 0);
- }
- if (fromActive) {
- addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
- "", 0);
- }
+ addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
+ activeReason != null ? activeReason : "", activeUid);
if (enabled) {
mHistoryCur.states2 |= HistoryItem.STATE2_DEVICE_IDLE_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode enabled to: "
@@ -3580,7 +3491,7 @@
addHistoryRecordLocked(elapsedRealtime, uptime);
mWifiOn = true;
mWifiOnTimer.startRunningLocked(elapsedRealtime);
- scheduleSyncExternalStatsLocked("wifi-off");
+ scheduleSyncExternalWifiStatsLocked("wifi-off");
}
}
@@ -3594,7 +3505,7 @@
addHistoryRecordLocked(elapsedRealtime, uptime);
mWifiOn = false;
mWifiOnTimer.stopRunningLocked(elapsedRealtime);
- scheduleSyncExternalStatsLocked("wifi-on");
+ scheduleSyncExternalWifiStatsLocked("wifi-on");
}
}
@@ -3846,7 +3757,7 @@
int uid = mapUid(ws.get(i));
getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
}
- scheduleSyncExternalStatsLocked("wifi-running");
+ scheduleSyncExternalWifiStatsLocked("wifi-running");
} else {
Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
}
@@ -3885,7 +3796,7 @@
int uid = mapUid(ws.get(i));
getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
}
- scheduleSyncExternalStatsLocked("wifi-stopped");
+ scheduleSyncExternalWifiStatsLocked("wifi-stopped");
} else {
Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
}
@@ -3900,7 +3811,7 @@
}
mWifiState = wifiState;
mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
- scheduleSyncExternalStatsLocked("wifi-state");
+ scheduleSyncExternalWifiStatsLocked("wifi-state");
}
}
@@ -7632,6 +7543,10 @@
* @param info The energy information from the WiFi controller.
*/
public void updateWifiStateLocked(@Nullable final WifiActivityEnergyInfo info) {
+ if (DEBUG_ENERGY) {
+ Slog.d(TAG, "Updating wifi stats");
+ }
+
final long elapsedRealtimeMs = SystemClock.elapsedRealtime();
NetworkStats delta = null;
try {
@@ -7829,6 +7744,10 @@
* Distribute Cell radio energy info and network traffic to apps.
*/
public void updateMobileRadioStateLocked(final long elapsedRealtimeMs) {
+ if (DEBUG_ENERGY) {
+ Slog.d(TAG, "Updating mobile radio stats");
+ }
+
NetworkStats delta = null;
try {
if (!ArrayUtils.isEmpty(mMobileIfaces)) {
@@ -7901,6 +7820,10 @@
* @param info The energy information from the bluetooth controller.
*/
public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
+ if (DEBUG_ENERGY) {
+ Slog.d(TAG, "Updating bluetooth stats");
+ }
+
if (info != null && mOnBatteryInternal) {
mHasBluetoothEnergyReporting = true;
mBluetoothActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
@@ -7959,30 +7882,196 @@
}
}
+ // We use an anonymous class to access these variables,
+ // so they can't live on the stack or they'd have to be
+ // final MutableLong objects (more allocations).
+ // Used in updateCpuTimeLocked().
+ long mTempTotalCpuUserTimeUs;
+ long mTempTotalCpuSystemTimeUs;
+
/**
- * Read and distribute CPU usage across apps.
+ * Read and distribute CPU usage across apps. If their are partial wakelocks being held
+ * and we are on battery with screen off, we give more of the cpu time to those apps holding
+ * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
*/
- public void updateCpuTimeLocked(boolean firstTime) {
+ public void updateCpuTimeLocked() {
+ if (DEBUG_ENERGY_CPU) {
+ Slog.d(TAG, "!Cpu updating!");
+ }
+
+ // Holding a wakelock costs more than just using the cpu.
+ // Currently, we assign only half the cpu time to an app that is running but
+ // not holding a wakelock. The apps holding wakelocks get the rest of the blame.
+ // If no app is holding a wakelock, then the distribution is normal.
+ final int wakelockWeight = 50;
+
+ // Read the time spent at various cpu frequencies.
final int cpuSpeedSteps = getCpuSpeedSteps();
final long[] cpuSpeeds = mKernelCpuSpeedReader.readDelta();
- KernelUidCpuTimeReader.Callback callback = null;
- if (mOnBatteryInternal && !firstTime) {
- callback = new KernelUidCpuTimeReader.Callback() {
- @Override
- public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) {
- final Uid u = getUidStatsLocked(mapUid(uid));
- u.mUserCpuTime.addCountLocked(userTimeUs);
- u.mSystemCpuTime.addCountLocked(systemTimeUs);
- for (int i = 0; i < cpuSpeedSteps; i++) {
- if (u.mSpeedBins[i] == null) {
- u.mSpeedBins[i] = new LongSamplingCounter(mOnBatteryTimeBase);
- }
- u.mSpeedBins[i].addCountLocked(cpuSpeeds[i]);
- }
+
+ int numWakelocks = 0;
+
+ // Calculate how many wakelocks we have to distribute amongst. The system is excluded.
+ // Only distribute cpu power to wakelocks if the screen is off and we're on battery.
+ final int numPartialTimers = mPartialTimers.size();
+ if (mOnBatteryScreenOffTimeBase.isRunning()) {
+ for (int i = 0; i < numPartialTimers; i++) {
+ final StopwatchTimer timer = mPartialTimers.get(i);
+ if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
+ // Since the collection and blaming of wakelocks can be scheduled to run after
+ // some delay, the mPartialTimers list may have new entries. We can't blame
+ // the newly added timer for past cpu time, so we only consider timers that
+ // were present for one round of collection. Once a timer has gone through
+ // a round of collection, its mInList field is set to true.
+ numWakelocks++;
}
- };
+ }
}
- mKernelUidCpuTimeReader.readDelta(callback);
+
+ final int numWakelocksF = numWakelocks;
+ mTempTotalCpuUserTimeUs = 0;
+ mTempTotalCpuSystemTimeUs = 0;
+
+ // Read the CPU data for each UID. This will internally generate a snapshot so next time
+ // we read, we get a delta. If we are to distribute the cpu time, then do so. Otherwise
+ // we just ignore the data.
+ final long startTimeMs = SystemClock.elapsedRealtime();
+ mKernelUidCpuTimeReader.readDelta(!mOnBatteryInternal ? null :
+ new KernelUidCpuTimeReader.Callback() {
+ @Override
+ public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) {
+ final Uid u = getUidStatsLocked(mapUid(uid));
+
+ // Accumulate the total system and user time.
+ mTempTotalCpuUserTimeUs += userTimeUs;
+ mTempTotalCpuSystemTimeUs += systemTimeUs;
+
+ StringBuilder sb = null;
+ if (DEBUG_ENERGY_CPU) {
+ sb = new StringBuilder();
+ sb.append(" got time for uid=").append(u.mUid).append(": u=");
+ TimeUtils.formatDuration(userTimeUs / 1000, sb);
+ sb.append(" s=");
+ TimeUtils.formatDuration(systemTimeUs / 1000, sb);
+ sb.append("\n");
+ }
+
+ if (numWakelocksF > 0) {
+ // We have wakelocks being held, so only give a portion of the
+ // time to the process. The rest will be distributed among wakelock
+ // holders.
+ userTimeUs = (userTimeUs * wakelockWeight) / 100;
+ systemTimeUs = (systemTimeUs * wakelockWeight) / 100;
+ }
+
+ if (sb != null) {
+ sb.append(" adding to uid=").append(u.mUid).append(": u=");
+ TimeUtils.formatDuration(userTimeUs / 1000, sb);
+ sb.append(" s=");
+ TimeUtils.formatDuration(systemTimeUs / 1000, sb);
+ Slog.d(TAG, sb.toString());
+ }
+
+ u.mUserCpuTime.addCountLocked(userTimeUs);
+ u.mSystemCpuTime.addCountLocked(systemTimeUs);
+
+ // Add the cpu speeds to this UID. These are used as a ratio
+ // for computing the power this UID used.
+ for (int i = 0; i < cpuSpeedSteps; i++) {
+ if (u.mSpeedBins[i] == null) {
+ u.mSpeedBins[i] = new LongSamplingCounter(mOnBatteryTimeBase);
+ }
+ u.mSpeedBins[i].addCountLocked(cpuSpeeds[i]);
+ }
+ }
+ });
+
+ if (DEBUG_ENERGY_CPU) {
+ Slog.d(TAG, "Reading cpu stats took " + (SystemClock.elapsedRealtime() - startTimeMs) +
+ " ms");
+ }
+
+ if (mOnBatteryInternal && numWakelocks > 0) {
+ // Distribute a portion of the total cpu time to wakelock holders.
+ mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - wakelockWeight)) / 100;
+ mTempTotalCpuSystemTimeUs =
+ (mTempTotalCpuSystemTimeUs * (100 - wakelockWeight)) / 100;
+
+ for (int i = 0; i < numPartialTimers; i++) {
+ final StopwatchTimer timer = mPartialTimers.get(i);
+
+ // The system does not share any blame, as it is usually holding the wakelock
+ // on behalf of an app.
+ if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
+ int userTimeUs = (int) (mTempTotalCpuUserTimeUs / numWakelocks);
+ int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / numWakelocks);
+
+ if (DEBUG_ENERGY_CPU) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(" Distributing wakelock uid=").append(timer.mUid.mUid)
+ .append(": u=");
+ TimeUtils.formatDuration(userTimeUs / 1000, sb);
+ sb.append(" s=");
+ TimeUtils.formatDuration(systemTimeUs / 1000, sb);
+ Slog.d(TAG, sb.toString());
+ }
+
+ timer.mUid.mUserCpuTime.addCountLocked(userTimeUs);
+ timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs);
+
+ final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
+ proc.addCpuTimeLocked(userTimeUs, systemTimeUs);
+
+ mTempTotalCpuUserTimeUs -= userTimeUs;
+ mTempTotalCpuSystemTimeUs -= systemTimeUs;
+ numWakelocks--;
+ }
+ }
+
+ if (mTempTotalCpuUserTimeUs > 0 || mTempTotalCpuSystemTimeUs > 0) {
+ // Anything left over is given to the system.
+ if (DEBUG_ENERGY_CPU) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(" Distributing lost time to system: u=");
+ TimeUtils.formatDuration(mTempTotalCpuUserTimeUs / 1000, sb);
+ sb.append(" s=");
+ TimeUtils.formatDuration(mTempTotalCpuSystemTimeUs / 1000, sb);
+ Slog.d(TAG, sb.toString());
+ }
+
+ final Uid u = getUidStatsLocked(Process.SYSTEM_UID);
+ u.mUserCpuTime.addCountLocked(mTempTotalCpuUserTimeUs);
+ u.mSystemCpuTime.addCountLocked(mTempTotalCpuSystemTimeUs);
+
+ final Uid.Proc proc = u.getProcessStatsLocked("*lost*");
+ proc.addCpuTimeLocked((int) mTempTotalCpuUserTimeUs,
+ (int) mTempTotalCpuSystemTimeUs);
+ }
+ }
+
+ // See if there is a difference in wakelocks between this collection and the last
+ // collection.
+ if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
+ // No difference, so each timer is now considered for the next collection.
+ for (int i = 0; i < numPartialTimers; i++) {
+ mPartialTimers.get(i).mInList = true;
+ }
+ } else {
+ // The lists are different, meaning we added (or removed a timer) since the last
+ // collection.
+ final int numLastPartialTimers = mLastPartialTimers.size();
+ for (int i = 0; i < numLastPartialTimers; i++) {
+ mLastPartialTimers.get(i).mInList = false;
+ }
+ mLastPartialTimers.clear();
+
+ // Mark the current timers as gone through a collection.
+ for (int i = 0; i < numPartialTimers; i++) {
+ final StopwatchTimer timer = mPartialTimers.get(i);
+ timer.mInList = true;
+ mLastPartialTimers.add(timer);
+ }
+ }
}
boolean setChargingLocked(boolean charging) {
@@ -8157,6 +8246,12 @@
}
}
+ private void scheduleSyncExternalWifiStatsLocked(String reason) {
+ if (mExternalSync != null) {
+ mExternalSync.scheduleWifiSync(reason);
+ }
+ }
+
// This should probably be exposed in the API, though it's not critical
public static final int BATTERY_PLUGGED_NONE = 0;
diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
index b236378..62926d1 100644
--- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
@@ -16,9 +16,11 @@
package com.android.internal.os;
import android.annotation.Nullable;
+import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Slog;
import android.util.SparseLongArray;
+import android.util.TimeUtils;
import java.io.BufferedReader;
import java.io.FileReader;
@@ -49,6 +51,7 @@
private SparseLongArray mLastUserTimeUs = new SparseLongArray();
private SparseLongArray mLastSystemTimeUs = new SparseLongArray();
+ private long mLastTimeRead = 0;
/**
* Reads the proc file, calling into the callback with a delta of time for each UID.
@@ -57,6 +60,7 @@
* a fresh delta.
*/
public void readDelta(@Nullable Callback callback) {
+ long now = SystemClock.elapsedRealtime();
try (BufferedReader reader = new BufferedReader(new FileReader(sProcFile))) {
TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' ');
String line;
@@ -75,10 +79,32 @@
userTimeDeltaUs -= mLastUserTimeUs.valueAt(index);
systemTimeDeltaUs -= mLastSystemTimeUs.valueAt(index);
- if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0) {
- // The UID must have been removed from accounting, then added back.
- userTimeDeltaUs = userTimeUs;
- systemTimeDeltaUs = systemTimeUs;
+ final long timeDiffMs = (now - mLastTimeRead) * 1000;
+ if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0 ||
+ userTimeDeltaUs > timeDiffMs || systemTimeDeltaUs > timeDiffMs ) {
+ StringBuilder sb = new StringBuilder("Malformed cpu data!\n");
+ sb.append("Time between reads: ");
+ TimeUtils.formatDuration(timeDiffMs, sb);
+ sb.append("ms\n");
+ sb.append("Previous times: u=");
+ TimeUtils.formatDuration(mLastUserTimeUs.valueAt(index) / 1000, sb);
+ sb.append("ms s=");
+ TimeUtils.formatDuration(mLastSystemTimeUs.valueAt(index) / 1000, sb);
+ sb.append("ms\n");
+ sb.append("Current times: u=");
+ TimeUtils.formatDuration(userTimeUs / 1000, sb);
+ sb.append("ms s=");
+ TimeUtils.formatDuration(systemTimeUs / 1000, sb);
+ sb.append("ms\n");
+ sb.append("Delta for UID=").append(uid).append(": u=");
+ TimeUtils.formatDuration(userTimeDeltaUs / 1000, sb);
+ sb.append("ms s=");
+ TimeUtils.formatDuration(systemTimeDeltaUs / 1000, sb);
+ sb.append("ms");
+ Slog.wtf(TAG, sb.toString());
+
+ userTimeDeltaUs = 0;
+ systemTimeDeltaUs = 0;
}
}
@@ -92,6 +118,7 @@
} catch (IOException e) {
Slog.e(TAG, "Failed to read uid_cputime", e);
}
+ mLastTimeRead = now;
}
/**
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 294e4ba..66f6079 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -390,6 +390,7 @@
} else {
mLayoutInflater.inflate(layoutResID, mContentParent);
}
+ mContentParent.requestApplyInsets();
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
@@ -419,6 +420,7 @@
} else {
mContentParent.addView(view, params);
}
+ mContentParent.requestApplyInsets();
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
@@ -435,6 +437,7 @@
Log.v(TAG, "addContentView does not support content transitions");
}
mContentParent.addView(view, params);
+ mContentParent.requestApplyInsets();
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
diff --git a/core/java/com/android/internal/statusbar/StatusBarIcon.java b/core/java/com/android/internal/statusbar/StatusBarIcon.java
index 4693d4b..1d62623 100644
--- a/core/java/com/android/internal/statusbar/StatusBarIcon.java
+++ b/core/java/com/android/internal/statusbar/StatusBarIcon.java
@@ -20,17 +20,27 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
+import android.text.TextUtils;
public class StatusBarIcon implements Parcelable {
public UserHandle user;
+ public String pkg;
public Icon icon;
public int iconLevel;
public boolean visible = true;
public int number;
public CharSequence contentDescription;
- public StatusBarIcon(UserHandle user, Icon icon, int iconLevel, int number,
+ public StatusBarIcon(UserHandle user, String resPackage, Icon icon, int iconLevel, int number,
CharSequence contentDescription) {
+ if (icon.getType() == Icon.TYPE_RESOURCE
+ && TextUtils.isEmpty(icon.getResPackage())) {
+ // This is an odd situation where someone's managed to hand us an icon without a
+ // package inside, probably by mashing an int res into a Notification object.
+ // Now that we have the correct package name handy, let's fix it.
+ icon = Icon.createWithResource(resPackage, icon.getResId());
+ }
+ this.pkg = resPackage;
this.user = user;
this.icon = icon;
this.iconLevel = iconLevel;
@@ -41,21 +51,23 @@
public StatusBarIcon(String iconPackage, UserHandle user,
int iconId, int iconLevel, int number,
CharSequence contentDescription) {
- this(user, Icon.createWithResource(iconPackage, iconId),
+ this(user, iconPackage, Icon.createWithResource(iconPackage, iconId),
iconLevel, number, contentDescription);
}
@Override
public String toString() {
- return "StatusBarIcon(icon=" + this.icon
+ return "StatusBarIcon(icon=" + icon
+ + ((iconLevel != 0)?(" level=" + iconLevel):"")
+ + (visible?" visible":"")
+ " user=" + user.getIdentifier()
- + " level=" + this.iconLevel + " visible=" + visible
- + " num=" + this.number + " )";
+ + ((number != 0)?(" num=" + number):"")
+ + " )";
}
@Override
public StatusBarIcon clone() {
- StatusBarIcon that = new StatusBarIcon(this.user, this.icon,
+ StatusBarIcon that = new StatusBarIcon(this.user, this.pkg, this.icon,
this.iconLevel, this.number, this.contentDescription);
that.visible = this.visible;
return that;
@@ -70,6 +82,7 @@
public void readFromParcel(Parcel in) {
this.icon = (Icon) in.readParcelable(null);
+ this.pkg = in.readString();
this.user = (UserHandle) in.readParcelable(null);
this.iconLevel = in.readInt();
this.visible = in.readInt() != 0;
@@ -79,6 +92,7 @@
public void writeToParcel(Parcel out, int flags) {
out.writeParcelable(this.icon, 0);
+ out.writeString(this.pkg);
out.writeParcelable(this.user, 0);
out.writeInt(this.iconLevel);
out.writeInt(this.visible ? 1 : 0);
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 62e724a..9d0636a 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -387,4 +387,26 @@
public static <T> boolean contains(ArrayList<T> cur, T val) {
return (cur != null) ? cur.contains(val) : false;
}
+
+ /**
+ * Returns true if the two ArrayLists are equal with respect to the objects they contain.
+ * The objects must be in the same order and be reference equal (== not .equals()).
+ */
+ public static <T> boolean referenceEquals(ArrayList<T> a, ArrayList<T> b) {
+ if (a == b) {
+ return true;
+ }
+
+ final int sizeA = a.size();
+ final int sizeB = b.size();
+ if (a == null || b == null || sizeA != sizeB) {
+ return false;
+ }
+
+ boolean diff = false;
+ for (int i = 0; i < sizeA && !diff; i++) {
+ diff |= a.get(i) != b.get(i);
+ }
+ return !diff;
+ }
}
diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java
index 99c12776..784b256 100644
--- a/core/java/com/android/internal/view/FloatingActionMode.java
+++ b/core/java/com/android/internal/view/FloatingActionMode.java
@@ -25,6 +25,7 @@
import android.view.View;
import android.view.ViewConfiguration;
+import com.android.internal.R;
import com.android.internal.util.Preconditions;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.widget.FloatingToolbar;
@@ -44,6 +45,7 @@
private final Rect mViewRect;
private final Rect mScreenRect;
private final View mOriginatingView;
+ private final int mBottomAllowance;
private final Runnable mMovingOff = new Runnable() {
public void run() {
@@ -77,6 +79,10 @@
mScreenRect = new Rect();
mOriginatingView = Preconditions.checkNotNull(originatingView);
mOriginatingView.getLocationInWindow(mViewPosition);
+ // Allow the content rect to overshoot a little bit beyond the
+ // bottom view bound if necessary.
+ mBottomAllowance = context.getResources()
+ .getDimensionPixelSize(R.dimen.content_rect_bottom_clip_allowance);
}
public void setFloatingToolbar(FloatingToolbar floatingToolbar) {
@@ -141,7 +147,7 @@
Math.max(mContentRectOnWindow.left, mViewRect.left),
Math.max(mContentRectOnWindow.top, mViewRect.top),
Math.min(mContentRectOnWindow.right, mViewRect.right),
- Math.min(mContentRectOnWindow.bottom, mViewRect.bottom));
+ Math.min(mContentRectOnWindow.bottom, mViewRect.bottom + mBottomAllowance));
if (!mContentRectOnWindow.equals(mPreviousContentRectOnWindow)) {
// Content rect is moving.
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 53ebc23..65f2f53f 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -20,7 +20,9 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
+import android.content.ComponentCallbacks;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
@@ -89,6 +91,19 @@
private int mSuggestedWidth;
private boolean mWidthChanged = true;
+ private final ComponentCallbacks mOrientationChangeHandler = new ComponentCallbacks() {
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ if (mPopup.isShowing() && mPopup.viewPortHasChanged()) {
+ mWidthChanged = true;
+ updateLayout();
+ }
+ }
+
+ @Override
+ public void onLowMemory() {}
+ };
+
/**
* Initializes a floating toolbar.
*/
@@ -151,6 +166,8 @@
* Shows this floating toolbar.
*/
public FloatingToolbar show() {
+ mContext.unregisterComponentCallbacks(mOrientationChangeHandler);
+ mContext.registerComponentCallbacks(mOrientationChangeHandler);
List<MenuItem> menuItems = getVisibleAndEnabledMenuItems(mMenu);
if (!isCurrentlyShowing(menuItems) || mWidthChanged) {
mPopup.dismiss();
@@ -181,6 +198,7 @@
* Dismisses this floating toolbar.
*/
public void dismiss() {
+ mContext.unregisterComponentCallbacks(mOrientationChangeHandler);
mPopup.dismiss();
}
@@ -329,6 +347,7 @@
private final Rect mViewPort = new Rect();
private final Point mCoords = new Point();
+ private final Rect mTmpRect = new Rect();
private final Region mTouchableRegion = new Region();
private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer =
@@ -873,6 +892,11 @@
mParent.getWindowVisibleDisplayFrame(mViewPort);
}
+ private boolean viewPortHasChanged() {
+ mParent.getWindowVisibleDisplayFrame(mTmpRect);
+ return !mTmpRect.equals(mViewPort);
+ }
+
private int getToolbarWidth(int suggestedWidth) {
int width = suggestedWidth;
refreshViewPort();
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index be727f1..585cbc9 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -127,6 +127,8 @@
final ViewConfiguration vc = ViewConfiguration.get(context);
mTouchSlop = vc.getScaledTouchSlop();
mMinFlingVelocity = vc.getScaledMinimumFlingVelocity();
+
+ setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
}
public void setSmallCollapsed(boolean smallCollapsed) {
@@ -593,11 +595,6 @@
}
@Override
- public CharSequence getAccessibilityClassName() {
- return ResolverDrawerLayout.class.getName();
- }
-
- @Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
if (isEnabled()) {
diff --git a/core/jni/android/graphics/Region.cpp b/core/jni/android/graphics/Region.cpp
index 3bab2df..e99bdfc 100644
--- a/core/jni/android/graphics/Region.cpp
+++ b/core/jni/android/graphics/Region.cpp
@@ -231,15 +231,24 @@
static jboolean Region_writeToParcel(JNIEnv* env, jobject clazz, jlong regionHandle, jobject parcel)
{
const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
- if (parcel == NULL) {
+ if (parcel == nullptr) {
return JNI_FALSE;
}
android::Parcel* p = android::parcelForJavaObject(env, parcel);
- size_t size = region->writeToMemory(NULL);
+ const size_t size = region->writeToMemory(nullptr);
p->writeInt32(size);
- region->writeToMemory(p->writeInplace(size));
+ void* dst = p->writeInplace(size);
+ if (dst == nullptr) {
+ ALOGE("Region.writeToParcel could not write %zi bytes", size);
+ return JNI_FALSE;
+ }
+ const size_t sizeWritten = region->writeToMemory(dst);
+ if (sizeWritten != size) {
+ ALOGE("SkRegion::writeToMemory should have written %zi bytes but wrote %zi",
+ size, sizeWritten);
+ }
return JNI_TRUE;
}
diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h
index 5144457..bb13c35 100644
--- a/core/jni/android_media_AudioFormat.h
+++ b/core/jni/android_media_AudioFormat.h
@@ -80,6 +80,13 @@
return ENCODING_PCM_8BIT;
case AUDIO_FORMAT_PCM_FLOAT:
return ENCODING_PCM_FLOAT;
+
+ // map these to ENCODING_PCM_FLOAT
+ case AUDIO_FORMAT_PCM_8_24_BIT:
+ case AUDIO_FORMAT_PCM_24_BIT_PACKED:
+ case AUDIO_FORMAT_PCM_32_BIT:
+ return ENCODING_PCM_FLOAT;
+
case AUDIO_FORMAT_AC3:
return ENCODING_AC3;
case AUDIO_FORMAT_E_AC3:
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index ac00532..91b3278 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -832,6 +832,15 @@
return jStatus;
}
+static bool hasFormat(int* formats, size_t size, int format) {
+ for (size_t index = 0; index < size; index++) {
+ if (formats[index] == format) {
+ return true; // found
+ }
+ }
+ return false; // not found
+}
+
static jint convertAudioPortFromNative(JNIEnv *env,
jobject *jAudioPort, const struct audio_port *nAudioPort)
{
@@ -839,6 +848,7 @@
jintArray jSamplingRates = NULL;
jintArray jChannelMasks = NULL;
jintArray jChannelIndexMasks = NULL;
+ int* cFormats = NULL;
jintArray jFormats = NULL;
jobjectArray jGains = NULL;
jobject jHandle = NULL;
@@ -846,6 +856,7 @@
bool useInMask;
size_t numPositionMasks = 0;
size_t numIndexMasks = 0;
+ size_t numUniqueFormats = 0;
ALOGV("convertAudioPortFromNative id %d role %d type %d name %s",
nAudioPort->id, nAudioPort->role, nAudioPort->type, nAudioPort->name);
@@ -897,14 +908,22 @@
}
// formats
- jFormats = env->NewIntArray(nAudioPort->num_formats);
+ if (nAudioPort->num_formats != 0) {
+ cFormats = new int[nAudioPort->num_formats];
+ for (size_t index = 0; index < nAudioPort->num_formats; index++) {
+ int format = audioFormatFromNative(nAudioPort->formats[index]);
+ if (!hasFormat(cFormats, numUniqueFormats, format)) {
+ cFormats[numUniqueFormats++] = format;
+ }
+ }
+ }
+ jFormats = env->NewIntArray(numUniqueFormats);
if (jFormats == NULL) {
jStatus = (jint)AUDIO_JAVA_ERROR;
goto exit;
}
- for (size_t j = 0; j < nAudioPort->num_formats; j++) {
- jint jFormat = audioFormatFromNative(nAudioPort->formats[j]);
- env->SetIntArrayRegion(jFormats, j, 1, &jFormat);
+ if (numUniqueFormats != 0) {
+ env->SetIntArrayRegion(jFormats, 0, numUniqueFormats, cFormats);
}
// gains
@@ -1000,6 +1019,12 @@
if (jChannelMasks != NULL) {
env->DeleteLocalRef(jChannelMasks);
}
+ if (jChannelIndexMasks != NULL) {
+ env->DeleteLocalRef(jChannelIndexMasks);
+ }
+ if (cFormats != NULL) {
+ delete[] cFormats;
+ }
if (jFormats != NULL) {
env->DeleteLocalRef(jFormats);
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 65c064b..c2e8c8b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -242,6 +242,7 @@
<protected-broadcast android:name="android.intent.action.DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN" />
<protected-broadcast android:name="com.android.server.WifiManager.action.START_SCAN" />
+ <protected-broadcast android:name="com.android.server.WifiManager.action.START_PNO" />
<protected-broadcast android:name="com.android.server.WifiManager.action.DELAYED_DRIVER_STOP" />
<protected-broadcast android:name="android.net.wifi.WIFI_STATE_CHANGED" />
<protected-broadcast android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" />
@@ -316,8 +317,6 @@
<protected-broadcast android:name="android.intent.action.ACTION_SET_RADIO_CAPABILITY_FAILED" />
<protected-broadcast android:name="android.internal.policy.action.BURN_IN_PROTECTION" />
- <protected-broadcast android:name="android.service.persistentdata.action.WIPE_IF_ALLOWED" />
-
<protected-broadcast android:name="android.app.action.SYSTEM_UPDATE_POLICY_CHANGED" />
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
@@ -1342,6 +1341,11 @@
android:description="@string/permdesc_killBackgroundProcesses"
android:protectionLevel="normal" />
+ <!-- @SystemApi @hide Allows an application to retrieve a package's importance.
+ This permission is not available to third party applications. -->
+ <permission android:name="android.permission.GET_PACKAGE_IMPORTANCE"
+ android:protectionLevel="signature|system" />
+
<!-- ================================== -->
<!-- Permissions affecting the display of other applications -->
<!-- ================================== -->
@@ -2435,8 +2439,7 @@
android:backupAgent="com.android.server.backup.SystemBackupAgent"
android:killAfterRestore="false"
android:icon="@drawable/ic_launcher_android"
- android:supportsRtl="true"
- android:theme="@style/Theme.Material.DayNight.DarkActionBar">
+ android:supportsRtl="true">
<activity android:name="com.android.internal.app.ChooserActivity"
android:theme="@style/Theme.DeviceDefault.Resolver"
android:finishOnCloseSystemDialogs="true"
@@ -2469,7 +2472,7 @@
android:label="@string/managed_profile_label">
</activity-alias>
<activity android:name="com.android.internal.app.HeavyWeightSwitcherActivity"
- android:theme="@style/Theme.Material.DayNight.Dialog"
+ android:theme="@style/Theme.Material.Light.Dialog"
android:label="@string/heavy_weight_switcher_title"
android:finishOnCloseSystemDialogs="true"
android:excludeFromRecents="true"
@@ -2502,7 +2505,7 @@
<activity android:name="android.accounts.ChooseAccountActivity"
android:excludeFromRecents="true"
android:exported="true"
- android:theme="@style/Theme.Material.DayNight.Dialog"
+ android:theme="@style/Theme.Material.Light.Dialog"
android:label="@string/choose_account_label"
android:process=":ui">
</activity>
@@ -2510,14 +2513,14 @@
<activity android:name="android.accounts.ChooseTypeAndAccountActivity"
android:excludeFromRecents="true"
android:exported="true"
- android:theme="@style/Theme.Material.DayNight.Dialog"
+ android:theme="@style/Theme.Material.Light.Dialog"
android:label="@string/choose_account_label"
android:process=":ui">
</activity>
<activity android:name="android.accounts.ChooseAccountTypeActivity"
android:excludeFromRecents="true"
- android:theme="@style/Theme.Material.DayNight.Dialog"
+ android:theme="@style/Theme.Material.Light.Dialog"
android:label="@string/choose_account_label"
android:process=":ui">
</activity>
@@ -2525,19 +2528,19 @@
<activity android:name="android.accounts.CantAddAccountActivity"
android:excludeFromRecents="true"
android:exported="true"
- android:theme="@style/Theme.Material.DayNight.Dialog.NoActionBar"
+ android:theme="@style/Theme.Material.Light.Dialog.NoActionBar"
android:process=":ui">
</activity>
<activity android:name="android.accounts.GrantCredentialsPermissionActivity"
android:excludeFromRecents="true"
android:exported="true"
- android:theme="@style/Theme.Material.DayNight.DialogWhenLarge"
+ android:theme="@style/Theme.Material.Light.DialogWhenLarge"
android:process=":ui">
</activity>
<activity android:name="android.content.SyncActivityTooManyDeletes"
- android:theme="@style/Theme.Material.DayNight.Dialog"
+ android:theme="@style/Theme.Material.Light.Dialog"
android:label="@string/sync_too_many_deletes"
android:process=":ui">
</activity>
@@ -2557,7 +2560,7 @@
</activity>
<activity android:name="com.android.internal.app.NetInitiatedActivity"
- android:theme="@style/Theme.Material.DayNight.Dialog.Alert"
+ android:theme="@style/Theme.Material.Light.Dialog.Alert"
android:excludeFromRecents="true"
android:process=":ui">
</activity>
diff --git a/core/res/res/drawable/seekbar_track_material.xml b/core/res/res/drawable/seekbar_track_material.xml
index 6e40c48..01eb243 100644
--- a/core/res/res/drawable/seekbar_track_material.xml
+++ b/core/res/res/drawable/seekbar_track_material.xml
@@ -20,7 +20,7 @@
<shape android:shape="rectangle"
android:tint="?attr/colorControlNormal">
<size android:height="@dimen/seekbar_track_background_height_material" />
- <solid android:color="#ff000000" />
+ <solid android:color="@color/white_disabled_material" />
</shape>
</item>
<item android:id="@id/secondaryProgress"
diff --git a/core/res/res/drawable/spinner_background_material.xml b/core/res/res/drawable/spinner_background_material.xml
index 892dbc5..d37f5b7 100644
--- a/core/res/res/drawable/spinner_background_material.xml
+++ b/core/res/res/drawable/spinner_background_material.xml
@@ -17,22 +17,18 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingMode="stack"
android:paddingStart="0dp"
- android:paddingEnd="48dp"
+ android:paddingEnd="24dp"
android:paddingLeft="0dp"
android:paddingRight="0dp">
<item
android:gravity="end|center_vertical"
- android:width="48dp"
- android:height="48dp">
- <ripple
- android:color="?attr/colorControlHighlight"
- android:radius="24dp" />
- </item>
+ android:width="24dp"
+ android:height="24dp"
+ android:drawable="@drawable/control_background_40dp_material" />
<item
android:drawable="@drawable/ic_spinner_caret"
android:gravity="end|center_vertical"
android:width="24dp"
- android:height="24dp"
- android:end="12dp" />
+ android:height="24dp" />
</layer-list>
diff --git a/core/res/res/values-mcc302-mnc220/config.xml b/core/res/res/values-mcc302-mnc220/config.xml
index 9147cbf..09a63aa 100644
--- a/core/res/res/values-mcc302-mnc220/config.xml
+++ b/core/res/res/values-mcc302-mnc220/config.xml
@@ -38,7 +38,8 @@
note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
<string-array translatable="false" name="config_tether_apndata">
<item>[ApnSettingV3]TELUS ISP,isp.telus.com,,,,,,,,,302,220,,DUN,,,true,0,,,,,,,gid,54</item>
- <item>[ApnSettingV3]Tethered PC Mobile,isp.mb.com,,,,,,,,,302,220,,DUN,,,true,0,,,,,,,gid,50</item>
+ <item>[ApnSettingV3]Tethered Mobile Internet,isp.mb.com,,,,,,,,,302,220,,DUN,,,true,0,,,,,,,gid,50</item>
+ <item>[ApnSettingV3]Tethered Public Mobile,isp.mb.com,,,,,,,,,302,220,,DUN,,,true,0,,,,,,,gid,4D4F</item>
</string-array>
</resources>
diff --git a/core/res/res/values-mcc302-mnc720/config.xml b/core/res/res/values-mcc302-mnc720/config.xml
index a83107a..dcfa5c5 100644
--- a/core/res/res/values-mcc302-mnc720/config.xml
+++ b/core/res/res/values-mcc302-mnc720/config.xml
@@ -29,6 +29,8 @@
<string-array translatable="false" name="config_tether_apndata">
<item>Rogers LTE Tethering,ltedata.apn,,,,,,,,,302,720,,DUN</item>
<item>[ApnSettingV3]chatr Tethering,chatrisp.apn,,,,,,,,,302,720,,DUN,,,true,0,,,,,,,imsi,302720x94</item>
+ <item>[ApnSettingV3]Tbaytel Tethering,ltedata.apn,,,,,,,,,302,720,,DUN,IPV4V6,IP,true,0,,,,,,,gid,BA</item>
+ <item>[ApnSettingV3]Cityfone Tethering,ltedata.apn,,,,,,,,,302,720,,DUN,IPV4V6,IP,true,0,,,,,,,spn,CITYFONE</item>
</string-array>
<!-- Configure mobile network MTU. Carrier specific value is set here.
diff --git a/core/res/res/values-night/themes_material_daynight.xml b/core/res/res/values-night/themes_material_daynight.xml
deleted file mode 100644
index b344582..0000000
--- a/core/res/res/values-night/themes_material_daynight.xml
+++ /dev/null
@@ -1,117 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 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.
--->
-
-<!--
-===============================================================
- PLEASE READ
-===============================================================
-
-The Material themes must not be modified in order to pass CTS.
-Many related themes and styles depend on other values defined in this file.
-If you would like to provide custom themes and styles for your device,
-please see themes_device_defaults.xml.
-
-===============================================================
- PLEASE READ
-===============================================================
- -->
-<resources>
-
- <!-- Material theme (day/night version) for activities. -->
- <style name="Theme.Material.DayNight" parent="Theme.Material" />
-
- <!-- Variant of Material.DayNight that has a solid (opaque) action bar
- with an inverse color profile. The dark action bar sharply stands out against
- the light content (when applicable). -->
- <style name="Theme.Material.DayNight.DarkActionBar" parent="Theme.Material" />
-
- <!-- Variant of Material.DayNight with no action bar. -->
- <style name="Theme.Material.DayNight.NoActionBar" parent="Theme.Material.NoActionBar" />
-
- <!-- Variant of Material.DayNight that has no title bar and fills
- the entire screen. This theme
- sets {@link android.R.attr#windowFullscreen} to true. -->
- <style name="Theme.Material.DayNight.NoActionBar.Fullscreen" parent="Theme.Material.NoActionBar.Fullscreen" />
-
- <!-- Variant of Material.DayNight that has no title bar and fills
- the entire screen and extends into the display overscan region. This theme
- sets {@link android.R.attr#windowFullscreen} and {@link android.R.attr#windowOverscan}
- to true. -->
- <style name="Theme.Material.DayNight.NoActionBar.Overscan" parent="Theme.Material.NoActionBar.Overscan" />
-
- <!-- Variant of Material.DayNight that has no title bar and translucent
- system decor. This theme sets {@link android.R.attr#windowTranslucentStatus} and
- {@link android.R.attr#windowTranslucentNavigation} to true. -->
- <style name="Theme.Material.DayNight.NoActionBar.TranslucentDecor" parent="Theme.Material.NoActionBar.TranslucentDecor" />
-
- <!-- Default Material.DayNight theme for panel windows. This removes all extraneous
- window decorations, so you basically have an empty rectangle in which
- to place your content. It makes the window floating, with a transparent
- background, and turns off dimming behind the window. -->
- <style name="Theme.Material.DayNight.Panel" parent="Theme.Material.Panel" />
-
- <!-- Material theme (day/night version) for dialog windows and activities,
- which is used by the {@link android.app.Dialog} class. This changes
- the window to be floating (not fill the entire screen), and puts a
- frame around its contents. You can set this theme on an activity if
- you would like to make an activity that looks like a Dialog. -->
- <style name="Theme.Material.DayNight.Dialog" parent="Theme.Material.DayNight.BaseDialog" />
- <style name="Theme.Material.DayNight.BaseDialog" parent="Theme.Material.BaseDialog" />
-
- <!-- Variant of Theme.Material.DayNight.Dialog that has a nice minimum width for
- a regular dialog. -->
- <style name="Theme.Material.DayNight.Dialog.MinWidth" parent="Theme.Material.Dialog.MinWidth" />
-
- <!-- Variant of Theme.Material.DayNight.Dialog that does not include a title bar. -->
- <style name="Theme.Material.DayNight.Dialog.NoActionBar" parent="Theme.Material.Dialog.NoActionBar" />
-
- <!-- Variant of Theme.Material.DayNight.Dialog.NoActionBar that has a nice minimum width for
- a regular dialog. -->
- <style name="Theme.Material.DayNight.Dialog.NoActionBar.MinWidth" parent="Theme.Material.Dialog.NoActionBar.MinWidth" />
-
- <!-- Variant of Theme.Material.DayNight.Dialog that has a fixed size. -->
- <style name="Theme.Material.DayNight.Dialog.FixedSize" parent="Theme.Material.Dialog.FixedSize" />
-
- <!-- Variant of Theme.Material.DayNight.Dialog.NoActionBar that has a fixed size. -->
- <style name="Theme.Material.DayNight.Dialog.NoActionBar.FixedSize" parent="Theme.Material.Dialog.NoActionBar.FixedSize" />
-
- <!-- Theme for a window that will be displayed either full-screen on
- smaller screens (small, normal) or as a dialog on larger screens
- (large, xlarge). -->
- <style name="Theme.Material.DayNight.DialogWhenLarge" parent="Theme.Material.DialogWhenLarge" />
-
- <!-- Theme for a window with a dark action bar that will be displayed
- either full-screen on smaller screens (small, normal) or as a dialog
- on larger screens (large, xlarge). -->
- <style name="Theme.Material.DayNight.DialogWhenLarge.DarkActionBar" parent="Theme.Material.DialogWhenLarge" />
-
- <!-- Theme for a window without an action bar that will be displayed either full-screen
- on smaller screens (small, normal) or as a dialog on larger screens
- (large, xlarge). -->
- <style name="Theme.Material.DayNight.DialogWhenLarge.NoActionBar" parent="Theme.Material.DialogWhenLarge.NoActionBar" />
-
- <!-- Theme for a presentation window on a secondary display. -->
- <style name="Theme.Material.DayNight.Dialog.Presentation" parent="Theme.Material.Dialog.Presentation" />
-
- <!-- Material user theme for alert dialog windows, which is used by the
- {@link android.app.AlertDialog} class. -->
- <style name="Theme.Material.DayNight.Dialog.Alert" parent="Theme.Material.DayNight.Dialog.BaseAlert" />
- <style name="Theme.Material.DayNight.Dialog.BaseAlert" parent="Theme.Material.Dialog.BaseAlert" />
-
- <style name="Theme.Material.DayNight.SearchBar" parent="Theme.Material.SearchBar" />
- <style name="Theme.Material.DayNight.CompactMenu" parent="Theme.Material.CompactMenu" />
-
-</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index c08d511..33c9c60b 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4384,7 +4384,7 @@
<enum name="simple" value="0" />
<!-- Line breaking uses high-quality strategy, including hyphenation. -->
<enum name="high_quality" value="1" />
- <!-- Line breaking stratgegy balances line lengths. -->
+ <!-- Line breaking strategy balances line lengths. -->
<enum name="balanced" value="2" />
</attr>
<!-- Frequency of automatic hyphenation. -->
@@ -4398,10 +4398,10 @@
screens with limited space for text. -->
<enum name="full" value="2" />
</attr>
- <!-- Array of indents, one dimension value per line, left side. -->
- <attr name="leftIndents" format="reference" />
- <!-- Array of indents, one dimension value per line, right side. -->
- <attr name="rightIndents" format="reference" />
+ <!-- Placeholder for a deleted attribute. This should be removed before M release. -->
+ <attr name="__removeBeforeMRelease_leftIndents" format="reference" />
+ <!-- Placeholder for a deleted attribute. This should be removed before M release. -->
+ <attr name="__removeBeforeMRelease_rightIndents" format="reference" />
</declare-styleable>
<declare-styleable name="TextViewAppearance">
<!-- Base text color, typeface, size, and style. -->
@@ -7775,6 +7775,16 @@
<!-- Text to set as the content description for the navigation button
located at the start of the toolbar. -->
<attr name="navigationContentDescription" format="string" />
+ <!-- Drawable to set as the logo that appears at the starting side of
+ the Toolbar, just after the navigation button. -->
+ <attr name="logo" />
+ <!-- A content description string to describe the appearance of the
+ associated logo image. -->
+ <attr name="logoDescription" format="string" />
+ <!-- A color to apply to the title string. -->
+ <attr name="titleTextColor" format="color" />
+ <!-- A color to apply to the subtitle string. -->
+ <attr name="subtitleTextColor" format="color" />
</declare-styleable>
<declare-styleable name="Toolbar_LayoutParams">
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index e60a48d..7e74680 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -399,6 +399,7 @@
<dimen name="floating_toolbar_maximum_overflow_height">192dp</dimen>
<dimen name="floating_toolbar_horizontal_margin">16dp</dimen>
<dimen name="floating_toolbar_vertical_margin">8dp</dimen>
+ <dimen name="content_rect_bottom_clip_allowance">20dp</dimen>
<dimen name="chooser_grid_padding">0dp</dimen>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index bbe27a4..ab798bb 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2631,27 +2631,41 @@
<public type="attr" name="fullBackupContent" />
<public type="style" name="Widget.Material.Button.Colored" />
- <public type="style" name="Theme.Material.DayNight" />
- <public type="style" name="Theme.Material.DayNight.DarkActionBar" />
- <public type="style" name="Theme.Material.DayNight.Dialog" />
- <public type="style" name="Theme.Material.DayNight.Dialog.Alert" />
- <public type="style" name="Theme.Material.DayNight.Dialog.MinWidth" />
- <public type="style" name="Theme.Material.DayNight.Dialog.NoActionBar" />
- <public type="style" name="Theme.Material.DayNight.Dialog.NoActionBar.MinWidth" />
- <public type="style" name="Theme.Material.DayNight.Dialog.Presentation" />
- <public type="style" name="Theme.Material.DayNight.DialogWhenLarge" />
- <public type="style" name="Theme.Material.DayNight.DialogWhenLarge.NoActionBar" />
- <public type="style" name="Theme.Material.DayNight.NoActionBar" />
- <public type="style" name="Theme.Material.DayNight.NoActionBar.Fullscreen" />
- <public type="style" name="Theme.Material.DayNight.NoActionBar.Overscan" />
- <public type="style" name="Theme.Material.DayNight.NoActionBar.TranslucentDecor" />
- <public type="style" name="Theme.Material.DayNight.Panel" />
+
+ <style name="__reserved8" />
+ <public type="style" name="__reserved8" />
+ <style name="__reserved9" />
+ <public type="style" name="__reserved9" />
+ <style name="__reserved10" />
+ <public type="style" name="__reserved10" />
+ <style name="__reserved11" />
+ <public type="style" name="__reserved11" />
+ <style name="__reserved12" />
+ <public type="style" name="__reserved12" />
+ <style name="__reserved13" />
+ <public type="style" name="__reserved13" />
+ <style name="__reserved14" />
+ <public type="style" name="__reserved14" />
+ <style name="__reserved15" />
+ <public type="style" name="__reserved15" />
+ <style name="__reserved16" />
+ <public type="style" name="__reserved16" />
+ <style name="__reserved17" />
+ <public type="style" name="__reserved17" />
+ <style name="__reserved18" />
+ <public type="style" name="__reserved18" />
+ <style name="__reserved19" />
+ <public type="style" name="__reserved19" />
+ <style name="__reserved20" />
+ <public type="style" name="__reserved20" />
+ <style name="__reserved21" />
+ <public type="style" name="__reserved21" />
+ <style name="__reserved22" />
+ <public type="style" name="__reserved22" />
<public type="style" name="Theme.Material.Light.LightStatusBar" />
<public type="style" name="ThemeOverlay.Material.Dialog" />
<public type="style" name="TextAppearance.Material.Widget.Button.Inverse" />
<public type="style" name="ThemeOverlay.Material.Dialog.Alert" />
- <public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" />
- <public type="style" name="Theme.Material.DayNight.DialogWhenLarge.DarkActionBar" />
<public type="id" name="pasteAsPlainText" />
<public type="id" name="undo" />
@@ -2683,8 +2697,9 @@
<public type="attr" name="lockTaskMode" />
- <public type="attr" name="leftIndents" />
- <public type="attr" name="rightIndents" />
+ <!-- Placeholder for a removed attribute. Remove this before M release. -->
+ <public type="attr" name="__removeBeforeMRelease_leftIndents" />
+ <public type="attr" name="__removeBeforeMRelease_rightIndents" />
<public type="attr" name="showForAllUsers" />
@@ -2699,4 +2714,7 @@
<public type="attr" name="scrollIndicators" />
<public type="attr" name="hyphenationFrequency" />
<public type="attr" name="fingerprintAuthDrawable" />
+ <public type="attr" name="logoDescription" />
+ <public type="attr" name="titleTextColor" />
+ <public type="attr" name="subtitleTextColor" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 510f6a5..ea0d349 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -537,10 +537,10 @@
<!-- Label for the Android system components when they are shown to the user. -->
<string name="android_system_label">Android System</string>
- <!-- Label for the user owner in the intent forwarding app. -->
- <string name="user_owner_label">Personal apps</string>
+ <!-- Label for the user owner in the intent forwarding app. [CHAR LIMIT=15] -->
+ <string name="user_owner_label">Personal</string>
- <!-- Label for a corporate profile in the intent forwarding app. -->
+ <!-- Label for a corporate profile in the intent forwarding app. [CHAR LIMIT=15] -->
<string name="managed_profile_label">Work</string>
<!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 5ba57c4..4160e0e 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2274,6 +2274,7 @@
<java-symbol type="dimen" name="floating_toolbar_maximum_overflow_height" />
<java-symbol type="dimen" name="floating_toolbar_horizontal_margin" />
<java-symbol type="dimen" name="floating_toolbar_vertical_margin" />
+ <java-symbol type="dimen" name="content_rect_bottom_clip_allowance" />
<java-symbol type="string" name="date_picker_prev_month_button" />
<java-symbol type="string" name="date_picker_next_month_button" />
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 295b453..9d3a7ef 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -1281,7 +1281,7 @@
</style>
<!-- Default theme for Settings and activities launched from Settings. -->
- <style name="Theme.Material.Settings" parent="Theme.Material.DayNight.DarkActionBar">
+ <style name="Theme.Material.Settings" parent="Theme.Material.Light.DarkActionBar">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
@@ -1291,7 +1291,7 @@
</style>
<!-- Default theme for Settings and activities launched from Settings. -->
- <style name="Theme.Material.Settings.NoActionBar" parent="Theme.Material.DayNight.NoActionBar">
+ <style name="Theme.Material.Settings.NoActionBar" parent="Theme.Material.Light.NoActionBar">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
@@ -1299,42 +1299,40 @@
<item name="searchDialogTheme">@style/Theme.Material.Settings.SearchBar</item>
<item name="panelMenuListTheme">@style/Theme.Material.Settings.CompactMenu</item>
</style>
-
- <style name="Theme.Material.Settings.BaseDialog" parent="Theme.Material.DayNight.BaseDialog">
+ <style name="Theme.Material.Settings.BaseDialog" parent="Theme.Material.Light.BaseDialog">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
</style>
<style name="Theme.Material.Settings.Dialog" parent="Theme.Material.Settings.BaseDialog" />
- <style name="Theme.Material.Settings.Dialog.BaseAlert" parent="Theme.Material.DayNight.Dialog.BaseAlert">
+ <style name="Theme.Material.Settings.Dialog.BaseAlert" parent="Theme.Material.Light.Dialog.BaseAlert">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
</style>
<style name="Theme.Material.Settings.Dialog.Alert" parent="Theme.Material.Settings.Dialog.BaseAlert" />
- <style name="Theme.Material.Settings.DialogWhenLarge" parent="Theme.Material.DayNight.DialogWhenLarge.DarkActionBar">
+ <style name="Theme.Material.Settings.DialogWhenLarge" parent="Theme.Material.Light.DialogWhenLarge.DarkActionBar">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
</style>
- <style name="Theme.Material.Settings.DialogWhenLarge.NoActionBar" parent="Theme.Material.DayNight.DialogWhenLarge.NoActionBar">
+ <style name="Theme.Material.Settings.DialogWhenLarge.NoActionBar" parent="Theme.Material.Light.DialogWhenLarge.NoActionBar">
+ <item name="colorPrimary">@color/material_blue_grey_900</item>
+ <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+ </style>
+ <style name="Theme.Material.Settings.Dialog.Presentation" parent="Theme.Material.Light.Dialog.Presentation">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
</style>
- <style name="Theme.Material.Settings.Dialog.Presentation" parent="Theme.Material.DayNight.Dialog.Presentation">
+ <style name="Theme.Material.Settings.SearchBar" parent="Theme.Material.Light.SearchBar">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
</style>
- <style name="Theme.Material.Settings.SearchBar" parent="Theme.Material.DayNight.SearchBar">
- <item name="colorPrimary">@color/material_blue_grey_900</item>
- <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
- </style>
-
- <style name="Theme.Material.Settings.CompactMenu" parent="Theme.Material.DayNight.CompactMenu">
+ <style name="Theme.Material.Settings.CompactMenu" parent="Theme.Material.Light.CompactMenu">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
</style>
diff --git a/core/res/res/values/themes_material_daynight.xml b/core/res/res/values/themes_material_daynight.xml
deleted file mode 100644
index 4ecca6b..0000000
--- a/core/res/res/values/themes_material_daynight.xml
+++ /dev/null
@@ -1,117 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 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.
--->
-
-<!--
-===============================================================
- PLEASE READ
-===============================================================
-
-The Material themes must not be modified in order to pass CTS.
-Many related themes and styles depend on other values defined in this file.
-If you would like to provide custom themes and styles for your device,
-please see themes_device_defaults.xml.
-
-===============================================================
- PLEASE READ
-===============================================================
- -->
-<resources>
-
- <!-- Material theme (day/night vesion) for activities. -->
- <style name="Theme.Material.DayNight" parent="Theme.Material.Light" />
-
- <!-- Variant of Material.DayNight that has a solid (opaque) action bar
- with an inverse color profile. The dark action bar sharply stands out against
- the light content (when applicable). -->
- <style name="Theme.Material.DayNight.DarkActionBar" parent="Theme.Material.Light.DarkActionBar" />
-
- <!-- Variant of Material.DayNight with no action bar. -->
- <style name="Theme.Material.DayNight.NoActionBar" parent="Theme.Material.Light.NoActionBar" />
-
- <!-- Variant of Material.DayNight that has no title bar and fills
- the entire screen. This theme
- sets {@link android.R.attr#windowFullscreen} to true. -->
- <style name="Theme.Material.DayNight.NoActionBar.Fullscreen" parent="Theme.Material.Light.NoActionBar.Fullscreen" />
-
- <!-- Variant of Material.DayNight that has no title bar and fills
- the entire screen and extends into the display overscan region. This theme
- sets {@link android.R.attr#windowFullscreen} and {@link android.R.attr#windowOverscan}
- to true. -->
- <style name="Theme.Material.DayNight.NoActionBar.Overscan" parent="Theme.Material.Light.NoActionBar.Overscan" />
-
- <!-- Variant of Material.DayNight that has no title bar and translucent
- system decor. This theme sets {@link android.R.attr#windowTranslucentStatus} and
- {@link android.R.attr#windowTranslucentNavigation} to true. -->
- <style name="Theme.Material.DayNight.NoActionBar.TranslucentDecor" parent="Theme.Material.Light.NoActionBar.TranslucentDecor" />
-
- <!-- Default Material.DayNight theme for panel windows. This removes all extraneous
- window decorations, so you basically have an empty rectangle in which
- to place your content. It makes the window floating, with a transparent
- background, and turns off dimming behind the window. -->
- <style name="Theme.Material.DayNight.Panel" parent="Theme.Material.Light.Panel" />
-
- <!-- Material theme (day/night vesion) for dialog windows and activities,
- which is used by the {@link android.app.Dialog} class. This changes
- the window to be floating (not fill the entire screen), and puts a
- frame around its contents. You can set this theme on an activity if
- you would like to make an activity that looks like a Dialog. -->
- <style name="Theme.Material.DayNight.Dialog" parent="Theme.Material.DayNight.BaseDialog" />
- <style name="Theme.Material.DayNight.BaseDialog" parent="Theme.Material.Light.BaseDialog" />
-
- <!-- Variant of Theme.Material.DayNight.Dialog that has a nice minimum width for
- a regular dialog. -->
- <style name="Theme.Material.DayNight.Dialog.MinWidth" parent="Theme.Material.Light.Dialog.MinWidth" />
-
- <!-- Variant of Theme.Material.DayNight.Dialog that does not include a title bar. -->
- <style name="Theme.Material.DayNight.Dialog.NoActionBar" parent="Theme.Material.Light.Dialog.NoActionBar" />
-
- <!-- Variant of Theme.Material.DayNight.Dialog.NoActionBar that has a nice minimum width for
- a regular dialog. -->
- <style name="Theme.Material.DayNight.Dialog.NoActionBar.MinWidth" parent="Theme.Material.Light.Dialog.NoActionBar.MinWidth" />
-
- <!-- Variant of Theme.Material.DayNight.Dialog that has a fixed size. -->
- <style name="Theme.Material.DayNight.Dialog.FixedSize" parent="Theme.Material.Light.Dialog.FixedSize" />
-
- <!-- Variant of Theme.Material.DayNight.Dialog.NoActionBar that has a fixed size. -->
- <style name="Theme.Material.DayNight.Dialog.NoActionBar.FixedSize" parent="Theme.Material.Light.Dialog.NoActionBar.FixedSize" />
-
- <!-- Theme for a window that will be displayed either full-screen on
- smaller screens (small, normal) or as a dialog on larger screens
- (large, xlarge). -->
- <style name="Theme.Material.DayNight.DialogWhenLarge" parent="Theme.Material.Light.DialogWhenLarge" />
-
- <!-- Theme for a window with a dark action bar that will be displayed
- either full-screen on smaller screens (small, normal) or as a dialog
- on larger screens (large, xlarge). -->
- <style name="Theme.Material.DayNight.DialogWhenLarge.DarkActionBar" parent="Theme.Material.Light.DialogWhenLarge.DarkActionBar" />
-
- <!-- Theme for a window without an action bar that will be displayed either full-screen
- on smaller screens (small, normal) or as a dialog on larger screens
- (large, xlarge). -->
- <style name="Theme.Material.DayNight.DialogWhenLarge.NoActionBar" parent="Theme.Material.Light.DialogWhenLarge.NoActionBar" />
-
- <!-- Theme for a presentation window on a secondary display. -->
- <style name="Theme.Material.DayNight.Dialog.Presentation" parent="Theme.Material.Light.Dialog.Presentation" />
-
- <!-- Material user theme for alert dialog windows, which is used by the
- {@link android.app.AlertDialog} class. -->
- <style name="Theme.Material.DayNight.Dialog.Alert" parent="Theme.Material.DayNight.Dialog.BaseAlert" />
- <style name="Theme.Material.DayNight.Dialog.BaseAlert" parent="Theme.Material.Light.Dialog.BaseAlert" />
-
- <style name="Theme.Material.DayNight.SearchBar" parent="Theme.Material.Light.SearchBar" />
- <style name="Theme.Material.DayNight.CompactMenu" parent="Theme.Material.Light.CompactMenu" />
-
-</resources>
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 9a834506..7b1169f 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -30,21 +30,22 @@
-sdk.linux_download=android-sdk_r24.3.2-linux.tgz
-sdk.linux_bytes=309138263
-sdk.linux_checksum=4a10e62c5d88fd6c2a69db12348cbe168228b98f
+sdk.linux_download=android-sdk_r24.3.3-linux.tgz
+sdk.linux_bytes=309109716
+sdk.linux_checksum=cd4cab76c2e3d926b3495c26ec56c831ba77d0d0
-sdk.mac_download=android-sdk_r24.3.2-macosx.zip
-sdk.mac_bytes=98329772
-sdk.mac_checksum=8609b92e26e9bd5796f771138c6b222b6c0cb474
+sdk.mac_download=android-sdk_r24.3.3-macosx.zip
+sdk.mac_bytes=98330824
+sdk.mac_checksum=41f0f3e76d6868018740e654aefb04fd765c357d
-sdk.win_download=android-sdk_r24.3.2-windows.zip
-sdk.win_bytes=187488291
-sdk.win_checksum=bcfe3c41ea7e33a29ad6f358adbdf977008be80a
+sdk.win_download=android-sdk_r24.3.3-windows.zip
+sdk.win_bytes=187480692
+sdk.win_checksum=b6a4899efbf20fc593042f1515446c6630ba502e
-sdk.win_installer=installer_r24.3.2-windows.exe
-sdk.win_installer_bytes=139471724
-sdk.win_installer_checksum=8f9d0ae9fdb37973ed62d6e93975ff375beb5542
+
+sdk.win_installer=installer_r24.3.3-windows.exe
+sdk.win_installer_bytes=139463749
+sdk.win_installer_checksum=bbdae40a7665e55b3cdb1fbae865986e6cd3df14
diff --git a/docs/html/tools/sdk/tools-notes.jd b/docs/html/tools/sdk/tools-notes.jd
index 326fbe2..934b262 100644
--- a/docs/html/tools/sdk/tools-notes.jd
+++ b/docs/html/tools/sdk/tools-notes.jd
@@ -25,6 +25,36 @@
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>SDK Tools, Revision 24.3.3</a> <em>(June 2015)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+
+ <dl>
+ <dt>Dependencies:</dt>
+
+ <dd>
+ <ul>
+ <li>Android SDK Platform-tools revision 19 or later.</li>
+ </ul>
+ </dd>
+
+ <dt>General Notes:</dt>
+ <dd>
+ <ul>
+ <li>Fixed issues with using Ant build tasks with the Eclipse ADT build structure. </li>
+ <li>Fixed the emulator boot problem on Mac OS X 10.8.5.</li>
+ </ul>
+ </dd>
+ </div>
+</div>
+
+
+
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
alt=""/>SDK Tools, Revision 24.3.2</a> <em>(June 2015)</em>
</p>
diff --git a/docs/html/training/articles/keystore.jd b/docs/html/training/articles/keystore.jd
index fca958e..52cb13e 100644
--- a/docs/html/training/articles/keystore.jd
+++ b/docs/html/training/articles/keystore.jd
@@ -32,7 +32,7 @@
keystore, they can be used for cryptographic operations with the key material
remaining non-exportable. Moreover, it offers facilities to restrict when and
how keys can be used, such as requiring user authentication for key use or
- restricting encryption keys to be used only in certain block modes. See
+ restricting keys to be used only in certain cryptographic modes. See
<a href="#SecurityFeatures">Security Features</a> section for more information.</p>
<p>The Keystore system is used by the {@link
@@ -48,7 +48,8 @@
mitigates unauthorized use of key material outside of the Android device by preventing extraction of
the key material from application processes and from the Android device as a whole. Secondly,
Android KeyStore mitigates unauthorized use of key material on the Android device by making apps
-specify authorized uses of their keys and then enforcing these restrictions.
+specify authorized uses of their keys and then enforcing these restrictions outside of the apps'
+processes.
<h3 id="ExtractionPrevention">Extraction Prevention</h3>
@@ -78,14 +79,16 @@
To mitigate unauthorized use of keys on the Android device, Android Keystore lets apps specify
authorized uses of their keys when generating or importing the keys. Once a key is generated or
imported, its authorizations can not be changed. Authorizations are then enforced by the Android
-Keystore whenever the key is used.
+Keystore whenever the key is used. This is an advanced security feature which is generally useful
+only if your requirements are that a compromise of your application process after key
+generation/import (but not before or during) cannot lead to unauthorized uses of the key.
<p>Supported key use authorizations fall into the following categories:
<ul>
<li><em>cryptography</em>: authorized key algorithm, operations or purposes (encrypt, decrypt, sign,
- verify), padding schemes, block modes, digests with which the key can be used</li>
+ verify), padding schemes, block modes, digests with which the key can be used;</li>
<li><em>temporal validity interval</em>: interval of time during which the key is authorized for
- use</li>
+ use;</li>
<li><em>user authentication</em>: the key can only be used if the user has been authenticated
recently enough. See <a href="#UserAuthentication">Requiring User Authentication For Key Use</a>.
</li>
@@ -181,23 +184,33 @@
<h3 id="UserAuthentication">Requiring User Authentication For Key Use</h3>
<p>When generating or importing a key into the {@code AndroidKeyStore} you can specify that the key
-can only be used if user has been authenticated. The user is authenticated using a subset of their
-secure lock screen credentials. This is a security measure which makes it possible to generate
-cryptographic assertions about the user having been authenticated.
+is only authorized to be used if the user has been authenticated. The user is authenticated using a
+subset of their secure lock screen credentials (pattern/PIN/password, fingerprint).
-<p>When a key is configured to require user authentication, it is also configured to operate in one
-of the two modes:
+<p>This is an advanced security feature which is generally useful only if your requirements are that
+a compromise of your application process after key generation/import (but not before or during)
+cannot bypass the requirement for the user to be authenticated to use the key.
+
+<p>When a key is authorized to be used only if the user has been authenticated, it is configured to
+operate in one of the two modes:
<ul>
-<li>User authentication is valid for a duration of time. All keys in this mode are authorized
- for use as soon as the user unlocks the secure lock screen or confirms their secure lock screen
- credentials using the {@link android.app.KeyguardManager#createConfirmDeviceCredentialIntent(CharSequence, CharSequence) KeyguardManager.createConfirmDeviceCredentialIntent}
- flow. Each key specifies for how long the authorization remains valid for that key. Such keys
- can only be generated or imported if the secure lock screen is enabled (see {@link android.app.KeyguardManager#isDeviceSecure() KeyguardManager.isDeviceSecure()}).
- These keys become permanently invalidated once the secure lock screen is disabled or forcibly
- reset (e.g. by a Device Admin).</li>
-<li>User authentication is required for every use of the key. In this mode, a specific operation
- involving a specific key is authorized by the user. Currently, the only means of such
- authorization is fingerprint authentication: {@link android.hardware.fingerprint.FingerprintManager#authenticate(CryptoObject, CancellationSignal, int, AuthenticationCallback, Handler) FingerprintManager.authenticate}.
- Such keys can only be generated or imported if at least one fingerprint is enrolled (see {@link android.hardware.fingerprint.FingerprintManager#hasEnrolledFingerprints() FingerprintManager.hasEnrolledFingerprints}).
- These keys become permanently invalidated once all fingerprints are unenrolled.</li>
-</ul>
+<li>User authentication authorizes the use of keys for a duration of time. All keys in this mode are
+ authorized for use as soon as the user unlocks the secure lock screen or confirms their secure
+ lock screen credential using the
+ {@link android.app.KeyguardManager#createConfirmDeviceCredentialIntent(CharSequence, CharSequence) KeyguardManager.createConfirmDeviceCredentialIntent}
+ flow. The duration for which the authorization remains valid is specific to each key, as specified
+ using {@code setUserAuthenticationValidityDurationSeconds} during key generation or import. Such
+ keys can only be generated or imported if the secure lock screen is enabled (see
+ {@link android.app.KeyguardManager#isDeviceSecure() KeyguardManager.isDeviceSecure()}). These keys
+ become permanently invalidated once the secure lock screen is disabled (reconfigured to None,
+ Swipe or other mode which does not authenticate the user) or forcibly reset (e.g. by a Device
+ Administrator).</li>
+<li>User authentication authorizes a specific cryptographic operation associated with one key. In
+ this mode, each operation involving such a key must be individually authorized by the user.
+ Currently, the only means of such authorization is fingerprint authentication:
+ {@link android.hardware.fingerprint.FingerprintManager#authenticate(CryptoObject, CancellationSignal, int, AuthenticationCallback, Handler) FingerprintManager.authenticate}.
+ Such keys can only be generated or imported if at least one fingerprint is enrolled (see
+ {@link android.hardware.fingerprint.FingerprintManager#hasEnrolledFingerprints() FingerprintManager.hasEnrolledFingerprints}).
+ These keys become permanently invalidated once a new fingerprint is enrolled or all fingerprints
+ are unenrolled.</li>
+</ul>
\ No newline at end of file
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index a0c407f..f059727 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -363,7 +363,7 @@
}
@Override
- public boolean getDither() {
+ public boolean isDither() {
return mBitmapState.mPaint.isDither();
}
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 415af0d..5e62aea 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -279,7 +279,7 @@
* @return whether this drawable dithers its colors
* @see #setDither(boolean)
*/
- public boolean getDither() {
+ public boolean isDither() {
return false;
}
@@ -433,7 +433,7 @@
/**
* Set the layout direction for this drawable. Should be a resolved
- * layout direction, as the Drawable as no capacity to do the resolution on
+ * layout direction, as the Drawable has no capacity to do the resolution on
* its own.
*
* @param layoutDirection the resolved layout direction for the drawable,
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 8b801c3..1759f53 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -167,7 +167,7 @@
}
@Override
- public boolean getDither() {
+ public boolean isDither() {
return mDrawableContainerState.mDither;
}
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index ed47eed..626991d 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -826,7 +826,7 @@
}
@Override
- public boolean getDither() {
+ public boolean isDither() {
return mGradientState.mDither;
}
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index 7b4329a..85db6a1 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -29,6 +29,7 @@
import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
import android.util.Log;
import java.io.DataInputStream;
@@ -258,16 +259,21 @@
return new BitmapDrawable(context.getResources(), getBitmap());
case TYPE_RESOURCE:
if (getResources() == null) {
- if (getResPackage() == null || "android".equals(getResPackage())) {
+ // figure out where to load resources from
+ String resPackage = getResPackage();
+ if (TextUtils.isEmpty(resPackage)) {
+ // if none is specified, try the given context
+ resPackage = context.getPackageName();
+ }
+ if ("android".equals(resPackage)) {
mObj1 = Resources.getSystem();
} else {
final PackageManager pm = context.getPackageManager();
try {
- mObj1 = pm.getResourcesForApplication(getResPackage());
+ mObj1 = pm.getResourcesForApplication(resPackage);
} catch (PackageManager.NameNotFoundException e) {
- Log.e(TAG, String.format("Unable to find pkg=%s",
- getResPackage()),
- e);
+ Log.e(TAG, String.format("Unable to find pkg=%s for icon %s",
+ resPackage, this), e);
break;
}
}
@@ -320,12 +326,15 @@
*/
public Drawable loadDrawableAsUser(Context context, int userId) {
if (mType == TYPE_RESOURCE) {
- if (getResources() == null
- && getResPackage() != null
- && !(getResPackage().equals("android"))) {
+ String resPackage = getResPackage();
+ if (TextUtils.isEmpty(resPackage)) {
+ resPackage = context.getPackageName();
+ }
+ if (getResources() == null && !(getResPackage().equals("android"))) {
final PackageManager pm = context.getPackageManager();
try {
- mObj1 = pm.getResourcesForApplicationAsUser(getResPackage(), userId);
+ // assign getResources() as the correct user
+ mObj1 = pm.getResourcesForApplicationAsUser(resPackage, userId);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, String.format("Unable to find pkg=%s user=%d",
getResPackage(),
@@ -410,6 +419,9 @@
* @param resId ID of the drawable resource
*/
public static Icon createWithResource(Context context, @DrawableRes int resId) {
+ if (context == null) {
+ throw new IllegalArgumentException("Context must not be null.");
+ }
final Icon rep = new Icon(TYPE_RESOURCE);
rep.mInt1 = resId;
rep.mString1 = context.getPackageName();
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 5c00a23..90891f6 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -1248,12 +1248,12 @@
}
@Override
- public boolean getDither() {
+ public boolean isDither() {
final Drawable dr = getFirstNonNullDrawable();
if (dr != null) {
- return dr.getDither();
+ return dr.isDither();
} else {
- return super.getDither();
+ return super.isDither();
}
}
@@ -1537,8 +1537,23 @@
continue;
}
+ // Take the resolved layout direction into account. If start / end
+ // padding are defined, they will be resolved (hence overriding) to
+ // left / right or right / left depending on the resolved layout
+ // direction. If start / end padding are not defined, use the
+ // left / right ones.
+ final int insetL, insetR;
+ final int layoutDirection = getLayoutDirection();
+ if (layoutDirection == LayoutDirection.RTL) {
+ insetL = r.mInsetE == UNDEFINED_INSET ? r.mInsetL : r.mInsetE;
+ insetR = r.mInsetS == UNDEFINED_INSET ? r.mInsetR : r.mInsetS;
+ } else {
+ insetL = r.mInsetS == UNDEFINED_INSET ? r.mInsetL : r.mInsetS;
+ insetR = r.mInsetE == UNDEFINED_INSET ? r.mInsetR : r.mInsetE;
+ }
+
final int minWidth = r.mWidth < 0 ? r.mDrawable.getIntrinsicWidth() : r.mWidth;
- final int w = minWidth + r.mInsetL + r.mInsetR + padL + padR;
+ final int w = minWidth + insetL + insetR + padL + padR;
if (w > width) {
width = w;
}
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 0b7869b..adf53e3 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -374,7 +374,7 @@
}
@Override
- public boolean getDither() {
+ public boolean isDither() {
return mPaint == null ? DEFAULT_DITHER : mPaint.isDither();
}
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index 334b3bd..a669d3c 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -328,7 +328,7 @@
}
@Override
- public boolean getDither() {
+ public boolean isDither() {
return mShapeState.mPaint.isDither();
}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java
new file mode 100644
index 0000000..f412743
--- /dev/null
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java
@@ -0,0 +1,442 @@
+/*
+ * Copyright (C) 2015 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.security.keystore;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.IBinder;
+import android.security.KeyStore;
+import android.security.KeyStoreException;
+import android.security.keymaster.KeymasterArguments;
+import android.security.keymaster.KeymasterDefs;
+import android.security.keymaster.OperationResult;
+import android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.Stream;
+
+import libcore.util.EmptyArray;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.ProviderException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.util.Arrays;
+
+import javax.crypto.CipherSpi;
+import javax.crypto.spec.GCMParameterSpec;
+
+/**
+ * Base class for Android Keystore authenticated AES {@link CipherSpi} implementations.
+ *
+ * @hide
+ */
+abstract class AndroidKeyStoreAuthenticatedAESCipherSpi extends AndroidKeyStoreCipherSpiBase {
+
+ abstract static class GCM extends AndroidKeyStoreAuthenticatedAESCipherSpi {
+ private static final int MIN_SUPPORTED_TAG_LENGTH_BITS = 96;
+ private static final int MAX_SUPPORTED_TAG_LENGTH_BITS = 128;
+ private static final int DEFAULT_TAG_LENGTH_BITS = 128;
+ private static final int IV_LENGTH_BYTES = 12;
+
+ private int mTagLengthBits = DEFAULT_TAG_LENGTH_BITS;
+
+ GCM(int keymasterPadding) {
+ super(KeymasterDefs.KM_MODE_GCM, keymasterPadding);
+ }
+
+ @Override
+ protected final void resetAll() {
+ mTagLengthBits = DEFAULT_TAG_LENGTH_BITS;
+ super.resetAll();
+ }
+
+ @Override
+ protected final void resetWhilePreservingInitState() {
+ super.resetWhilePreservingInitState();
+ }
+
+ @Override
+ protected final void initAlgorithmSpecificParameters() throws InvalidKeyException {
+ if (!isEncrypting()) {
+ throw new InvalidKeyException("IV required when decrypting"
+ + ". Use IvParameterSpec or AlgorithmParameters to provide it.");
+ }
+ }
+
+ @Override
+ protected final void initAlgorithmSpecificParameters(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException {
+ // IV is used
+ if (params == null) {
+ if (!isEncrypting()) {
+ // IV must be provided by the caller
+ throw new InvalidAlgorithmParameterException(
+ "GCMParameterSpec must be provided when decrypting");
+ }
+ return;
+ }
+ if (!(params instanceof GCMParameterSpec)) {
+ throw new InvalidAlgorithmParameterException("Only GCMParameterSpec supported");
+ }
+ GCMParameterSpec spec = (GCMParameterSpec) params;
+ byte[] iv = spec.getIV();
+ if (iv == null) {
+ throw new InvalidAlgorithmParameterException("Null IV in GCMParameterSpec");
+ } else if (iv.length != IV_LENGTH_BYTES) {
+ throw new InvalidAlgorithmParameterException("Unsupported IV length: "
+ + iv.length + " bytes. Only " + IV_LENGTH_BYTES
+ + " bytes long IV supported");
+ }
+ int tagLengthBits = spec.getTLen();
+ if ((tagLengthBits < MIN_SUPPORTED_TAG_LENGTH_BITS)
+ || (tagLengthBits > MAX_SUPPORTED_TAG_LENGTH_BITS)
+ || ((tagLengthBits % 8) != 0)) {
+ throw new InvalidAlgorithmParameterException(
+ "Unsupported tag length: " + tagLengthBits + " bits"
+ + ". Supported lengths: 96, 104, 112, 120, 128");
+ }
+ setIv(iv);
+ mTagLengthBits = tagLengthBits;
+ }
+
+ @Override
+ protected final void initAlgorithmSpecificParameters(AlgorithmParameters params)
+ throws InvalidAlgorithmParameterException {
+ if (params == null) {
+ if (!isEncrypting()) {
+ // IV must be provided by the caller
+ throw new InvalidAlgorithmParameterException("IV required when decrypting"
+ + ". Use GCMParameterSpec or GCM AlgorithmParameters to provide it.");
+ }
+ return;
+ }
+
+ GCMParameterSpec spec;
+ try {
+ spec = params.getParameterSpec(GCMParameterSpec.class);
+ } catch (InvalidParameterSpecException e) {
+ if (!isEncrypting()) {
+ // IV must be provided by the caller
+ throw new InvalidAlgorithmParameterException("IV and tag length required when"
+ + " decrypting, but not found in parameters: " + params, e);
+ }
+ setIv(null);
+ return;
+ }
+ initAlgorithmSpecificParameters(spec);
+ }
+
+ @Nullable
+ @Override
+ protected final AlgorithmParameters engineGetParameters() {
+ byte[] iv = getIv();
+ if ((iv != null) && (iv.length > 0)) {
+ try {
+ AlgorithmParameters params = AlgorithmParameters.getInstance("GCM");
+ params.init(new GCMParameterSpec(mTagLengthBits, iv));
+ return params;
+ } catch (NoSuchAlgorithmException e) {
+ throw new ProviderException(
+ "Failed to obtain GCM AlgorithmParameters", e);
+ } catch (InvalidParameterSpecException e) {
+ throw new ProviderException(
+ "Failed to initialize GCM AlgorithmParameters", e);
+ }
+ }
+ return null;
+ }
+
+ @NonNull
+ @Override
+ protected KeyStoreCryptoOperationStreamer createMainDataStreamer(
+ KeyStore keyStore, IBinder operationToken) {
+ KeyStoreCryptoOperationStreamer streamer = new KeyStoreCryptoOperationChunkedStreamer(
+ new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
+ keyStore, operationToken));
+ if (isEncrypting()) {
+ return streamer;
+ } else {
+ // When decrypting, to avoid leaking unauthenticated plaintext, do not return any
+ // plaintext before ciphertext is authenticated by KeyStore.finish.
+ return new BufferAllOutputUntilDoFinalStreamer(streamer);
+ }
+ }
+
+ @NonNull
+ @Override
+ protected final KeyStoreCryptoOperationStreamer createAdditionalAuthenticationDataStreamer(
+ KeyStore keyStore, IBinder operationToken) {
+ return new KeyStoreCryptoOperationChunkedStreamer(
+ new AdditionalAuthenticationDataStream(keyStore, operationToken));
+ }
+
+ @Override
+ protected final int getAdditionalEntropyAmountForBegin() {
+ if ((getIv() == null) && (isEncrypting())) {
+ // IV will need to be generated
+ return IV_LENGTH_BYTES;
+ }
+
+ return 0;
+ }
+
+ @Override
+ protected final int getAdditionalEntropyAmountForFinish() {
+ return 0;
+ }
+
+ @Override
+ protected final void addAlgorithmSpecificParametersToBegin(
+ @NonNull KeymasterArguments keymasterArgs) {
+ super.addAlgorithmSpecificParametersToBegin(keymasterArgs);
+ keymasterArgs.addInt(KeymasterDefs.KM_TAG_MAC_LENGTH, mTagLengthBits);
+ }
+
+ protected final int getTagLengthBits() {
+ return mTagLengthBits;
+ }
+
+ public static final class NoPadding extends GCM {
+ public NoPadding() {
+ super(KeymasterDefs.KM_PAD_NONE);
+ }
+
+ @Override
+ protected final int engineGetOutputSize(int inputLen) {
+ int tagLengthBytes = (getTagLengthBits() + 7) / 8;
+ long result;
+ if (isEncrypting()) {
+ result = getConsumedInputSizeBytes() - getProducedOutputSizeBytes() + inputLen
+ + tagLengthBytes;
+ } else {
+ result = getConsumedInputSizeBytes() - getProducedOutputSizeBytes() + inputLen
+ - tagLengthBytes;
+ }
+ if (result < 0) {
+ return 0;
+ } else if (result > Integer.MAX_VALUE) {
+ return Integer.MAX_VALUE;
+ }
+ return (int) result;
+ }
+ }
+ }
+
+ private static final int BLOCK_SIZE_BYTES = 16;
+
+ private final int mKeymasterBlockMode;
+ private final int mKeymasterPadding;
+
+ private byte[] mIv;
+
+ /** Whether the current {@code #mIv} has been used by the underlying crypto operation. */
+ private boolean mIvHasBeenUsed;
+
+ AndroidKeyStoreAuthenticatedAESCipherSpi(
+ int keymasterBlockMode,
+ int keymasterPadding) {
+ mKeymasterBlockMode = keymasterBlockMode;
+ mKeymasterPadding = keymasterPadding;
+ }
+
+ @Override
+ protected void resetAll() {
+ mIv = null;
+ mIvHasBeenUsed = false;
+ super.resetAll();
+ }
+
+ @Override
+ protected final void initKey(int opmode, Key key) throws InvalidKeyException {
+ if (!(key instanceof AndroidKeyStoreSecretKey)) {
+ throw new InvalidKeyException(
+ "Unsupported key: " + ((key != null) ? key.getClass().getName() : "null"));
+ }
+ if (!KeyProperties.KEY_ALGORITHM_AES.equalsIgnoreCase(key.getAlgorithm())) {
+ throw new InvalidKeyException(
+ "Unsupported key algorithm: " + key.getAlgorithm() + ". Only " +
+ KeyProperties.KEY_ALGORITHM_AES + " supported");
+ }
+ setKey((AndroidKeyStoreSecretKey) key);
+ }
+
+ @Override
+ protected void addAlgorithmSpecificParametersToBegin(
+ @NonNull KeymasterArguments keymasterArgs) {
+ if ((isEncrypting()) && (mIvHasBeenUsed)) {
+ // IV is being reused for encryption: this violates security best practices.
+ throw new IllegalStateException(
+ "IV has already been used. Reusing IV in encryption mode violates security best"
+ + " practices.");
+ }
+
+ keymasterArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
+ keymasterArgs.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockMode);
+ keymasterArgs.addInt(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding);
+ if (mIv != null) {
+ keymasterArgs.addBlob(KeymasterDefs.KM_TAG_NONCE, mIv);
+ }
+ }
+
+ @Override
+ protected final void loadAlgorithmSpecificParametersFromBeginResult(
+ @NonNull KeymasterArguments keymasterArgs) {
+ mIvHasBeenUsed = true;
+
+ // NOTE: Keymaster doesn't always return an IV, even if it's used.
+ byte[] returnedIv = keymasterArgs.getBlob(KeymasterDefs.KM_TAG_NONCE, null);
+ if ((returnedIv != null) && (returnedIv.length == 0)) {
+ returnedIv = null;
+ }
+
+ if (mIv == null) {
+ mIv = returnedIv;
+ } else if ((returnedIv != null) && (!Arrays.equals(returnedIv, mIv))) {
+ throw new ProviderException("IV in use differs from provided IV");
+ }
+ }
+
+ @Override
+ protected final int engineGetBlockSize() {
+ return BLOCK_SIZE_BYTES;
+ }
+
+ @Override
+ protected final byte[] engineGetIV() {
+ return ArrayUtils.cloneIfNotEmpty(mIv);
+ }
+
+ protected void setIv(byte[] iv) {
+ mIv = iv;
+ }
+
+ protected byte[] getIv() {
+ return mIv;
+ }
+
+ /**
+ * {@link KeyStoreCryptoOperationStreamer} which buffers all output until {@code doFinal} from
+ * which it returns all output in one go, provided {@code doFinal} succeeds.
+ */
+ private static class BufferAllOutputUntilDoFinalStreamer
+ implements KeyStoreCryptoOperationStreamer {
+
+ private final KeyStoreCryptoOperationStreamer mDelegate;
+ private ByteArrayOutputStream mBufferedOutput = new ByteArrayOutputStream();
+ private long mProducedOutputSizeBytes;
+
+ private BufferAllOutputUntilDoFinalStreamer(KeyStoreCryptoOperationStreamer delegate) {
+ mDelegate = delegate;
+ }
+
+ @Override
+ public byte[] update(byte[] input, int inputOffset, int inputLength)
+ throws KeyStoreException {
+ byte[] output = mDelegate.update(input, inputOffset, inputLength);
+ if (output != null) {
+ try {
+ mBufferedOutput.write(output);
+ } catch (IOException e) {
+ throw new ProviderException("Failed to buffer output", e);
+ }
+ }
+ return EmptyArray.BYTE;
+ }
+
+ @Override
+ public byte[] doFinal(byte[] input, int inputOffset, int inputLength,
+ byte[] additionalEntropy) throws KeyStoreException {
+ byte[] output = mDelegate.doFinal(input, inputOffset, inputLength, additionalEntropy);
+ if (output != null) {
+ try {
+ mBufferedOutput.write(output);
+ } catch (IOException e) {
+ throw new ProviderException("Failed to buffer output", e);
+ }
+ }
+ byte[] result = mBufferedOutput.toByteArray();
+ mBufferedOutput.reset();
+ mProducedOutputSizeBytes += result.length;
+ return result;
+ }
+
+ @Override
+ public long getConsumedInputSizeBytes() {
+ return mDelegate.getConsumedInputSizeBytes();
+ }
+
+ @Override
+ public long getProducedOutputSizeBytes() {
+ return mProducedOutputSizeBytes;
+ }
+ }
+
+ /**
+ * Additional Authentication Data (AAD) stream via a KeyStore streaming operation. This stream
+ * sends AAD into the KeyStore.
+ */
+ private static class AdditionalAuthenticationDataStream implements Stream {
+
+ private final KeyStore mKeyStore;
+ private final IBinder mOperationToken;
+
+ private AdditionalAuthenticationDataStream(KeyStore keyStore, IBinder operationToken) {
+ mKeyStore = keyStore;
+ mOperationToken = operationToken;
+ }
+
+ @Override
+ public OperationResult update(byte[] input) {
+ KeymasterArguments keymasterArgs = new KeymasterArguments();
+ keymasterArgs.addBlob(KeymasterDefs.KM_TAG_ASSOCIATED_DATA, input);
+
+ // KeyStore does not reflect AAD in inputConsumed, but users of Stream rely on this
+ // field. We fix this discrepancy here. KeyStore.update contract is that all of AAD
+ // has been consumed if the method succeeds.
+ OperationResult result = mKeyStore.update(mOperationToken, keymasterArgs, null);
+ if (result.resultCode == KeyStore.NO_ERROR) {
+ result = new OperationResult(
+ result.resultCode,
+ result.token,
+ result.operationHandle,
+ input.length, // inputConsumed
+ result.output,
+ result.outParams);
+ }
+ return result;
+ }
+
+ @Override
+ public OperationResult finish(byte[] additionalEntropy) {
+ if ((additionalEntropy != null) && (additionalEntropy.length > 0)) {
+ throw new ProviderException("AAD stream does not support additional entropy");
+ }
+ return new OperationResult(
+ KeyStore.NO_ERROR,
+ mOperationToken,
+ 0, // operation handle -- nobody cares about this being returned from finish
+ 0, // inputConsumed
+ EmptyArray.BYTE, // output
+ new KeymasterArguments() // additional params returned by finish
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java
index f37cf07..156f45f6 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java
@@ -93,6 +93,9 @@
putSymmetricCipherImpl("AES/CTR/NoPadding",
PACKAGE_NAME + ".AndroidKeyStoreUnauthenticatedAESCipherSpi$CTR$NoPadding");
+ putSymmetricCipherImpl("AES/GCM/NoPadding",
+ PACKAGE_NAME + ".AndroidKeyStoreAuthenticatedAESCipherSpi$GCM$NoPadding");
+
putAsymmetricCipherImpl("RSA/ECB/NoPadding",
PACKAGE_NAME + ".AndroidKeyStoreRSACipherSpi$NoPadding");
put("Alg.Alias.Cipher.RSA/None/NoPadding", "RSA/ECB/NoPadding");
@@ -129,52 +132,52 @@
putSignatureImpl("MD5withRSA",
PACKAGE_NAME + ".AndroidKeyStoreRSASignatureSpi$MD5WithPKCS1Padding");
- put("Alg.Alias.Signature.MD5WithRSAEncryption", "MD5WithRSA");
- put("Alg.Alias.Signature.MD5/RSA", "MD5WithRSA");
- put("Alg.Alias.Signature.1.2.840.113549.1.1.4", "MD5WithRSA");
- put("Alg.Alias.Signature.1.2.840.113549.2.5with1.2.840.113549.1.1.1", "MD5WithRSA");
+ put("Alg.Alias.Signature.MD5WithRSAEncryption", "MD5withRSA");
+ put("Alg.Alias.Signature.MD5/RSA", "MD5withRSA");
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.4", "MD5withRSA");
+ put("Alg.Alias.Signature.1.2.840.113549.2.5with1.2.840.113549.1.1.1", "MD5withRSA");
putSignatureImpl("SHA1withRSA",
PACKAGE_NAME + ".AndroidKeyStoreRSASignatureSpi$SHA1WithPKCS1Padding");
- put("Alg.Alias.Signature.SHA1WithRSAEncryption", "SHA1WithRSA");
- put("Alg.Alias.Signature.SHA1/RSA", "SHA1WithRSA");
- put("Alg.Alias.Signature.SHA-1/RSA", "SHA1WithRSA");
- put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA1WithRSA");
- put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.113549.1.1.1", "SHA1WithRSA");
- put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.113549.1.1.5", "SHA1WithRSA");
- put("Alg.Alias.Signature.1.3.14.3.2.29", "SHA1WithRSA");
+ put("Alg.Alias.Signature.SHA1WithRSAEncryption", "SHA1withRSA");
+ put("Alg.Alias.Signature.SHA1/RSA", "SHA1withRSA");
+ put("Alg.Alias.Signature.SHA-1/RSA", "SHA1withRSA");
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA1withRSA");
+ put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.113549.1.1.1", "SHA1withRSA");
+ put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.113549.1.1.5", "SHA1withRSA");
+ put("Alg.Alias.Signature.1.3.14.3.2.29", "SHA1withRSA");
putSignatureImpl("SHA224withRSA",
PACKAGE_NAME + ".AndroidKeyStoreRSASignatureSpi$SHA224WithPKCS1Padding");
- put("Alg.Alias.Signature.SHA224WithRSAEncryption", "SHA224WithRSA");
- put("Alg.Alias.Signature.1.2.840.113549.1.1.11", "SHA224WithRSA");
+ put("Alg.Alias.Signature.SHA224WithRSAEncryption", "SHA224withRSA");
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.11", "SHA224withRSA");
put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.4with1.2.840.113549.1.1.1",
- "SHA224WithRSA");
+ "SHA224withRSA");
put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.4with1.2.840.113549.1.1.11",
- "SHA224WithRSA");
+ "SHA224withRSA");
putSignatureImpl("SHA256withRSA",
PACKAGE_NAME + ".AndroidKeyStoreRSASignatureSpi$SHA256WithPKCS1Padding");
- put("Alg.Alias.Signature.SHA256WithRSAEncryption", "SHA256WithRSA");
- put("Alg.Alias.Signature.1.2.840.113549.1.1.11", "SHA256WithRSA");
+ put("Alg.Alias.Signature.SHA256WithRSAEncryption", "SHA256withRSA");
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.11", "SHA256withRSA");
put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.1with1.2.840.113549.1.1.1",
- "SHA256WithRSA");
+ "SHA256withRSA");
put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.1with1.2.840.113549.1.1.11",
- "SHA256WithRSA");
+ "SHA256withRSA");
putSignatureImpl("SHA384withRSA",
PACKAGE_NAME + ".AndroidKeyStoreRSASignatureSpi$SHA384WithPKCS1Padding");
- put("Alg.Alias.Signature.SHA384WithRSAEncryption", "SHA384WithRSA");
- put("Alg.Alias.Signature.1.2.840.113549.1.1.12", "SHA384WithRSA");
+ put("Alg.Alias.Signature.SHA384WithRSAEncryption", "SHA384withRSA");
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.12", "SHA384withRSA");
put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.2with1.2.840.113549.1.1.1",
- "SHA384WithRSA");
+ "SHA384withRSA");
putSignatureImpl("SHA512withRSA",
PACKAGE_NAME + ".AndroidKeyStoreRSASignatureSpi$SHA512WithPKCS1Padding");
- put("Alg.Alias.Signature.SHA512WithRSAEncryption", "SHA512WithRSA");
- put("Alg.Alias.Signature.1.2.840.113549.1.1.13", "SHA512WithRSA");
+ put("Alg.Alias.Signature.SHA512WithRSAEncryption", "SHA512withRSA");
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.13", "SHA512withRSA");
put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.3with1.2.840.113549.1.1.1",
- "SHA512WithRSA");
+ "SHA512withRSA");
putSignatureImpl("SHA1withRSA/PSS",
PACKAGE_NAME + ".AndroidKeyStoreRSASignatureSpi$SHA1WithPSSPadding");
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
index d2d5850..fc53451 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
@@ -26,6 +26,8 @@
import android.security.keymaster.KeymasterDefs;
import android.security.keymaster.OperationResult;
+import libcore.util.EmptyArray;
+
import java.nio.ByteBuffer;
import java.security.AlgorithmParameters;
import java.security.GeneralSecurityException;
@@ -78,6 +80,8 @@
private IBinder mOperationToken;
private long mOperationHandle;
private KeyStoreCryptoOperationStreamer mMainDataStreamer;
+ private KeyStoreCryptoOperationStreamer mAdditionalAuthenticationDataStreamer;
+ private boolean mAdditionalAuthenticationDataStreamerClosed;
/**
* Encountered exception which could not be immediately thrown because it was encountered inside
@@ -189,6 +193,8 @@
mOperationToken = null;
mOperationHandle = 0;
mMainDataStreamer = null;
+ mAdditionalAuthenticationDataStreamer = null;
+ mAdditionalAuthenticationDataStreamerClosed = false;
mCachedException = null;
}
@@ -209,6 +215,8 @@
mOperationToken = null;
mOperationHandle = 0;
mMainDataStreamer = null;
+ mAdditionalAuthenticationDataStreamer = null;
+ mAdditionalAuthenticationDataStreamerClosed = false;
mCachedException = null;
}
@@ -273,6 +281,9 @@
loadAlgorithmSpecificParametersFromBeginResult(opResult.outParams);
mMainDataStreamer = createMainDataStreamer(mKeyStore, opResult.token);
+ mAdditionalAuthenticationDataStreamer =
+ createAdditionalAuthenticationDataStreamer(mKeyStore, opResult.token);
+ mAdditionalAuthenticationDataStreamerClosed = false;
}
/**
@@ -289,6 +300,20 @@
keyStore, operationToken));
}
+ /**
+ * Creates a streamer which sends Additional Authentication Data (AAD) into the KeyStore.
+ *
+ * <p>This implementation returns {@code null}.
+ *
+ * @returns stream or {@code null} if AAD is not supported by this cipher.
+ */
+ @Nullable
+ protected KeyStoreCryptoOperationStreamer createAdditionalAuthenticationDataStreamer(
+ @SuppressWarnings("unused") KeyStore keyStore,
+ @SuppressWarnings("unused") IBinder operationToken) {
+ return null;
+ }
+
@Override
protected final byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
if (mCachedException != null) {
@@ -307,6 +332,7 @@
byte[] output;
try {
+ flushAAD();
output = mMainDataStreamer.update(input, inputOffset, inputLen);
} catch (KeyStoreException e) {
mCachedException = e;
@@ -320,6 +346,25 @@
return output;
}
+ private void flushAAD() throws KeyStoreException {
+ if ((mAdditionalAuthenticationDataStreamer != null)
+ && (!mAdditionalAuthenticationDataStreamerClosed)) {
+ byte[] output;
+ try {
+ output = mAdditionalAuthenticationDataStreamer.doFinal(
+ EmptyArray.BYTE, 0, 0,
+ null // no additional entropy needed flushing AAD
+ );
+ } finally {
+ mAdditionalAuthenticationDataStreamerClosed = true;
+ }
+ if ((output != null) && (output.length > 0)) {
+ throw new ProviderException(
+ "AAD update unexpectedly returned data: " + output.length + " bytes");
+ }
+ }
+ }
+
@Override
protected final int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output,
int outputOffset) throws ShortBufferException {
@@ -344,12 +389,64 @@
@Override
protected final void engineUpdateAAD(byte[] input, int inputOffset, int inputLen) {
- super.engineUpdateAAD(input, inputOffset, inputLen);
+ if (mCachedException != null) {
+ return;
+ }
+
+ try {
+ ensureKeystoreOperationInitialized();
+ } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
+ mCachedException = e;
+ return;
+ }
+
+ if (mAdditionalAuthenticationDataStreamerClosed) {
+ throw new IllegalStateException(
+ "AAD can only be provided before Cipher.update is invoked");
+ }
+
+ if (mAdditionalAuthenticationDataStreamer == null) {
+ throw new IllegalStateException("This cipher does not support AAD");
+ }
+
+ byte[] output;
+ try {
+ output = mAdditionalAuthenticationDataStreamer.update(input, inputOffset, inputLen);
+ } catch (KeyStoreException e) {
+ mCachedException = e;
+ return;
+ }
+
+ if ((output != null) && (output.length > 0)) {
+ throw new ProviderException("AAD update unexpectedly produced output: "
+ + output.length + " bytes");
+ }
}
@Override
protected final void engineUpdateAAD(ByteBuffer src) {
- super.engineUpdateAAD(src);
+ if (src == null) {
+ throw new IllegalArgumentException("src == null");
+ }
+ if (!src.hasRemaining()) {
+ return;
+ }
+
+ byte[] input;
+ int inputOffset;
+ int inputLen;
+ if (src.hasArray()) {
+ input = src.array();
+ inputOffset = src.arrayOffset() + src.position();
+ inputLen = src.remaining();
+ src.position(src.limit());
+ } else {
+ input = new byte[src.remaining()];
+ inputOffset = 0;
+ inputLen = input.length;
+ src.get(input);
+ }
+ super.engineUpdateAAD(input, inputOffset, inputLen);
}
@Override
@@ -368,6 +465,7 @@
byte[] output;
try {
+ flushAAD();
byte[] additionalEntropy =
KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
mRng, getAdditionalEntropyAmountForFinish());
@@ -615,6 +713,20 @@
return mKeyStore;
}
+ protected final long getConsumedInputSizeBytes() {
+ if (mMainDataStreamer == null) {
+ throw new IllegalStateException("Not initialized");
+ }
+ return mMainDataStreamer.getConsumedInputSizeBytes();
+ }
+
+ protected final long getProducedOutputSizeBytes() {
+ if (mMainDataStreamer == null) {
+ throw new IllegalStateException("Not initialized");
+ }
+ return mMainDataStreamer.getProducedOutputSizeBytes();
+ }
+
// The methods below need to be implemented by subclasses.
/**
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index 2de60fd..2055cdb 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -104,8 +104,6 @@
/* EC */
private static final int EC_DEFAULT_KEY_SIZE = 256;
- private static final int EC_MIN_KEY_SIZE = 192;
- private static final int EC_MAX_KEY_SIZE = 521;
/* RSA */
private static final int RSA_DEFAULT_KEY_SIZE = 2048;
@@ -115,16 +113,13 @@
private static final Map<String, Integer> SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE =
new HashMap<String, Integer>();
private static final List<String> SUPPORTED_EC_NIST_CURVE_NAMES = new ArrayList<String>();
+ private static final List<Integer> SUPPORTED_EC_NIST_CURVE_SIZES = new ArrayList<Integer>();
static {
- // Aliases for NIST P-192
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-192", 192);
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp192r1", 192);
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("prime192v1", 192);
-
// Aliases for NIST P-224
SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-224", 224);
SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp224r1", 224);
+
// Aliases for NIST P-256
SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-256", 256);
SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp256r1", 256);
@@ -140,6 +135,10 @@
SUPPORTED_EC_NIST_CURVE_NAMES.addAll(SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.keySet());
Collections.sort(SUPPORTED_EC_NIST_CURVE_NAMES);
+
+ SUPPORTED_EC_NIST_CURVE_SIZES.addAll(
+ new HashSet<Integer>(SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.values()));
+ Collections.sort(SUPPORTED_EC_NIST_CURVE_SIZES);
}
private final int mOriginalKeymasterAlgorithm;
@@ -227,9 +226,8 @@
| KeyProperties.PURPOSE_VERIFY);
// Authorized to be used with any digest (including no digest).
specBuilder.setDigests(KeyProperties.DIGEST_NONE);
- specBuilder.setSignaturePaddings(
- KeyProperties.SIGNATURE_PADDING_RSA_PKCS1);
- // Authorized to be used with any padding (including no padding).
+ // Authorized to be used with any encryption and signature padding
+ // scheme (including no padding).
specBuilder.setEncryptionPaddings(
KeyProperties.ENCRYPTION_PADDING_NONE);
// Disable randomized encryption requirement to support encryption
@@ -598,9 +596,9 @@
throws InvalidAlgorithmParameterException {
switch (keymasterAlgorithm) {
case KeymasterDefs.KM_ALGORITHM_EC:
- if (keySize < EC_MIN_KEY_SIZE || keySize > EC_MAX_KEY_SIZE) {
- throw new InvalidAlgorithmParameterException("EC key size must be >= "
- + EC_MIN_KEY_SIZE + " and <= " + EC_MAX_KEY_SIZE);
+ if (!SUPPORTED_EC_NIST_CURVE_SIZES.contains(keySize)) {
+ throw new InvalidAlgorithmParameterException("Unsupported EC key size: "
+ + keySize + " bits. Supported: " + SUPPORTED_EC_NIST_CURVE_SIZES);
}
break;
case KeymasterDefs.KM_ALGORITHM_RSA:
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java
index 6abdf19..38e216d 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java
@@ -129,6 +129,7 @@
private final KeyStoreCryptoOperationStreamer mDelegate;
private final int mModulusSizeBytes;
private final ByteArrayOutputStream mInputBuffer = new ByteArrayOutputStream();
+ private long mConsumedInputSizeBytes;
private ZeroPaddingEncryptionStreamer(
KeyStoreCryptoOperationStreamer delegate,
@@ -142,6 +143,7 @@
throws KeyStoreException {
if (inputLength > 0) {
mInputBuffer.write(input, inputOffset, inputLength);
+ mConsumedInputSizeBytes += inputLength;
}
return EmptyArray.BYTE;
}
@@ -151,6 +153,7 @@
byte[] additionalEntropy)
throws KeyStoreException {
if (inputLength > 0) {
+ mConsumedInputSizeBytes += inputLength;
mInputBuffer.write(input, inputOffset, inputLength);
}
byte[] bufferedInput = mInputBuffer.toByteArray();
@@ -173,6 +176,16 @@
}
return mDelegate.doFinal(paddedInput, 0, paddedInput.length, additionalEntropy);
}
+
+ @Override
+ public long getConsumedInputSizeBytes() {
+ return mConsumedInputSizeBytes;
+ }
+
+ @Override
+ public long getProducedOutputSizeBytes() {
+ return mDelegate.getProducedOutputSizeBytes();
+ }
}
}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index 3bd9d1d..5fb589e 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -258,9 +258,8 @@
| KeyProperties.PURPOSE_VERIFY);
// Authorized to be used with any digest (including no digest).
specBuilder.setDigests(KeyProperties.DIGEST_NONE);
- specBuilder.setSignaturePaddings(
- KeyProperties.SIGNATURE_PADDING_RSA_PKCS1);
- // Authorized to be used with any padding (including no padding).
+ // Authorized to be used with any encryption and signature padding scheme (including no
+ // padding).
specBuilder.setEncryptionPaddings(
KeyProperties.ENCRYPTION_PADDING_NONE);
// Disable randomized encryption requirement to support encryption padding NONE
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreUnauthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
index 76804a9..6c53c6a 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2015 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.security.keystore;
import android.annotation.NonNull;
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 8d4bfcd..1732db9 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -19,16 +19,20 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.KeyguardManager;
+import android.hardware.fingerprint.FingerprintManager;
import android.text.TextUtils;
import java.math.BigInteger;
import java.security.KeyPairGenerator;
+import java.security.Signature;
import java.security.cert.Certificate;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Date;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
import javax.security.auth.x500.X500Principal;
/**
@@ -62,10 +66,15 @@
* <p>NOTE: If a private key is not authorized to sign the self-signed certificate, then the
* certificate will be created with an invalid signature which will not verify. Such a certificate
* is still useful because it provides access to the public key. To generate a valid
- * signature for the certificate the key needs to be authorized for
- * {@link KeyProperties#PURPOSE_SIGN}, a suitable digest or {@link KeyProperties#DIGEST_NONE}, and
- * {@link KeyProperties#SIGNATURE_PADDING_RSA_PKCS1} or
- * {@link KeyProperties#ENCRYPTION_PADDING_NONE}.
+ * signature for the certificate the key needs to be authorized for all of the following:
+ * <ul>
+ * <li>{@link KeyProperties#PURPOSE_SIGN},</li>
+ * <li>operation without requiring the user to be authenticated (see
+ * {@link Builder#setUserAuthenticationRequired(boolean)}),</li>
+ * <li>suitable digest or {@link KeyProperties#DIGEST_NONE},</li>
+ * <li>(RSA keys only) padding scheme {@link KeyProperties#SIGNATURE_PADDING_RSA_PKCS1} or
+ * {@link KeyProperties#ENCRYPTION_PADDING_NONE}.</li>
+ * </ul>
*
* <p>NOTE: The key material of the generated symmetric and private keys is not accessible. The key
* material of the public keys is accessible.
@@ -103,7 +112,7 @@
*
* <p><h3>Example: Symmetric key</h3>
* The following example illustrates how to generate an AES key in the Android KeyStore system under
- * alias {@code key2} authorized to be used only for encryption/decryption in CBC mode with PKCS#7
+ * alias {@code key2} authorized to be used only for encryption/decryption in GCM mode with no
* padding.
* <pre> {@code
* KeyGenerator keyGenerator = KeyGenerator.getInstance(
@@ -112,8 +121,8 @@
* keyGenerator.initialize(
* new KeyGenParameterSpec.Builder("key2",
* KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
- * .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
- * .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
+ * .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+ * .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
* .build());
* SecretKey key = keyGenerator.generateKey();
*
@@ -368,7 +377,7 @@
}
/**
- * Gets the set of block modes (e.g., {@code CBC}, {@code CTR}) with which the key can be used
+ * Gets the set of block modes (e.g., {@code GCM}, {@code CBC}) with which the key can be used
* when encrypting/decrypting. Attempts to use the key with any other block modes will be
* rejected.
*
@@ -393,28 +402,32 @@
}
/**
- * Returns {@code true} if user authentication is required for this key to be used.
+ * Returns {@code true} if the key is authorized to be used only if the user has been
+ * authenticated.
*
- * <p>This restriction applies only to private key operations. Public key operations are not
- * restricted.
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
*
* @see #getUserAuthenticationValidityDurationSeconds()
+ * @see Builder#setUserAuthenticationRequired(boolean)
*/
public boolean isUserAuthenticationRequired() {
return mUserAuthenticationRequired;
}
/**
- * Gets the duration of time (seconds) for which this key can be used after the user is
- * successfully authenticated. This has effect only if user authentication is required.
+ * Gets the duration of time (seconds) for which this key is authorized to be used after the
+ * user is successfully authenticated. This has effect only if user authentication is required
+ * (see {@link #isUserAuthenticationRequired()}).
*
- * <p>This restriction applies only to private key operations. Public key operations are not
- * restricted.
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
*
* @return duration in seconds or {@code -1} if authentication is required for every use of the
- * key.
+ * key.
*
* @see #isUserAuthenticationRequired()
+ * @see Builder#setUserAuthenticationValidityDurationSeconds(int)
*/
public int getUserAuthenticationValidityDurationSeconds() {
return mUserAuthenticationValidityDurationSeconds;
@@ -681,11 +694,11 @@
}
/**
- * Sets the set of block modes (e.g., {@code CBC}, {@code CTR}, {@code ECB}) with which the
- * key can be used when encrypting/decrypting. Attempts to use the key with any other block
- * modes will be rejected.
+ * Sets the set of block modes (e.g., {@code GCM}, {@code CBC}) with which the key can be
+ * used when encrypting/decrypting. Attempts to use the key with any other block modes will
+ * be rejected.
*
- * <p>This must be specified for encryption/decryption keys.
+ * <p>This must be specified for symmetric encryption/decryption keys.
*
* <p>See {@link KeyProperties}.{@code BLOCK_MODE} constants.
*/
@@ -711,7 +724,7 @@
* <li>encryption/decryption transformation which do not offer {@code IND-CPA}, such as
* {@code ECB} with a symmetric encryption algorithm, or RSA encryption/decryption without
* padding, are prohibited;</li>
- * <li>in block modes which use an IV, such as {@code CBC}, {@code CTR}, and {@code GCM},
+ * <li>in block modes which use an IV, such as {@code GCM}, {@code CBC}, and {@code CTR},
* caller-provided IVs are rejected when encrypting, to ensure that only random IVs are
* used.</li>
* </ul>
@@ -738,22 +751,38 @@
}
/**
- * Sets whether user authentication is required to use this key.
+ * Sets whether this key is authorized to be used only if the user has been authenticated.
*
- * <p>By default, the key can be used without user authentication.
+ * <p>By default, the key is authorized to be used regardless of whether the user has been
+ * authenticated.
*
- * <p>When user authentication is required, the user authorizes the use of the key by
- * authenticating to this Android device using a subset of their secure lock screen
- * credentials. Different authentication methods are used depending on whether the every
- * use of the key must be authenticated (as specified by
- * {@link #setUserAuthenticationValidityDurationSeconds(int)}).
+ * <p>When user authentication is required:
+ * <ul>
+ * <li>The key can only be generated if secure lock screen is set up (see
+ * {@link KeyguardManager#isDeviceSecure()}). Additionally, if the key requires that user
+ * authentication takes place for every use of the key (see
+ * {@link #setUserAuthenticationValidityDurationSeconds(int)}), at least one fingerprint
+ * must be enrolled (see {@link FingerprintManager#hasEnrolledFingerprints()}).</li>
+ * <li>The use of the key must be authorized by the user by authenticating to this Android
+ * device using a subset of their secure lock screen credentials such as
+ * password/PIN/pattern or fingerprint.
* <a href="{@docRoot}training/articles/keystore.html#UserAuthentication">More
* information</a>.
+ * <li>The key will become <em>irreversibly invalidated</em> once the secure lock screen is
+ * disabled (reconfigured to None, Swipe or other mode which does not authenticate the user)
+ * or when the secure lock screen is forcibly reset (e.g., by a Device Administrator).
+ * Additionally, if the key requires that user authentication takes place for every use of
+ * the key, it is also irreversibly invalidated once a new fingerprint is enrolled or once\
+ * no more fingerprints are enrolled. Attempts to initialize cryptographic operations using
+ * such keys will throw {@link KeyPermanentlyInvalidatedException}.</li>
+ * </ul>
*
- * <p>This restriction applies only to private key operations. Public key operations are not
- * restricted.
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
*
* @see #setUserAuthenticationValidityDurationSeconds(int)
+ * @see KeyguardManager#isDeviceSecure()
+ * @see FingerprintManager#hasEnrolledFingerprints()
*/
@NonNull
public Builder setUserAuthenticationRequired(boolean required) {
@@ -762,15 +791,39 @@
}
/**
- * Sets the duration of time (seconds) for which this key can be used after the user is
- * successfully authenticated. This has effect only if user authentication is required.
+ * Sets the duration of time (seconds) for which this key is authorized to be used after the
+ * user is successfully authenticated. This has effect if the key requires user
+ * authentication for its use (see {@link #setUserAuthenticationRequired(boolean)}).
*
- * <p>By default, the user needs to authenticate for every use of the key.
+ * <p>By default, if user authentication is required, it must take place for every use of
+ * the key.
*
- * @param seconds duration in seconds or {@code -1} if the user needs to authenticate for
- * every use of the key.
+ * <p>Cryptographic operations involving keys which require user authentication to take
+ * place for every operation can only use fingerprint authentication. This is achieved by
+ * initializing a cryptographic operation ({@link Signature}, {@link Cipher}, {@link Mac})
+ * with the key, wrapping it into a {@link FingerprintManager.CryptoObject}, invoking
+ * {@code FingerprintManager.authenticate} with {@code CryptoObject}, and proceeding with
+ * the cryptographic operation only if the authentication flow succeeds.
+ *
+ * <p>Cryptographic operations involving keys which are authorized to be used for a duration
+ * of time after a successful user authentication event can only use secure lock screen
+ * authentication. These cryptographic operations will throw
+ * {@link UserNotAuthenticatedException} during initialization if the user needs to be
+ * authenticated to proceed. This situation can be resolved by the user unlocking the secure
+ * lock screen of the Android or by going through the confirm credential flow initiated by
+ * {@link KeyguardManager#createConfirmDeviceCredentialIntent(CharSequence, CharSequence)}.
+ * Once resolved, initializing a new cryptographic operation using this key (or any other
+ * key which is authorized to be used for a fixed duration of time after user
+ * authentication) should succeed provided the user authentication flow completed
+ * successfully.
+ *
+ * @param seconds duration in seconds or {@code -1} if user authentication must take place
+ * for every use of the key.
*
* @see #setUserAuthenticationRequired(boolean)
+ * @see FingerprintManager
+ * @see FingerprintManager.CryptoObject
+ * @see KeyguardManager
*/
@NonNull
public Builder setUserAuthenticationValidityDurationSeconds(
diff --git a/keystore/java/android/security/keystore/KeyInfo.java b/keystore/java/android/security/keystore/KeyInfo.java
index 03b4100..785ec15 100644
--- a/keystore/java/android/security/keystore/KeyInfo.java
+++ b/keystore/java/android/security/keystore/KeyInfo.java
@@ -30,7 +30,7 @@
* Keystore system</a>. This class describes whether the key material is available in
* plaintext outside of secure hardware, whether user authentication is required for using the key
* and whether this requirement is enforced by secure hardware, the key's origin, what uses the key
- * is authorized for (e.g., only in {@code CBC} mode, or signing only), whether the key should be
+ * is authorized for (e.g., only in {@code GCM} mode, or signing only), whether the key should be
* encrypted at rest, the key's and validity start and end dates.
*
* <p>Instances of this class are immutable.
@@ -191,7 +191,7 @@
}
/**
- * Gets the set of block modes (e.g., {@code CBC}, {@code CTR}) with which the key can be used
+ * Gets the set of block modes (e.g., {@code GCM}, {@code CBC}) with which the key can be used
* when encrypting/decrypting. Attempts to use the key with any other block modes will be
* rejected.
*
@@ -238,17 +238,27 @@
}
/**
- * Returns {@code true} if user authentication is required for this key to be used.
+ * Returns {@code true} if the key is authorized to be used only if the user has been
+ * authenticated.
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
*
* @see #getUserAuthenticationValidityDurationSeconds()
+ * @see KeyGenParameterSpec.Builder#setUserAuthenticationRequired(boolean)
+ * @see KeyProtection.Builder#setUserAuthenticationRequired(boolean)
*/
public boolean isUserAuthenticationRequired() {
return mUserAuthenticationRequired;
}
/**
- * Gets the duration of time (seconds) for which this key can be used after the user is
- * successfully authenticated. This has effect only if user authentication is required.
+ * Gets the duration of time (seconds) for which this key is authorized to be used after the
+ * user is successfully authenticated. This has effect only if user authentication is required
+ * (see {@link #isUserAuthenticationRequired()}).
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
*
* @return duration in seconds or {@code -1} if authentication is required for every use of the
* key.
diff --git a/keystore/java/android/security/keystore/KeyPermanentlyInvalidatedException.java b/keystore/java/android/security/keystore/KeyPermanentlyInvalidatedException.java
index e320c9c..9e82fc0 100644
--- a/keystore/java/android/security/keystore/KeyPermanentlyInvalidatedException.java
+++ b/keystore/java/android/security/keystore/KeyPermanentlyInvalidatedException.java
@@ -21,12 +21,13 @@
/**
* Indicates that the key can no longer be used because it has been permanently invalidated.
*
- * <p>This can currently occur only for keys that require user authentication. Such keys are
- * permanently invalidated once the secure lock screen is disabled (i.e., reconfigured to None,
- * Swipe or other mode which does not authenticate the user) or when the secure lock screen is
- * forcibly reset (e.g., by Device Admin). Additionally, keys configured to require user
- * authentication for every use of the key are also permanently invalidated once a new fingerprint
- * is enrolled or once no more fingerprints are enrolled.
+ * <p>This only occurs for keys which are authorized to be used only if the user has been
+ * authenticated. Such keys are permanently and irreversibly invalidated once the secure lock screen
+ * is disabled (i.e., reconfigured to None, Swipe or other mode which does not authenticate the
+ * user) or when the secure lock screen is forcibly reset (e.g., by Device Admin). Additionally,
+ * keys configured to require user authentication to take place for every of the keys, are also
+ * permanently invalidated once a new fingerprint is enrolled or once no more fingerprints are
+ * enrolled.
*/
public class KeyPermanentlyInvalidatedException extends InvalidKeyException {
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index 1e0611c..b7a2a0b 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -19,19 +19,23 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.KeyguardManager;
+import android.hardware.fingerprint.FingerprintManager;
import java.security.Key;
+import java.security.Signature;
import java.security.KeyStore.ProtectionParameter;
import java.security.cert.Certificate;
import java.util.Date;
import javax.crypto.Cipher;
+import javax.crypto.Mac;
/**
* Specification of how a key or key pair is secured when imported into the
* <a href="{@docRoot}training/articles/keystore.html">Android KeyStore facility</a>. This class
* specifies parameters such as whether user authentication is required for using the key, what uses
- * the key is authorized for (e.g., only in {@code CTR} mode, or only for signing -- decryption not
+ * the key is authorized for (e.g., only in {@code GCM} mode, or only for signing -- decryption not
* permitted), the key's and validity start and end dates.
*
* <p>To import a key or key pair into the Android KeyStore, create an instance of this class using
@@ -51,8 +55,8 @@
*
* <p><h3>Example: Symmetric Key</h3>
* The following example illustrates how to import an AES key into the Android KeyStore under alias
- * {@code key1} authorized to be used only for encryption/decryption in CBC mode with PKCS#7
- * padding. The key must export its key material via {@link Key#getEncoded()} in {@code RAW} format.
+ * {@code key1} authorized to be used only for encryption/decryption in GCM mode with no padding.
+ * The key must export its key material via {@link Key#getEncoded()} in {@code RAW} format.
* <pre> {@code
* SecretKey key = ...; // AES key
*
@@ -62,8 +66,8 @@
* "key1",
* new KeyStore.SecretKeyEntry(key),
* new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
- * .setBlockMode(KeyProperties.BLOCK_MODE_CBC)
- * .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
+ * .setBlockMode(KeyProperties.BLOCK_MODE_GCM)
+ * .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
* .build());
* // Key imported, obtain a reference to it.
* SecretKey keyStoreKey = (SecretKey) keyStore.getKey("key1", null);
@@ -232,7 +236,7 @@
}
/**
- * Gets the set of block modes (e.g., {@code CBC}, {@code CTR}) with which the key can be used
+ * Gets the set of block modes (e.g., {@code GCM}, {@code CBC}) with which the key can be used
* when encrypting/decrypting. Attempts to use the key with any other block modes will be
* rejected.
*
@@ -257,22 +261,32 @@
}
/**
- * Returns {@code true} if user authentication is required for this key to be used.
+ * Returns {@code true} if the key is authorized to be used only if the user has been
+ * authenticated.
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
*
* @see #getUserAuthenticationValidityDurationSeconds()
+ * @see Builder#setUserAuthenticationRequired(boolean)
*/
public boolean isUserAuthenticationRequired() {
return mUserAuthenticationRequired;
}
/**
- * Gets the duration of time (seconds) for which this key can be used after the user is
- * successfully authenticated. This has effect only if user authentication is required.
+ * Gets the duration of time (seconds) for which this key is authorized to be used after the
+ * user is successfully authenticated. This has effect only if user authentication is required
+ * (see {@link #isUserAuthenticationRequired()}).
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
*
* @return duration in seconds or {@code -1} if authentication is required for every use of the
* key.
*
* @see #isUserAuthenticationRequired()
+ * @see Builder#setUserAuthenticationValidityDurationSeconds(int)
*/
public int getUserAuthenticationValidityDurationSeconds() {
return mUserAuthenticationValidityDurationSeconds;
@@ -424,11 +438,11 @@
}
/**
- * Sets the set of block modes (e.g., {@code CBC}, {@code CTR}, {@code ECB}) with which the
- * key can be used when encrypting/decrypting. Attempts to use the key with any other block
- * modes will be rejected.
+ * Sets the set of block modes (e.g., {@code GCM}, {@code CBC}) with which the key can be
+ * used when encrypting/decrypting. Attempts to use the key with any other block modes will
+ * be rejected.
*
- * <p>This must be specified for encryption/decryption keys.
+ * <p>This must be specified for symmetric encryption/decryption keys.
*
* <p>See {@link KeyProperties}.{@code BLOCK_MODE} constants.
*/
@@ -453,8 +467,8 @@
* <ul>
* <li>transformation which do not offer {@code IND-CPA}, such as symmetric ciphers using
* {@code ECB} mode or RSA encryption without padding, are prohibited;</li>
- * <li>in transformations which use an IV, such as symmetric ciphers in {@code CBC},
- * {@code CTR}, and {@code GCM} block modes, caller-provided IVs are rejected when
+ * <li>in transformations which use an IV, such as symmetric ciphers in {@code GCM},
+ * {@code CBC}, and {@code CTR} block modes, caller-provided IVs are rejected when
* encrypting, to ensure that only random IVs are used.</li>
*
* <p>Before disabling this requirement, consider the following approaches instead:
@@ -479,19 +493,38 @@
}
/**
- * Sets whether user authentication is required to use this key.
+ * Sets whether this key is authorized to be used only if the user has been authenticated.
*
- * <p>By default, the key can be used without user authentication.
+ * <p>By default, the key is authorized to be used regardless of whether the user has been
+ * authenticated.
*
- * <p>When user authentication is required, the user authorizes the use of the key by
- * authenticating to this Android device using a subset of their secure lock screen
- * credentials. Different authentication methods are used depending on whether the every
- * use of the key must be authenticated (as specified by
- * {@link #setUserAuthenticationValidityDurationSeconds(int)}).
+ * <p>When user authentication is required:
+ * <ul>
+ * <li>The key can only be import if secure lock screen is set up (see
+ * {@link KeyguardManager#isDeviceSecure()}). Additionally, if the key requires that user
+ * authentication takes place for every use of the key (see
+ * {@link #setUserAuthenticationValidityDurationSeconds(int)}), at least one fingerprint
+ * must be enrolled (see {@link FingerprintManager#hasEnrolledFingerprints()}).</li>
+ * <li>The use of the key must be authorized by the user by authenticating to this Android
+ * device using a subset of their secure lock screen credentials such as
+ * password/PIN/pattern or fingerprint.
* <a href="{@docRoot}training/articles/keystore.html#UserAuthentication">More
* information</a>.
+ * <li>The key will become <em>irreversibly invalidated</em> once the secure lock screen is
+ * disabled (reconfigured to None, Swipe or other mode which does not authenticate the user)
+ * or when the secure lock screen is forcibly reset (e.g., by a Device Administrator).
+ * Additionally, if the key requires that user authentication takes place for every use of
+ * the key, it is also irreversibly invalidated once a new fingerprint is enrolled or once\
+ * no more fingerprints are enrolled. Attempts to initialize cryptographic operations using
+ * such keys will throw {@link KeyPermanentlyInvalidatedException}.</li>
+ * </ul>
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
*
* @see #setUserAuthenticationValidityDurationSeconds(int)
+ * @see KeyguardManager#isDeviceSecure()
+ * @see FingerprintManager#hasEnrolledFingerprints()
*/
@NonNull
public Builder setUserAuthenticationRequired(boolean required) {
@@ -500,15 +533,39 @@
}
/**
- * Sets the duration of time (seconds) for which this key can be used after the user is
- * successfully authenticated. This has effect only if user authentication is required.
+ * Sets the duration of time (seconds) for which this key is authorized to be used after the
+ * user is successfully authenticated. This has effect if the key requires user
+ * authentication for its use (see {@link #setUserAuthenticationRequired(boolean)}).
*
- * <p>By default, the user needs to authenticate for every use of the key.
+ * <p>By default, if user authentication is required, it must take place for every use of
+ * the key.
*
- * @param seconds duration in seconds or {@code -1} if the user needs to authenticate for
- * every use of the key.
+ * <p>Cryptographic operations involving keys which require user authentication to take
+ * place for every operation can only use fingerprint authentication. This is achieved by
+ * initializing a cryptographic operation ({@link Signature}, {@link Cipher}, {@link Mac})
+ * with the key, wrapping it into a {@link FingerprintManager.CryptoObject}, invoking
+ * {@code FingerprintManager.authenticate} with {@code CryptoObject}, and proceeding with
+ * the cryptographic operation only if the authentication flow succeeds.
+ *
+ * <p>Cryptographic operations involving keys which are authorized to be used for a duration
+ * of time after a successful user authentication event can only use secure lock screen
+ * authentication. These cryptographic operations will throw
+ * {@link UserNotAuthenticatedException} during initialization if the user needs to be
+ * authenticated to proceed. This situation can be resolved by the user unlocking the secure
+ * lock screen of the Android or by going through the confirm credential flow initiated by
+ * {@link KeyguardManager#createConfirmDeviceCredentialIntent(CharSequence, CharSequence)}.
+ * Once resolved, initializing a new cryptographic operation using this key (or any other
+ * key which is authorized to be used for a fixed duration of time after user
+ * authentication) should succeed provided the user authentication flow completed
+ * successfully.
+ *
+ * @param seconds duration in seconds or {@code -1} if user authentication must take place
+ * for every use of the key.
*
* @see #setUserAuthenticationRequired(boolean)
+ * @see FingerprintManager
+ * @see FingerprintManager.CryptoObject
+ * @see KeyguardManager
*/
@NonNull
public Builder setUserAuthenticationValidityDurationSeconds(
diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
index 9957e79..894d52a 100644
--- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
+++ b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
@@ -73,6 +73,8 @@
private byte[] mBuffered = EmptyArray.BYTE;
private int mBufferedOffset;
private int mBufferedLength;
+ private long mConsumedInputSizeBytes;
+ private long mProducedOutputSizeBytes;
public KeyStoreCryptoOperationChunkedStreamer(Stream operation) {
this(operation, DEFAULT_MAX_CHUNK_SIZE);
@@ -119,6 +121,7 @@
// Update input array references to reflect that some of its bytes are now in mBuffered.
inputOffset += inputBytesInChunk;
inputLength -= inputBytesInChunk;
+ mConsumedInputSizeBytes += inputBytesInChunk;
OperationResult opResult = mKeyStoreStream.update(chunk);
if (opResult == null) {
@@ -167,9 +170,10 @@
}
} else {
// No more output will be produced in this loop
+ byte[] result;
if (bufferedOutput == null) {
// No previously buffered output
- return opResult.output;
+ result = opResult.output;
} else {
// There was some previously buffered output
try {
@@ -177,18 +181,23 @@
} catch (IOException e) {
throw new IllegalStateException("Failed to buffer output", e);
}
- return bufferedOutput.toByteArray();
+ result = bufferedOutput.toByteArray();
}
+ mProducedOutputSizeBytes += result.length;
+ return result;
}
}
}
+ byte[] result;
if (bufferedOutput == null) {
// No output produced
- return EmptyArray.BYTE;
+ result = EmptyArray.BYTE;
} else {
- return bufferedOutput.toByteArray();
+ result = bufferedOutput.toByteArray();
}
+ mProducedOutputSizeBytes += result.length;
+ return result;
}
@Override
@@ -210,14 +219,11 @@
} else if (opResult.resultCode != KeyStore.NO_ERROR) {
throw KeyStore.getKeyStoreException(opResult.resultCode);
}
+ mProducedOutputSizeBytes += opResult.output.length;
return ArrayUtils.concat(output, opResult.output);
}
- /**
- * Passes all of buffered input into the the KeyStore operation (via the {@code update}
- * operation) and returns output.
- */
public byte[] flush() throws KeyStoreException {
if (mBufferedLength <= 0) {
return EmptyArray.BYTE;
@@ -243,7 +249,19 @@
+ " . Provided: " + chunk.length + ", consumed: " + opResult.inputConsumed);
}
- return (opResult.output != null) ? opResult.output : EmptyArray.BYTE;
+ byte[] result = (opResult.output != null) ? opResult.output : EmptyArray.BYTE;
+ mProducedOutputSizeBytes += result.length;
+ return result;
+ }
+
+ @Override
+ public long getConsumedInputSizeBytes() {
+ return mConsumedInputSizeBytes;
+ }
+
+ @Override
+ public long getProducedOutputSizeBytes() {
+ return mProducedOutputSizeBytes;
}
/**
diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationStreamer.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationStreamer.java
index 1c6de2d..897bd71 100644
--- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationStreamer.java
+++ b/keystore/java/android/security/keystore/KeyStoreCryptoOperationStreamer.java
@@ -37,4 +37,6 @@
byte[] update(byte[] input, int inputOffset, int inputLength) throws KeyStoreException;
byte[] doFinal(byte[] input, int inputOffset, int inputLength, byte[] additionalEntropy)
throws KeyStoreException;
+ long getConsumedInputSizeBytes();
+ long getProducedOutputSizeBytes();
}
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index a3ea896..f3d755c 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -75,6 +75,7 @@
String getBestProvider(in Criteria criteria, boolean enabledOnly);
boolean providerMeetsCriteria(String provider, in Criteria criteria);
ProviderProperties getProviderProperties(String provider);
+ String getNetworkProviderPackage();
boolean isProviderEnabled(String provider);
void addTestProvider(String name, in ProviderProperties properties, String opPackageName);
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 3cbc405..974b62e 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -527,10 +527,11 @@
}
/**
- * @return a new {@link AudioRecord} instance initialized with all the parameters set
- * on this <code>Builder</code>
+ * @return a new {@link AudioRecord} instance successfully initialized with all
+ * the parameters set on this <code>Builder</code>.
* @throws UnsupportedOperationException if the parameters set on the <code>Builder</code>
- * were incompatible, or if they are not supported by the device.
+ * were incompatible, or if they are not supported by the device,
+ * or if the device was not available.
*/
public AudioRecord build() throws UnsupportedOperationException {
if (mFormat == null) {
@@ -564,7 +565,13 @@
mBufferSizeInBytes = mFormat.getChannelCount()
* mFormat.getBytesPerSample(mFormat.getEncoding());
}
- return new AudioRecord(mAttributes, mFormat, mBufferSizeInBytes, mSessionId);
+ final AudioRecord record = new AudioRecord(
+ mAttributes, mFormat, mBufferSizeInBytes, mSessionId);
+ if (record.getState() == STATE_UNINITIALIZED) {
+ // release is not necessary
+ throw new UnsupportedOperationException("Cannot create AudioRecord");
+ }
+ return record;
} catch (IllegalArgumentException e) {
throw new UnsupportedOperationException(e.getMessage());
}
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index f395cb3..62810c6 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -661,9 +661,10 @@
/**
* Builds an {@link AudioTrack} instance initialized with all the parameters set
* on this <code>Builder</code>.
- * @return a new {@link AudioTrack} instance.
+ * @return a new successfully initialized {@link AudioTrack} instance.
* @throws UnsupportedOperationException if the parameters set on the <code>Builder</code>
- * were incompatible, or if they are not supported by the device.
+ * were incompatible, or if they are not supported by the device,
+ * or if the device was not available.
*/
public @NonNull AudioTrack build() throws UnsupportedOperationException {
if (mAttributes == null) {
@@ -686,7 +687,13 @@
mBufferSizeInBytes = mFormat.getChannelCount()
* mFormat.getBytesPerSample(mFormat.getEncoding());
}
- return new AudioTrack(mAttributes, mFormat, mBufferSizeInBytes, mMode, mSessionId);
+ final AudioTrack track = new AudioTrack(
+ mAttributes, mFormat, mBufferSizeInBytes, mMode, mSessionId);
+ if (track.getState() == STATE_UNINITIALIZED) {
+ // release is not necessary
+ throw new UnsupportedOperationException("Cannot create AudioTrack");
+ }
+ return track;
} catch (IllegalArgumentException e) {
throw new UnsupportedOperationException(e.getMessage());
}
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 8e962187..c75c7e5 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -40,7 +40,7 @@
*/
interface IAudioService {
- void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
+ oneway void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
String callingPackage, String caller);
void adjustStreamVolume(int streamType, int direction, int flags, String callingPackage);
diff --git a/media/java/android/media/midi/MidiDevice.java b/media/java/android/media/midi/MidiDevice.java
index 7998a92..93fb6d2 100644
--- a/media/java/android/media/midi/MidiDevice.java
+++ b/media/java/android/media/midi/MidiDevice.java
@@ -50,21 +50,43 @@
* Close this object to terminate the connection.
*/
public class MidiConnection implements Closeable {
- private final IBinder mToken;
- private final MidiInputPort mInputPort;
+ private final IMidiDeviceServer mInputPortDeviceServer;
+ private final IBinder mInputPortToken;
+ private final IBinder mOutputPortToken;
+ private final CloseGuard mGuard = CloseGuard.get();
+ private boolean mIsClosed;
- MidiConnection(IBinder token, MidiInputPort inputPort) {
- mToken = token;
- mInputPort = inputPort;
+ MidiConnection(IBinder outputPortToken, MidiInputPort inputPort) {
+ mInputPortDeviceServer = inputPort.getDeviceServer();
+ mInputPortToken = inputPort.getToken();
+ mOutputPortToken = outputPortToken;
+ mGuard.open("close");
}
@Override
public void close() throws IOException {
+ synchronized (mGuard) {
+ if (mIsClosed) return;
+ mGuard.close();
+ try {
+ // close input port
+ mInputPortDeviceServer.closePort(mInputPortToken);
+ // close output port
+ mDeviceServer.closePort(mOutputPortToken);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in MidiConnection.close");
+ }
+ mIsClosed = true;
+ }
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
try {
- mDeviceServer.closePort(mToken);
- IoUtils.closeQuietly(mInputPort);
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in MidiConnection.close");
+ mGuard.warnIfOpen();
+ close();
+ } finally {
+ super.finalize();
}
}
}
diff --git a/media/java/android/media/midi/MidiDeviceServer.java b/media/java/android/media/midi/MidiDeviceServer.java
index 1212b64..19ff624 100644
--- a/media/java/android/media/midi/MidiDeviceServer.java
+++ b/media/java/android/media/midi/MidiDeviceServer.java
@@ -257,7 +257,14 @@
public void connectPorts(IBinder token, ParcelFileDescriptor pfd,
int outputPortNumber) {
MidiInputPort inputPort = new MidiInputPort(pfd, outputPortNumber);
- mOutputPortDispatchers[outputPortNumber].getSender().connect(inputPort);
+ MidiDispatcher dispatcher = mOutputPortDispatchers[outputPortNumber];
+ synchronized (dispatcher) {
+ dispatcher.getSender().connect(inputPort);
+ int openCount = dispatcher.getReceiverCount();
+ mOutputPortOpenCount[outputPortNumber] = openCount;
+ updateDeviceStatus();
+ }
+
mInputPorts.add(inputPort);
OutputPortClient client = new OutputPortClient(token, inputPort);
synchronized (mPortClients) {
diff --git a/media/java/android/media/midi/MidiInputPort.java b/media/java/android/media/midi/MidiInputPort.java
index af5a86c..db41b10 100644
--- a/media/java/android/media/midi/MidiInputPort.java
+++ b/media/java/android/media/midi/MidiInputPort.java
@@ -103,17 +103,33 @@
// used by MidiDevice.connectInputPort() to connect our socket directly to another device
/* package */ ParcelFileDescriptor claimFileDescriptor() {
- synchronized (mBuffer) {
- ParcelFileDescriptor pfd = mParcelFileDescriptor;
- if (pfd != null) {
+ synchronized (mGuard) {
+ ParcelFileDescriptor pfd;
+ synchronized (mBuffer) {
+ pfd = mParcelFileDescriptor;
+ if (pfd == null) return null;
IoUtils.closeQuietly(mOutputStream);
mParcelFileDescriptor = null;
mOutputStream = null;
}
+
+ // Set mIsClosed = true so we will not call mDeviceServer.closePort() in close().
+ // MidiDevice.MidiConnection.close() will do the cleanup instead.
+ mIsClosed = true;
return pfd;
}
}
+ // used by MidiDevice.MidiConnection to close this port after the connection is closed
+ /* package */ IBinder getToken() {
+ return mToken;
+ }
+
+ // used by MidiDevice.MidiConnection to close this port after the connection is closed
+ /* package */ IMidiDeviceServer getDeviceServer() {
+ return mDeviceServer;
+ }
+
@Override
public void close() throws IOException {
synchronized (mGuard) {
diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp
index 634ba64..ba7634c 100644
--- a/media/jni/android_media_ImageWriter.cpp
+++ b/media/jni/android_media_ImageWriter.cpp
@@ -361,8 +361,7 @@
ALOGV("%s:", __FUNCTION__);
JNIImageWriterContext* const ctx = reinterpret_cast<JNIImageWriterContext *>(nativeCtx);
if (ctx == NULL || thiz == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "ImageWriterContext is not initialized");
+ // ImageWriter is already closed.
return;
}
diff --git a/packages/DocumentsUI/res/values-sw720dp/styles.xml b/packages/DocumentsUI/res/values-sw720dp/styles.xml
index 0b03a94..d7c031e 100644
--- a/packages/DocumentsUI/res/values-sw720dp/styles.xml
+++ b/packages/DocumentsUI/res/values-sw720dp/styles.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <style name="DialogWhenReallyLarge" parent="@*android:style/Theme.Material.DayNight.Dialog">
+ <style name="DialogWhenReallyLarge" parent="@*android:style/Theme.DeviceDefault.Light.Dialog">
<!-- We do not specify width of window here because the max size of
floating window specified by windowFixedWidthis is limited. -->
<item name="*android:windowFixedHeightMajor">80%</item>
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index 6d741aa..8c4b777 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <style name="DialogWhenReallyLarge" parent="@android:style/Theme.Material.DayNight.DarkActionBar" />
+ <style name="DialogWhenReallyLarge" parent="@android:style/Theme.DeviceDefault.Light.DarkActionBar" />
<style name="DocumentsTheme" parent="@style/DialogWhenReallyLarge">
<item name="android:actionBarWidgetTheme">@null</item>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 90ccf91..fe148da 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -393,25 +393,23 @@
@Override
public void updateActionBar() {
if (mRootsToolbar != null) {
- if (mState.action == ACTION_OPEN ||
- mState.action == ACTION_GET_CONTENT ||
- mState.action == ACTION_OPEN_TREE) {
- mRootsToolbar.setTitle(R.string.title_open);
- } else if (mState.action == ACTION_CREATE ||
- mState.action == ACTION_OPEN_COPY_DESTINATION) {
- mRootsToolbar.setTitle(R.string.title_save);
+ final String prompt = getIntent().getStringExtra(DocumentsContract.EXTRA_PROMPT);
+ if (prompt != null) {
+ mRootsToolbar.setTitle(prompt);
+ } else {
+ if (mState.action == ACTION_OPEN ||
+ mState.action == ACTION_GET_CONTENT ||
+ mState.action == ACTION_OPEN_TREE) {
+ mRootsToolbar.setTitle(R.string.title_open);
+ } else if (mState.action == ACTION_CREATE ||
+ mState.action == ACTION_OPEN_COPY_DESTINATION) {
+ mRootsToolbar.setTitle(R.string.title_save);
+ }
}
}
- final RootInfo root = getCurrentRoot();
- final boolean showRootIcon = mShowAsDialog
- || (mState.action == ACTION_MANAGE || mState.action == ACTION_BROWSE);
- if (showRootIcon) {
- mToolbar.setNavigationIcon(
- root != null ? root.loadToolbarIcon(mToolbar.getContext()) : null);
- mToolbar.setNavigationContentDescription(R.string.drawer_open);
- mToolbar.setNavigationOnClickListener(null);
- } else {
+ if (!mShowAsDialog && mDrawerLayout.getDrawerLockMode(mRootsDrawer) ==
+ DrawerLayout.LOCK_MODE_UNLOCKED) {
mToolbar.setNavigationIcon(R.drawable.ic_hamburger);
mToolbar.setNavigationContentDescription(R.string.drawer_open);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@@ -420,6 +418,10 @@
setRootsDrawerOpen(true);
}
});
+ } else {
+ mToolbar.setNavigationIcon(null);
+ mToolbar.setNavigationContentDescription(R.string.drawer_open);
+ mToolbar.setNavigationOnClickListener(null);
}
if (mSearchManager.isExpanded()) {
@@ -428,7 +430,7 @@
mToolbarStack.setAdapter(null);
} else {
if (mState.stack.size() <= 1) {
- mToolbar.setTitle(root.title);
+ mToolbar.setTitle(getCurrentRoot().title);
mToolbarStack.setVisibility(View.GONE);
mToolbarStack.setAdapter(null);
} else {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index aa99a7b..0c6837f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -216,6 +216,19 @@
return mCallback;
}
+ @Override
+ public void showPromptReason(int reason) {
+ if (reason != PROMPT_REASON_NONE) {
+ int promtReasonStringRes = getPromtReasonStringRes(reason);
+ if (promtReasonStringRes != 0) {
+ mSecurityMessageDisplay.setMessage(promtReasonStringRes,
+ true /* important */);
+ }
+ }
+ }
+
+ protected abstract int getPromtReasonStringRes(int reason);
+
// Cause a VIRTUAL_KEY vibration
public void doHapticKeyClick() {
if (mEnableHaptics) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index cd4b24a..ff4e815 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -160,6 +160,17 @@
}
/**
+ * Show a string explaining why the security view needs to be solved.
+ *
+ * @param reason a flag indicating which string should be shown, see
+ * {@link KeyguardSecurityView#PROMPT_REASON_NONE}
+ * and {@link KeyguardSecurityView#PROMPT_REASON_RESTART}
+ */
+ public void showPromptReason(int reason) {
+ mSecurityContainer.showPromptReason(reason);
+ }
+
+ /**
* Dismisses the keyguard by going to the next screen or making it gone.
*
* @return True if the keyguard is done.
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
index c9ad728..2db87b3 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
@@ -111,6 +111,16 @@
}
@Override
+ protected int getPromtReasonStringRes(int reason) {
+ switch (reason) {
+ case PROMPT_REASON_RESTART:
+ return R.string.kg_prompt_reason_restart_password;
+ default:
+ return 0;
+ }
+ }
+
+ @Override
public void onPause() {
super.onPause();
mImm.hideSoftInputFromWindow(getWindowToken(), 0);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index 1bd0bb4..59a8ad5 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -85,10 +85,9 @@
}
};
private Rect mTempRect = new Rect();
- private SecurityMessageDisplay mSecurityMessageDisplay;
+ private KeyguardMessageArea mSecurityMessageDisplay;
private View mEcaView;
private ViewGroup mContainer;
- private KeyguardMessageArea mHelpMessage;
private int mDisappearYTranslation;
enum FooterMode {
@@ -141,10 +140,10 @@
// vibrate mode will be the same for the life of this screen
mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
- mSecurityMessageDisplay = KeyguardMessageArea.findSecurityMessageDisplay(this);
+ mSecurityMessageDisplay =
+ (KeyguardMessageArea) KeyguardMessageArea.findSecurityMessageDisplay(this);
mEcaView = findViewById(R.id.keyguard_selector_fade_container);
mContainer = (ViewGroup) findViewById(R.id.container);
- mHelpMessage = (KeyguardMessageArea) findViewById(R.id.keyguard_message_area);
EmergencyButton button = (EmergencyButton) findViewById(R.id.emergency_call_button);
if (button != null) {
@@ -320,6 +319,17 @@
}
@Override
+ public void showPromptReason(int reason) {
+ switch (reason) {
+ case PROMPT_REASON_RESTART:
+ mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_restart_pattern,
+ true /* important */);
+ break;
+ default:
+ }
+ }
+
+ @Override
public void startAppearAnimation() {
enableClipping(false);
setAlpha(1f);
@@ -337,8 +347,8 @@
}
},
this);
- if (!TextUtils.isEmpty(mHelpMessage.getText())) {
- mAppearAnimationUtils.createAnimation(mHelpMessage, 0,
+ if (!TextUtils.isEmpty(mSecurityMessageDisplay.getText())) {
+ mAppearAnimationUtils.createAnimation(mSecurityMessageDisplay, 0,
AppearAnimationUtils.DEFAULT_APPEAR_DURATION,
mAppearAnimationUtils.getStartTranslation(),
true /* appearing */,
@@ -366,8 +376,8 @@
}
}
}, KeyguardPatternView.this);
- if (!TextUtils.isEmpty(mHelpMessage.getText())) {
- mDisappearAnimationUtils.createAnimation(mHelpMessage, 0,
+ if (!TextUtils.isEmpty(mSecurityMessageDisplay.getText())) {
+ mDisappearAnimationUtils.createAnimation(mSecurityMessageDisplay, 0,
200,
- mDisappearAnimationUtils.getStartTranslation() * 3,
false /* appearing */,
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 23834a3..07947b1 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -93,6 +93,16 @@
return super.onKeyDown(keyCode, event);
}
+ @Override
+ protected int getPromtReasonStringRes(int reason) {
+ switch (reason) {
+ case PROMPT_REASON_RESTART:
+ return R.string.kg_prompt_reason_restart_pin;
+ default:
+ return 0;
+ }
+ }
+
private void performClick(View view) {
view.performClick();
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index d17b25a..f529ac0 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -509,6 +509,13 @@
}
@Override
+ public void showPromptReason(int reason) {
+ if (mCurrentSecuritySelection != SecurityMode.None) {
+ getSecurityView(mCurrentSecuritySelection).showPromptReason(reason);
+ }
+ }
+
+ @Override
public void showUsabilityHint() {
mSecurityViewFlipper.showUsabilityHint();
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
index 5b50236..5658a74 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
@@ -21,6 +21,9 @@
static public final int SCREEN_ON = 1;
static public final int VIEW_REVEALED = 2;
+ int PROMPT_REASON_NONE = 0;
+ int PROMPT_REASON_RESTART = 1;
+
/**
* Interface back to keyguard to tell it when security
* @param callback
@@ -66,6 +69,14 @@
KeyguardSecurityCallback getCallback();
/**
+ * Show a string explaining why the security view needs to be solved.
+ *
+ * @param reason a flag indicating which string should be shown, see {@link #PROMPT_REASON_NONE}
+ * and {@link #PROMPT_REASON_RESTART}
+ */
+ void showPromptReason(int reason);
+
+ /**
* Instruct the view to show usability hints, if any.
*
*/
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
index 54467f3..a0ff21b 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
@@ -131,6 +131,14 @@
}
@Override
+ public void showPromptReason(int reason) {
+ KeyguardSecurityView ksv = getSecurityView();
+ if (ksv != null) {
+ ksv.showPromptReason(reason);
+ }
+ }
+
+ @Override
public void showUsabilityHint() {
KeyguardSecurityView ksv = getSecurityView();
if (ksv != null) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
index f4acff8..aeac912 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
@@ -95,6 +95,12 @@
}
}
+ @Override
+ protected int getPromtReasonStringRes(int reason) {
+ // No message on SIM Pin
+ return 0;
+ }
+
private String getPinPasswordErrorMessage(int attemptsRemaining) {
String displayMessage;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
index b85d966..af88239 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
@@ -140,6 +140,12 @@
}
}
+ @Override
+ protected int getPromtReasonStringRes(int reason) {
+ // No message on SIM Puk
+ return 0;
+ }
+
private String getPukPasswordErrorMessage(int attemptsRemaining) {
String displayMessage;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 273f166..022338d 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -804,8 +804,7 @@
private void startListeningForFingerprint() {
if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
int userId = ActivityManager.getCurrentUser();
- if (mFpm != null && mFpm.isHardwareDetected() && !isFingerprintDisabled(userId)
- && mFpm.getEnrolledFingerprints(userId).size() > 0) {
+ if (isUnlockWithFingerPrintPossible(userId)) {
if (mFingerprintCancelSignal != null) {
mFingerprintCancelSignal.cancel();
}
@@ -815,6 +814,11 @@
}
}
+ public boolean isUnlockWithFingerPrintPossible(int userId) {
+ return mFpm != null && mFpm.isHardwareDetected() && !isFingerprintDisabled(userId)
+ && mFpm.getEnrolledFingerprints(userId).size() > 0;
+ }
+
private void stopListeningForFingerprint() {
if (DEBUG) Log.v(TAG, "stopListeningForFingerprint()");
if (isFingerprintDetectionRunning()) {
diff --git a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
index f5c809a..ff463c6 100644
--- a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
@@ -81,4 +81,12 @@
* @return true if the screen is on
*/
boolean isScreenOn();
+
+ /**
+ * @return one of the reasons why the bouncer needs to be shown right now and the user can't use
+ * his normal unlock method like fingerprint or trust agents. See
+ * {@link KeyguardSecurityView#PROMPT_REASON_NONE}
+ * and {@link KeyguardSecurityView#PROMPT_REASON_RESTART}.
+ */
+ int getBouncerPromptReason();
}
diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml
index 05de5b7..11fa991 100644
--- a/packages/PrintSpooler/res/values/themes.xml
+++ b/packages/PrintSpooler/res/values/themes.xml
@@ -17,6 +17,9 @@
<resources>
<style name="PrintActivity" parent="@android:style/Theme.DeviceDefault">
+ <item name="android:colorPrimary">@*android:color/material_blue_grey_900</item>
+ <item name="android:colorPrimaryDark">@*android:color/material_blue_grey_950</item>
+ <item name="android:colorAccent">@*android:color/material_deep_teal_500</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index b0429ef..249eaa5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -808,7 +808,7 @@
// The pairing dialog now warns of phone-book access for paired devices.
// No separate prompt is displayed after pairing.
if (getPhonebookPermissionChoice() == CachedBluetoothDevice.ACCESS_UNKNOWN) {
- setPhonebookPermissionChoice(CachedBluetoothDevice.ACCESS_ALLOWED);
+ setPhonebookPermissionChoice(CachedBluetoothDevice.ACCESS_REJECTED);
}
}
}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 640fb29..9832b45 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -128,7 +128,7 @@
<activity
android:name=".BugreportWarningActivity"
- android:theme="@*android:style/Theme.Material.DayNight.Dialog.Alert"
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
android:finishOnCloseSystemDialogs="true"
android:excludeFromRecents="true"
android:exported="false" />
diff --git a/packages/Shell/src/com/android/shell/BugreportReceiver.java b/packages/Shell/src/com/android/shell/BugreportReceiver.java
index 13747ed..0c84fa1 100644
--- a/packages/Shell/src/com/android/shell/BugreportReceiver.java
+++ b/packages/Shell/src/com/android/shell/BugreportReceiver.java
@@ -27,6 +27,7 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Configuration;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.FileUtils;
@@ -77,21 +78,12 @@
@Override
public void onReceive(Context context, Intent intent) {
+ final Configuration conf = context.getResources().getConfiguration();
final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT);
final File screenshotFile = getFileExtra(intent, EXTRA_SCREENSHOT);
- // Files are kept on private storage, so turn into Uris that we can
- // grant temporary permissions for.
- final Uri bugreportUri = FileProvider.getUriForFile(context, AUTHORITY, bugreportFile);
- final Uri screenshotUri = FileProvider.getUriForFile(context, AUTHORITY, screenshotFile);
-
- boolean isPlainText = bugreportFile.getName().toLowerCase().endsWith(".txt");
- if (!isPlainText) {
- // Already zipped, send it right away.
- sendBugreportNotification(context, bugreportFile, screenshotFile);
- } else {
- // Asynchronously zip the file first, then send it.
- sendZippedBugreportNotification(context, bugreportFile, screenshotFile);
+ if ((conf.uiMode & Configuration.UI_MODE_TYPE_MASK) != Configuration.UI_MODE_TYPE_WATCH) {
+ triggerLocalNotification(context, bugreportFile, screenshotFile);
}
// Clean up older bugreports in background
@@ -107,6 +99,29 @@
}.execute();
}
+ /**
+ * Responsible for triggering a notification that allows the user to start a
+ * "share" intent with the bug report. On watches we have other methods to allow the user to
+ * start this intent (usually by triggering it on another connected device); we don't need to
+ * display the notification in this case.
+ */
+ private void triggerLocalNotification(final Context context, final File bugreportFile,
+ final File screenshotFile) {
+ // Files are kept on private storage, so turn into Uris that we can
+ // grant temporary permissions for.
+ final Uri bugreportUri = FileProvider.getUriForFile(context, AUTHORITY, bugreportFile);
+ final Uri screenshotUri = FileProvider.getUriForFile(context, AUTHORITY, screenshotFile);
+
+ boolean isPlainText = bugreportFile.getName().toLowerCase().endsWith(".txt");
+ if (!isPlainText) {
+ // Already zipped, send it right away.
+ sendBugreportNotification(context, bugreportFile, screenshotFile);
+ } else {
+ // Asynchronously zip the file first, then send it.
+ sendZippedBugreportNotification(context, bugreportFile, screenshotFile);
+ }
+ }
+
private static Intent buildWarningIntent(Context context, Intent sendIntent) {
final Intent intent = new Intent(context, BugreportWarningActivity.class);
intent.putExtra(Intent.EXTRA_INTENT, sendIntent);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index c06b34f..80761d8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -62,6 +62,7 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardConstants;
import com.android.keyguard.KeyguardDisplayManager;
+import com.android.keyguard.KeyguardSecurityView;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
@@ -526,6 +527,17 @@
public boolean isScreenOn() {
return mDeviceInteractive;
}
+
+ @Override
+ public int getBouncerPromptReason() {
+ int currentUser = ActivityManager.getCurrentUser();
+ if ((mUpdateMonitor.getUserTrustIsManaged(currentUser)
+ || mUpdateMonitor.isUnlockWithFingerPrintPossible(currentUser))
+ && !mTrustManager.hasUserAuthenticatedSinceBoot(currentUser)) {
+ return KeyguardSecurityView.PROMPT_REASON_RESTART;
+ }
+ return KeyguardSecurityView.PROMPT_REASON_NONE;
+ }
};
public void userActivity() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 442af90..89c456c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -316,14 +316,12 @@
void hideRecentsInternal(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
if (mBootCompleted) {
- ActivityManager.RunningTaskInfo topTask = mSystemServicesProxy.getTopMostTask();
- if (topTask != null && mSystemServicesProxy.isRecentsTopMost(topTask, null)) {
- // Notify recents to hide itself
- Intent intent = createLocalBroadcastIntent(mContext, ACTION_HIDE_RECENTS_ACTIVITY);
- intent.putExtra(EXTRA_TRIGGERED_FROM_ALT_TAB, triggeredFromAltTab);
- intent.putExtra(EXTRA_TRIGGERED_FROM_HOME_KEY, triggeredFromHomeKey);
- mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
- }
+ // Defer to the activity to handle hiding recents, if it handles it, then it must still
+ // be visible
+ Intent intent = createLocalBroadcastIntent(mContext, ACTION_HIDE_RECENTS_ACTIVITY);
+ intent.putExtra(EXTRA_TRIGGERED_FROM_ALT_TAB, triggeredFromAltTab);
+ intent.putExtra(EXTRA_TRIGGERED_FROM_HOME_KEY, triggeredFromHomeKey);
+ mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 3885799..3cd769e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -134,9 +134,9 @@
dismissRecentsToFocusedTaskOrHome(false);
} else if (intent.getBooleanExtra(Recents.EXTRA_TRIGGERED_FROM_HOME_KEY, false)) {
// Otherwise, dismiss Recents to Home
- dismissRecentsToHome(true);
+ dismissRecentsToHomeRaw(true);
} else {
- // Do nothing, another activity is being launched on top of Recents
+ // Do nothing
}
} else if (action.equals(Recents.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
// If we are toggling Recents, then first unfilter any filtered stacks first
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
index 02a7b94..d4e50f8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
@@ -70,6 +70,7 @@
@Override
protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidgetInfo) {
if (mCb == null) return;
+ if (mContext == null) return;
SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
if (appWidgetId > -1 && appWidgetId == mConfig.searchBarAppWidgetId) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 5711cd6..ebfc796 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -22,10 +22,12 @@
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
+import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
@@ -133,6 +135,7 @@
}
}
});
+ setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
}
/** Sets the callbacks */
@@ -350,6 +353,7 @@
mTmpTaskViewMap.clear();
List<TaskView> taskViews = getTaskViews();
int taskViewCount = taskViews.size();
+ boolean reaquireAccessibilityFocus = false;
for (int i = taskViewCount - 1; i >= 0; i--) {
TaskView tv = taskViews.get(i);
Task task = tv.getTask();
@@ -358,6 +362,7 @@
mTmpTaskViewMap.put(task, tv);
} else {
mViewPool.returnViewToPool(tv);
+ reaquireAccessibilityFocus |= (i == mPrevAccessibilityFocusedIndex);
// Hide the dismiss button if the front most task is invisible
if (task == mStack.getFrontMostTask()) {
@@ -402,14 +407,17 @@
// Request accessibility focus on the next view if we removed the task
// that previously held accessibility focus
- taskViews = getTaskViews();
- taskViewCount = taskViews.size();
- if (taskViewCount > 0 && ssp.isTouchExplorationEnabled()) {
- TaskView atv = taskViews.get(taskViewCount - 1);
- int indexOfTask = mStack.indexOfTask(atv.getTask());
- if (mPrevAccessibilityFocusedIndex != indexOfTask) {
- tv.requestAccessibilityFocus();
- mPrevAccessibilityFocusedIndex = indexOfTask;
+ if (reaquireAccessibilityFocus) {
+ taskViews = getTaskViews();
+ taskViewCount = taskViews.size();
+ if (taskViewCount > 0 && ssp.isTouchExplorationEnabled() &&
+ mPrevAccessibilityFocusedIndex != -1) {
+ TaskView atv = taskViews.get(taskViewCount - 1);
+ int indexOfTask = mStack.indexOfTask(atv.getTask());
+ if (mPrevAccessibilityFocusedIndex != indexOfTask) {
+ tv.requestAccessibilityFocus();
+ mPrevAccessibilityFocusedIndex = indexOfTask;
+ }
}
}
}
@@ -496,25 +504,20 @@
if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) {
mFocusedTaskIndex = taskIndex;
+ mPrevAccessibilityFocusedIndex = taskIndex;
// Focus the view if possible, otherwise, focus the view after we scroll into position
- Task t = mStack.getTasks().get(taskIndex);
- TaskView tv = getChildViewForTask(t);
- Runnable postScrollRunnable = null;
- if (tv != null) {
- tv.setFocusedTask(animateFocusedState);
- } else {
- postScrollRunnable = new Runnable() {
- @Override
- public void run() {
- Task t = mStack.getTasks().get(mFocusedTaskIndex);
- TaskView tv = getChildViewForTask(t);
- if (tv != null) {
- tv.setFocusedTask(animateFocusedState);
- }
+ final Task t = mStack.getTasks().get(mFocusedTaskIndex);
+ Runnable postScrollRunnable = new Runnable() {
+ @Override
+ public void run() {
+ TaskView tv = getChildViewForTask(t);
+ if (tv != null) {
+ tv.setFocusedTask(animateFocusedState);
+ tv.requestAccessibilityFocus();
}
- };
- }
+ }
+ };
// Scroll the view into position (just center it in the curve)
if (scrollToNewPosition) {
@@ -534,25 +537,30 @@
* Ensures that there is a task focused, if nothing is focused, then we will use the task
* at the center of the visible stack.
*/
- public boolean ensureFocusedTask() {
+ public boolean ensureFocusedTask(boolean findClosestToCenter) {
if (mFocusedTaskIndex < 0) {
- // If there is no task focused, then find the task that is closes to the center
- // of the screen and use that as the currently focused task
- int x = mLayoutAlgorithm.mStackVisibleRect.centerX();
- int y = mLayoutAlgorithm.mStackVisibleRect.centerY();
List<TaskView> taskViews = getTaskViews();
int taskViewCount = taskViews.size();
- for (int i = taskViewCount - 1; i >= 0; i--) {
- TaskView tv = taskViews.get(i);
- tv.getHitRect(mTmpRect);
- if (mTmpRect.contains(x, y)) {
- mFocusedTaskIndex = mStack.indexOfTask(tv.getTask());
- break;
+ if (findClosestToCenter) {
+ // If there is no task focused, then find the task that is closes to the center
+ // of the screen and use that as the currently focused task
+ int x = mLayoutAlgorithm.mStackVisibleRect.centerX();
+ int y = mLayoutAlgorithm.mStackVisibleRect.centerY();
+ for (int i = taskViewCount - 1; i >= 0; i--) {
+ TaskView tv = taskViews.get(i);
+ tv.getHitRect(mTmpRect);
+ if (mTmpRect.contains(x, y)) {
+ mFocusedTaskIndex = mStack.indexOfTask(tv.getTask());
+ mPrevAccessibilityFocusedIndex = mFocusedTaskIndex;
+ break;
+ }
}
}
// If we can't find the center task, then use the front most index
if (mFocusedTaskIndex < 0 && taskViewCount > 0) {
- mFocusedTaskIndex = taskViewCount - 1;
+ TaskView tv = taskViews.get(taskViewCount - 1);
+ mFocusedTaskIndex = mStack.indexOfTask(tv.getTask());
+ mPrevAccessibilityFocusedIndex = mFocusedTaskIndex;
}
}
return mFocusedTaskIndex >= 0;
@@ -600,6 +608,7 @@
}
}
mFocusedTaskIndex = -1;
+ mPrevAccessibilityFocusedIndex = -1;
}
@Override
@@ -620,6 +629,53 @@
}
@Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ List<TaskView> taskViews = getTaskViews();
+ int taskViewCount = taskViews.size();
+ if (taskViewCount > 1 && mPrevAccessibilityFocusedIndex != -1) {
+ info.setScrollable(true);
+ if (mPrevAccessibilityFocusedIndex > 0) {
+ info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+ }
+ if (mPrevAccessibilityFocusedIndex < mStack.getTaskCount() - 1) {
+ info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+ }
+ }
+ }
+
+ @Override
+ public CharSequence getAccessibilityClassName() {
+ return TaskStackView.class.getName();
+ }
+
+ @Override
+ public boolean performAccessibilityAction(int action, Bundle arguments) {
+ if (super.performAccessibilityAction(action, arguments)) {
+ return true;
+ }
+ if (ensureFocusedTask(false)) {
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
+ if (mPrevAccessibilityFocusedIndex > 0) {
+ focusNextTask(true, false);
+ return true;
+ }
+ }
+ break;
+ case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
+ if (mPrevAccessibilityFocusedIndex < mStack.getTaskCount() - 1) {
+ focusNextTask(false, false);
+ return true;
+ }
+ }
+ break;
+ }
+ }
+ return false;
+ }
+
+ @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mTouchHandler.onInterceptTouchEvent(ev);
}
@@ -724,8 +780,8 @@
if (mDismissAllButton != null) {
int taskRectWidth = mLayoutAlgorithm.mTaskRect.width();
mDismissAllButton.measure(
- MeasureSpec.makeMeasureSpec(taskRectWidth, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(mConfig.dismissAllButtonSizePx, MeasureSpec.EXACTLY));
+ MeasureSpec.makeMeasureSpec(taskRectWidth, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(mConfig.dismissAllButtonSizePx, MeasureSpec.EXACTLY));
}
setMeasuredDimension(width, height);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 509560eb..13bdbd2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -396,11 +396,11 @@
// Find the front most task and scroll the next task to the front
float vScroll = ev.getAxisValue(MotionEvent.AXIS_VSCROLL);
if (vScroll > 0) {
- if (mSv.ensureFocusedTask()) {
+ if (mSv.ensureFocusedTask(true)) {
mSv.focusNextTask(true, false);
}
} else {
- if (mSv.ensureFocusedTask()) {
+ if (mSv.ensureFocusedTask(true)) {
mSv.focusNextTask(false, false);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 79761ec..a496548 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -41,6 +41,7 @@
import android.database.ContentObserver;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
@@ -1396,6 +1397,7 @@
final StatusBarIcon ic = new StatusBarIcon(
entry.notification.getUser(),
+ entry.notification.getPackageName(),
entry.notification.getNotification().getSmallIcon(),
entry.notification.getNotification().iconLevel,
entry.notification.getNotification().number,
@@ -1682,10 +1684,11 @@
final StatusBarIcon ic = new StatusBarIcon(
sbn.getUser(),
- n.getSmallIcon(),
- n.iconLevel,
- n.number,
- n.tickerText);
+ sbn.getPackageName(),
+ n.getSmallIcon(),
+ n.iconLevel,
+ n.number,
+ n.tickerText);
if (!iconView.set(ic)) {
handleNotificationError(sbn, "Couldn't create icon: " + ic);
return null;
@@ -1825,6 +1828,7 @@
// Update the icon
final StatusBarIcon ic = new StatusBarIcon(
notification.getUser(),
+ notification.getPackageName(),
n.getSmallIcon(),
n.iconLevel,
n.number,
@@ -1847,6 +1851,7 @@
if (DEBUG) Log.d(TAG, "not reusing notification for key: " + key);
final StatusBarIcon ic = new StatusBarIcon(
notification.getUser(),
+ notification.getPackageName(),
n.getSmallIcon(),
n.iconLevel,
n.number,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index dbabe3f..aedae52 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -125,16 +125,22 @@
@Override
public int compare(Entry a, Entry b) {
- String mediaNotification = mEnvironment.getCurrentMediaNotificationKey();
- boolean aMedia = a.key.equals(mediaNotification);
- boolean bMedia = b.key.equals(mediaNotification);
-
final StatusBarNotification na = a.notification;
final StatusBarNotification nb = b.notification;
+ final int aPriority = na.getNotification().priority;
+ final int bPriority = nb.getNotification().priority;
- boolean aSystemMax = na.getNotification().priority >= Notification.PRIORITY_MAX &&
+ String mediaNotification = mEnvironment.getCurrentMediaNotificationKey();
+
+ // PRIORITY_MIN media streams are allowed to drift to the bottom
+ final boolean aMedia = a.key.equals(mediaNotification)
+ && aPriority > Notification.PRIORITY_MIN;
+ final boolean bMedia = b.key.equals(mediaNotification)
+ && bPriority > Notification.PRIORITY_MIN;
+
+ boolean aSystemMax = aPriority >= Notification.PRIORITY_MAX &&
isSystemNotification(na);
- boolean bSystemMax = nb.getNotification().priority >= Notification.PRIORITY_MAX &&
+ boolean bSystemMax = bPriority >= Notification.PRIORITY_MAX &&
isSystemNotification(nb);
int d = nb.getScore() - na.getScore();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 9e0b08b..5a4acb4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -251,6 +251,9 @@
@Override
public void setSubs(List<SubscriptionInfo> subs) {
+ if (hasCorrectSubs(subs)) {
+ return;
+ }
// Clear out all old subIds.
mPhoneStates.clear();
if (mMobileSignalGroup != null) {
@@ -265,6 +268,19 @@
}
}
+ private boolean hasCorrectSubs(List<SubscriptionInfo> subs) {
+ final int N = subs.size();
+ if (N != mPhoneStates.size()) {
+ return false;
+ }
+ for (int i = 0; i < N; i++) {
+ if (mPhoneStates.get(i).mSubId != subs.get(i).getSubscriptionId()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
private PhoneState getOrInflateState(int subId) {
for (PhoneState state : mPhoneStates) {
if (state.mSubId == subId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
index 26d1c86..fcdd4b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -124,6 +124,9 @@
private void updateSlot(String slot, String iconPkg, int iconId) {
if (!mDemoMode) return;
+ if (iconPkg == null) {
+ iconPkg = mContext.getPackageName();
+ }
int removeIndex = -1;
for (int i = 0; i < getChildCount(); i++) {
StatusBarIconView v = (StatusBarIconView) getChildAt(i);
@@ -143,10 +146,10 @@
if (iconId == 0) {
if (removeIndex != -1) {
removeViewAt(removeIndex);
- return;
}
+ return;
}
- StatusBarIcon icon = new StatusBarIcon(iconPkg, UserHandle.CURRENT, iconId, 0, 0, "Demo");
+ StatusBarIcon icon = new StatusBarIcon(iconPkg, UserHandle.OWNER, iconId, 0, 0, "Demo");
StatusBarIconView v = new StatusBarIconView(getContext(), null, null);
v.setTag(slot);
v.set(icon);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
index f57575d..10c35af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
@@ -110,6 +110,8 @@
mInitialTouchX = x;
mInitialTouchY = y;
int expandedHeight = mPickedChild.getActualHeight();
+ mPanel.setPanelScrimMinFraction((float) expandedHeight
+ / mPanel.getMaxPanelHeight());
mPanel.startExpandMotion(x, y, true /* startTracking */, expandedHeight
+ mNotificationsTopPadding);
mHeadsUpManager.unpinAll();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 3737d05..a3bb129 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -26,6 +26,7 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardHostView;
+import com.android.keyguard.KeyguardSecurityView;
import com.android.keyguard.R;
import com.android.keyguard.ViewMediatorCallback;
@@ -46,6 +47,7 @@
private ViewGroup mRoot;
private boolean mShowingSoon;
private Choreographer mChoreographer = Choreographer.getInstance();
+ private int mBouncerPromptReason;
public KeyguardBouncer(Context context, ViewMediatorCallback callback,
LockPatternUtils lockPatternUtils, StatusBarWindowManager windowManager,
@@ -68,6 +70,8 @@
return;
}
+ mBouncerPromptReason = mCallback.getBouncerPromptReason();
+
// Try to dismiss the Keyguard. If no security pattern is set, this will dismiss the whole
// Keyguard. If we need to authenticate, show the bouncer.
if (!mKeyguardView.dismiss()) {
@@ -84,12 +88,24 @@
public void run() {
mRoot.setVisibility(View.VISIBLE);
mKeyguardView.onResume();
+ showPromptReason(mBouncerPromptReason);
mKeyguardView.startAppearAnimation();
mShowingSoon = false;
mKeyguardView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
};
+ /**
+ * Show a string explaining why the security view needs to be solved.
+ *
+ * @param reason a flag indicating which string should be shown, see
+ * {@link KeyguardSecurityView#PROMPT_REASON_NONE}
+ * and {@link KeyguardSecurityView#PROMPT_REASON_RESTART}
+ */
+ public void showPromptReason(int reason) {
+ mKeyguardView.showPromptReason(reason);
+ }
+
private void cancelShowRunnable() {
mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION, mShowRunnable, null);
mShowingSoon = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 5ac436a..c30cb34 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -491,7 +491,7 @@
}
public void closeQs() {
- cancelAnimation();
+ cancelQsAnimation();
setQsExpansion(mQsMinExpansionHeight);
}
@@ -508,7 +508,7 @@
}
public void openQs() {
- cancelAnimation();
+ cancelQsAnimation();
if (mQsExpansionEnabled) {
setQsExpansion(mQsMaxExpansionHeight);
}
@@ -921,7 +921,7 @@
@Override
public void onOverscrollTopChanged(float amount, boolean isRubberbanded) {
- cancelAnimation();
+ cancelQsAnimation();
if (!mQsExpansionEnabled) {
amount = 0f;
}
@@ -953,7 +953,8 @@
}
private void onQsExpansionStarted(int overscrollAmount) {
- cancelAnimation();
+ cancelQsAnimation();
+ cancelHeightAnimator();
// Reset scroll position and apply that position to the expanded height.
float height = mQsExpansionHeight - mScrollView.getScrollY() - overscrollAmount;
@@ -1391,7 +1392,7 @@
return mVelocityTracker.getYVelocity();
}
- private void cancelAnimation() {
+ private void cancelQsAnimation() {
if (mQsExpansionAnimator != null) {
mQsExpansionAnimator.cancel();
}
@@ -1767,6 +1768,7 @@
mIsExpansionFromHeadsUp = false;
mNotificationStackScroller.setTrackingHeadsUp(false);
mExpandingFromHeadsUp = false;
+ setPanelScrimMinFraction(0.0f);
}
private void setListening(boolean listening) {
@@ -2317,7 +2319,7 @@
}
x = Math.min(rightMost, Math.max(leftMost, x));
setVerticalPanelTranslation(x -
- (mNotificationStackScroller.getLeft() + mNotificationStackScroller.getWidth()/2));
+ (mNotificationStackScroller.getLeft() + mNotificationStackScroller.getWidth() / 2));
}
private void resetVerticalPanelPosition() {
@@ -2334,4 +2336,8 @@
mNotificationStackScroller.setStackHeight(stackHeight);
updateKeyguardBottomAreaAlpha();
}
+
+ public void setPanelScrimMinFraction(float minFraction) {
+ mBar.panelScrimMinFractionChanged(minFraction);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index 552a0b2..cf553ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -25,7 +25,7 @@
import java.util.ArrayList;
-public class PanelBar extends FrameLayout {
+public abstract class PanelBar extends FrameLayout {
public static final boolean DEBUG = false;
public static final String TAG = PanelBar.class.getSimpleName();
public static final void LOG(String fmt, Object... args) {
@@ -156,6 +156,8 @@
}
}
+ public abstract void panelScrimMinFractionChanged(float minFraction);
+
/**
* @param panel the panel which changed its expansion state
* @param frac the fraction from the expansion in [0, 1]
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 9d4997c..094d5f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -535,7 +535,7 @@
*/
protected abstract boolean isInContentBounds(float x, float y);
- private void cancelHeightAnimator() {
+ protected void cancelHeightAnimator() {
if (mHeightAnimator != null) {
mHeightAnimator.cancel();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 69198ed..cd90d27 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -3460,6 +3460,7 @@
mKeyguardIndicationController.setVisible(true);
mNotificationPanel.resetViews();
mKeyguardUserSwitcher.setKeyguard(true, fromShadeLocked);
+ mStatusBarView.removePendingHideExpandedRunnables();
} else {
mKeyguardIndicationController.setVisible(false);
mKeyguardUserSwitcher.setKeyguard(false,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index b7e675d..6a46924 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -40,6 +40,14 @@
PanelView mNotificationPanel;
private final PhoneStatusBarTransitions mBarTransitions;
private ScrimController mScrimController;
+ private float mMinFraction;
+ private float mPanelFraction;
+ private Runnable mHideExpandedRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mBar.makeExpandedInvisible();
+ }
+ };
public PhoneStatusBarView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -116,15 +124,14 @@
+ Log.getStackTraceString(new Throwable()));
}
// Close the status bar in the next frame so we can show the end of the animation.
- postOnAnimation(new Runnable() {
- @Override
- public void run() {
- mBar.makeExpandedInvisible();
- }
- });
+ postOnAnimation(mHideExpandedRunnable);
mLastFullyOpenedPanel = null;
}
+ public void removePendingHideExpandedRunnables() {
+ removeCallbacks(mHideExpandedRunnable);
+ }
+
@Override
public void onPanelFullyOpened(PanelView openPanel) {
super.onPanelFullyOpened(openPanel);
@@ -180,8 +187,22 @@
}
@Override
+ public void panelScrimMinFractionChanged(float minFraction) {
+ if (mMinFraction != minFraction) {
+ mMinFraction = minFraction;
+ updateScrimFraction();
+ }
+ }
+
+ @Override
public void panelExpansionChanged(PanelView panel, float frac, boolean expanded) {
super.panelExpansionChanged(panel, frac, expanded);
- mScrimController.setPanelExpansion(frac);
+ mPanelFraction = frac;
+ updateScrimFraction();
+ }
+
+ private void updateScrimFraction() {
+ float scrimFraction = Math.max(mPanelFraction - mMinFraction / (1.0f - mMinFraction), 0);
+ mScrimController.setPanelExpansion(scrimFraction);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java
index 0eb7197..d1e4963 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java
@@ -116,7 +116,7 @@
// Unknown network, need to add it.
if (ap.getSecurity() != AccessPoint.SECURITY_NONE) {
Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
- intent.putExtra(EXTRA_START_CONNECT_SSID, ap.getSsid());
+ intent.putExtra(EXTRA_START_CONNECT_SSID, ap.getSsidStr());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
fireSettingsIntentCallback(intent);
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 18b5820..1ba87da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -408,7 +408,7 @@
boolean hasNoSims = mHasMobileDataFeature && mMobileSignalControllers.size() == 0;
if (hasNoSims != mHasNoSims) {
mHasNoSims = hasNoSims;
- notifyListeners();
+ mCallbackHandler.setNoSims(mHasNoSims);
}
}
@@ -660,8 +660,8 @@
}
String nosim = args.getString("nosim");
if (nosim != null) {
- boolean show = nosim.equals("show");
- mCallbackHandler.setNoSims(show);
+ mHasNoSims = nosim.equals("show");
+ mCallbackHandler.setNoSims(mHasNoSims);
}
String mobile = args.getString("mobile");
if (mobile != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 1bf4547..5700732 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -228,6 +228,7 @@
private ScrimController mScrimController;
private boolean mForceNoOverlappingRendering;
private NotificationOverflowContainer mOverflowContainer;
+ private final ArrayList<Pair<ExpandableNotificationRow, Boolean>> mTmpList = new ArrayList<>();
public NotificationStackScrollLayout(Context context) {
this(context, null);
@@ -1608,7 +1609,7 @@
}
@Override
- protected void onViewRemoved(View child) {
+ public void onViewRemoved(View child) {
super.onViewRemoved(child);
// we only call our internal methods if this is actually a removal and not just a
// notification which becomes a child notification
@@ -1651,8 +1652,7 @@
* @return Whether an animation was generated.
*/
private boolean generateRemoveAnimation(View child) {
- if (mAddedHeadsUpChildren.contains(child)) {
- removeChildFromHeadsUpChangeAnimations(child);
+ if (removeRemovedChildFromHeadsUpChangeAnimations(child)) {
mAddedHeadsUpChildren.remove(child);
return false;
}
@@ -1671,15 +1671,27 @@
return false;
}
- private void removeChildFromHeadsUpChangeAnimations(View child) {
- ArrayList<Pair<ExpandableNotificationRow, Boolean> > toRemove = new ArrayList<>();
+ /**
+ * Remove a removed child view from the heads up animations if it was just added there
+ *
+ * @return whether any child was removed from the list to animate
+ */
+ private boolean removeRemovedChildFromHeadsUpChangeAnimations(View child) {
+ boolean hasAddEvent = false;
for (Pair<ExpandableNotificationRow, Boolean> eventPair : mHeadsUpChangeAnimations) {
ExpandableNotificationRow row = eventPair.first;
+ boolean isHeadsUp = eventPair.second;
if (child == row) {
- toRemove.add(eventPair);
+ mTmpList.add(eventPair);
+ hasAddEvent |= isHeadsUp;
}
}
- mHeadsUpChangeAnimations.removeAll(toRemove);
+ if (hasAddEvent) {
+ // This child was just added lets remove all events.
+ mHeadsUpChangeAnimations.removeAll(mTmpList);
+ }
+ mTmpList.clear();
+ return hasAddEvent;
}
/**
@@ -1745,7 +1757,7 @@
}
@Override
- protected void onViewAdded(View child) {
+ public void onViewAdded(View child) {
super.onViewAdded(child);
onViewAddedInternal(child);
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
index d9f0598..ca6aaeb 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
@@ -131,11 +131,14 @@
intent.putExtra("mobile", "show");
intent.putExtra("sims", "1");
intent.putExtra("nosim", "false");
- intent.putExtra("fully", "true");
intent.putExtra("level", "4");
intent.putExtra("datatypel", "");
getContext().sendBroadcast(intent);
+ // Need to send this after so that the sim controller already exists.
+ intent.putExtra("fully", "true");
+ getContext().sendBroadcast(intent);
+
intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_BATTERY);
intent.putExtra("level", "100");
intent.putExtra("plugged", "false");
diff --git a/packages/SystemUI/src/com/android/systemui/volume/Events.java b/packages/SystemUI/src/com/android/systemui/volume/Events.java
index 12dca94..893c939 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/Events.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/Events.java
@@ -16,11 +16,13 @@
package com.android.systemui.volume;
+import android.content.Context;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.provider.Settings.Global;
import android.util.Log;
+import com.android.internal.logging.MetricsLogger;
import com.android.systemui.volume.VolumeDialogController.State;
import java.util.Arrays;
@@ -47,6 +49,7 @@
public static final int EVENT_ZEN_MODE_CHANGED = 13; // (mode|int)
public static final int EVENT_SUPPRESSOR_CHANGED = 14; // (component|string) (name|string)
public static final int EVENT_MUTE_CHANGED = 15; // (stream|int) (muted|bool)
+ public static final int EVENT_TOUCH_LEVEL_DONE = 16; // (stream|int) (level|bool)
private static final String[] EVENT_TAGS = {
"show_dialog",
@@ -65,6 +68,7 @@
"zen_mode_changed",
"suppressor_changed",
"mute_changed",
+ "touch_level_done",
};
public static final int DISMISS_REASON_UNKNOWN = 0;
@@ -100,36 +104,59 @@
public static Callback sCallback;
- public static void writeEvent(int tag, Object... list) {
+ public static void writeEvent(Context context, int tag, Object... list) {
final long time = System.currentTimeMillis();
final StringBuilder sb = new StringBuilder("writeEvent ").append(EVENT_TAGS[tag]);
if (list != null && list.length > 0) {
sb.append(" ");
switch (tag) {
case EVENT_SHOW_DIALOG:
+ MetricsLogger.visible(context, MetricsLogger.VOLUME_DIALOG);
+ MetricsLogger.histogram(context, "volume_from_keyguard",
+ (Boolean) list[1] ? 1 : 0);
sb.append(SHOW_REASONS[(Integer) list[0]]).append(" keyguard=").append(list[1]);
break;
case EVENT_EXPAND:
+ MetricsLogger.visibility(context, MetricsLogger.VOLUME_DIALOG_DETAILS,
+ (Boolean) list[0]);
sb.append(list[0]);
break;
case EVENT_DISMISS_DIALOG:
+ MetricsLogger.hidden(context, MetricsLogger.VOLUME_DIALOG);
sb.append(DISMISS_REASONS[(Integer) list[0]]);
break;
case EVENT_ACTIVE_STREAM_CHANGED:
+ MetricsLogger.action(context, MetricsLogger.ACTION_VOLUME_STREAM,
+ (Integer) list[0]);
sb.append(AudioSystem.streamToString((Integer) list[0]));
break;
case EVENT_ICON_CLICK:
+ MetricsLogger.action(context, MetricsLogger.ACTION_VOLUME_ICON,
+ (Integer) list[1]);
sb.append(AudioSystem.streamToString((Integer) list[0])).append(' ')
.append(iconStateToString((Integer) list[1]));
break;
+ case EVENT_TOUCH_LEVEL_DONE:
+ MetricsLogger.action(context, MetricsLogger.ACTION_VOLUME_SLIDER,
+ (Integer) list[1]);
+ // fall through
case EVENT_TOUCH_LEVEL_CHANGED:
case EVENT_LEVEL_CHANGED:
case EVENT_MUTE_CHANGED:
sb.append(AudioSystem.streamToString((Integer) list[0])).append(' ')
.append(list[1]);
break;
- case EVENT_INTERNAL_RINGER_MODE_CHANGED:
+ case EVENT_KEY:
+ MetricsLogger.action(context, MetricsLogger.ACTION_VOLUME_KEY,
+ (Integer) list[1]);
+ sb.append(AudioSystem.streamToString((Integer) list[0])).append(' ')
+ .append(list[1]);
+ break;
case EVENT_EXTERNAL_RINGER_MODE_CHANGED:
+ MetricsLogger.action(context, MetricsLogger.ACTION_RINGER_MODE,
+ (Integer) list[0]);
+ // fall through
+ case EVENT_INTERNAL_RINGER_MODE_CHANGED:
sb.append(ringerModeToString((Integer) list[0]));
break;
case EVENT_ZEN_MODE_CHANGED:
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index aa891b6..5b2eb84 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -369,7 +369,7 @@
row.icon.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- Events.writeEvent(Events.EVENT_ICON_CLICK, row.stream, row.iconState);
+ Events.writeEvent(mContext, Events.EVENT_ICON_CLICK, row.stream, row.iconState);
mController.setActiveStream(row.stream);
if (row.stream == AudioManager.STREAM_RING) {
final boolean hasVibrator = mController.hasVibrator();
@@ -417,7 +417,7 @@
if (mShowing) return;
mShowing = true;
mDialog.show();
- Events.writeEvent(Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked());
+ Events.writeEvent(mContext, Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked());
mController.notifyVisible(true);
}
@@ -444,7 +444,7 @@
if (!mShowing) return;
mShowing = false;
mDialog.dismiss();
- Events.writeEvent(Events.EVENT_DISMISS_DIALOG, reason);
+ Events.writeEvent(mContext, Events.EVENT_DISMISS_DIALOG, reason);
setExpandedH(false);
mController.notifyVisible(false);
synchronized (mSafetyWarningLock) {
@@ -834,7 +834,7 @@
public void onClick(View v) {
if (mExpanding) return;
final boolean newExpand = !mExpanded;
- Events.writeEvent(Events.EVENT_EXPAND, v);
+ Events.writeEvent(mContext, Events.EVENT_EXPAND, newExpand);
setExpandedH(newExpand);
}
};
@@ -845,7 +845,7 @@
mSettingsButton.postDelayed(new Runnable() {
@Override
public void run() {
- Events.writeEvent(Events.EVENT_SETTINGS_CLICK);
+ Events.writeEvent(mContext, Events.EVENT_SETTINGS_CLICK);
if (mCallback != null) {
mCallback.onSettingsClicked();
}
@@ -933,7 +933,8 @@
if (mRow.requestedLevel != userLevel) {
mController.setStreamVolume(mRow.stream, userLevel);
mRow.requestedLevel = userLevel;
- Events.writeEvent(Events.EVENT_TOUCH_LEVEL_CHANGED, mRow.stream, userLevel);
+ Events.writeEvent(mContext, Events.EVENT_TOUCH_LEVEL_CHANGED, mRow.stream,
+ userLevel);
}
}
}
@@ -951,6 +952,7 @@
mRow.tracking = false;
mRow.userAttempt = SystemClock.uptimeMillis();
int userLevel = getImpliedLevel(seekBar, seekBar.getProgress());
+ Events.writeEvent(mContext, Events.EVENT_TOUCH_LEVEL_DONE, mRow.stream, userLevel);
if (mRow.ss.level != userLevel) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(H.RECHECK, mRow),
USER_ATTEMPT_GRACE_PERIOD);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
index c6d9e46..9a59a2a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
@@ -104,7 +104,7 @@
public VolumeDialogController(Context context, ComponentName component) {
mContext = context.getApplicationContext();
- Events.writeEvent(Events.EVENT_COLLECTION_STARTED);
+ Events.writeEvent(mContext, Events.EVENT_COLLECTION_STARTED);
mComponent = component;
mWorkerThread = new HandlerThread(VolumeDialogController.class.getSimpleName());
mWorkerThread.start();
@@ -168,7 +168,7 @@
if (D.BUG) Log.d(TAG, "destroy");
if (mDestroyed) return;
mDestroyed = true;
- Events.writeEvent(Events.EVENT_COLLECTION_STOPPED);
+ Events.writeEvent(mContext, Events.EVENT_COLLECTION_STOPPED);
mMediaSessions.destroy();
mObserver.destroy();
mReceiver.destroy();
@@ -293,7 +293,8 @@
if (showUI) {
changed |= updateActiveStreamW(stream);
}
- changed |= updateStreamLevelW(stream, mAudio.getLastAudibleStreamVolume(stream));
+ int lastAudibleStreamVolume = mAudio.getLastAudibleStreamVolume(stream);
+ changed |= updateStreamLevelW(stream, lastAudibleStreamVolume);
changed |= checkRoutedToBluetoothW(showUI ? AudioManager.STREAM_MUSIC : stream);
if (changed) {
mCallbacks.onStateChanged(mState);
@@ -308,14 +309,14 @@
mCallbacks.onShowSilentHint();
}
if (changed && fromKey) {
- Events.writeEvent(Events.EVENT_KEY);
+ Events.writeEvent(mContext, Events.EVENT_KEY, stream, lastAudibleStreamVolume);
}
}
private boolean updateActiveStreamW(int activeStream) {
if (activeStream == mState.activeStream) return false;
mState.activeStream = activeStream;
- Events.writeEvent(Events.EVENT_ACTIVE_STREAM_CHANGED, activeStream);
+ Events.writeEvent(mContext, Events.EVENT_ACTIVE_STREAM_CHANGED, activeStream);
if (D.BUG) Log.d(TAG, "updateActiveStreamW " + activeStream);
final int s = activeStream < DYNAMIC_STREAM_START_INDEX ? activeStream : -1;
if (D.BUG) Log.d(TAG, "forceVolumeControlStream " + s);
@@ -364,7 +365,7 @@
if (ss.level == level) return false;
ss.level = level;
if (isLogWorthy(stream)) {
- Events.writeEvent(Events.EVENT_LEVEL_CHANGED, stream, level);
+ Events.writeEvent(mContext, Events.EVENT_LEVEL_CHANGED, stream, level);
}
return true;
}
@@ -387,7 +388,7 @@
if (ss.muted == muted) return false;
ss.muted = muted;
if (isLogWorthy(stream)) {
- Events.writeEvent(Events.EVENT_MUTE_CHANGED, stream, muted);
+ Events.writeEvent(mContext, Events.EVENT_MUTE_CHANGED, stream, muted);
}
if (muted && isRinger(stream)) {
updateRingerModeInternalW(mAudio.getRingerModeInternal());
@@ -410,7 +411,7 @@
if (Objects.equals(mState.effectsSuppressor, effectsSuppressor)) return false;
mState.effectsSuppressor = effectsSuppressor;
mState.effectsSuppressorName = getApplicationName(mContext, mState.effectsSuppressor);
- Events.writeEvent(Events.EVENT_SUPPRESSOR_CHANGED, mState.effectsSuppressor,
+ Events.writeEvent(mContext, Events.EVENT_SUPPRESSOR_CHANGED, mState.effectsSuppressor,
mState.effectsSuppressorName);
return true;
}
@@ -434,21 +435,21 @@
Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
if (mState.zenMode == zen) return false;
mState.zenMode = zen;
- Events.writeEvent(Events.EVENT_ZEN_MODE_CHANGED, zen);
+ Events.writeEvent(mContext, Events.EVENT_ZEN_MODE_CHANGED, zen);
return true;
}
private boolean updateRingerModeExternalW(int rm) {
if (rm == mState.ringerModeExternal) return false;
mState.ringerModeExternal = rm;
- Events.writeEvent(Events.EVENT_EXTERNAL_RINGER_MODE_CHANGED, rm);
+ Events.writeEvent(mContext, Events.EVENT_EXTERNAL_RINGER_MODE_CHANGED, rm);
return true;
}
private boolean updateRingerModeInternalW(int rm) {
if (rm == mState.ringerModeInternal) return false;
mState.ringerModeInternal = rm;
- Events.writeEvent(Events.EVENT_INTERNAL_RINGER_MODE_CHANGED, rm);
+ Events.writeEvent(mContext, Events.EVENT_INTERNAL_RINGER_MODE_CHANGED, rm);
return true;
}
diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml
index 32e1e6d..375c5d8 100644
--- a/packages/VpnDialogs/AndroidManifest.xml
+++ b/packages/VpnDialogs/AndroidManifest.xml
@@ -24,7 +24,7 @@
<application android:label="VpnDialogs"
android:allowBackup="false" >
<activity android:name=".ConfirmDialog"
- android:theme="@*android:style/Theme.Material.DayNight.Dialog.Alert">
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.DEFAULT"/>
@@ -32,7 +32,7 @@
</activity>
<activity android:name=".ManageDialog"
- android:theme="@*android:style/Theme.Material.DayNight.Dialog.Alert"
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
android:noHistory="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
diff --git a/packages/WallpaperCropper/res/values/styles.xml b/packages/WallpaperCropper/res/values/styles.xml
index e438c84..a34b25a 100644
--- a/packages/WallpaperCropper/res/values/styles.xml
+++ b/packages/WallpaperCropper/res/values/styles.xml
@@ -15,13 +15,13 @@
-->
<resources>
- <style name="Theme.WallpaperCropper" parent="@android:style/Theme.Material.DayNight">
+ <style name="Theme.WallpaperCropper" parent="@android:style/Theme.DeviceDefault">
<item name="android:actionBarStyle">@style/WallpaperCropperActionBar</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowActionBarOverlay">true</item>
</style>
- <style name="WallpaperCropperActionBar" parent="@android:style/Widget.Material.ActionBar">
+ <style name="WallpaperCropperActionBar" parent="android:style/Widget.DeviceDefault.ActionBar">
<item name="android:displayOptions">showCustom</item>
<item name="android:background">#88000000</item>
</style>
diff --git a/rs/java/android/renderscript/ScriptGroup.java b/rs/java/android/renderscript/ScriptGroup.java
index 82d9a2f..9000d4d 100644
--- a/rs/java/android/renderscript/ScriptGroup.java
+++ b/rs/java/android/renderscript/ScriptGroup.java
@@ -851,13 +851,13 @@
* Returns the field ID
*/
- public Script.FieldID getField() { return mField; }
+ Script.FieldID getField() { return mField; }
/**
* Returns the value
*/
- public Object getValue() { return mValue; }
+ Object getValue() { return mValue; }
}
/**
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 17d7078..30680ed 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -37,6 +37,7 @@
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
@@ -1281,7 +1282,7 @@
}
@Override
- public List<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
+ public ParceledListSlice<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
int profileId) {
final int userId = UserHandle.getCallingUserId();
@@ -1297,7 +1298,7 @@
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
- ArrayList<AppWidgetProviderInfo> result = null;
+ ArrayList<AppWidgetProviderInfo> result = new ArrayList<AppWidgetProviderInfo>();
final int providerCount = mProviders.size();
for (int i = 0; i < providerCount; i++) {
@@ -1314,14 +1315,11 @@
if (providerProfileId == profileId
&& mSecurityPolicy.isProviderInCallerOrInProfileAndWhitelListed(
provider.id.componentName.getPackageName(), providerProfileId)) {
- if (result == null) {
- result = new ArrayList<>();
- }
result.add(cloneIfLocalBinder(info));
}
}
- return result;
+ return new ParceledListSlice<AppWidgetProviderInfo>(result);
}
}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 26ece72..839b87a 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -20,13 +20,16 @@
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.AlarmManager;
+import android.app.BroadcastOptions;
import android.app.IAlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.database.ContentObserver;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -43,6 +46,7 @@
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.util.ArrayMap;
+import android.util.KeyValueListParser;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -75,22 +79,6 @@
import com.android.internal.util.LocalLog;
class AlarmManagerService extends SystemService {
- // The threshold for how long an alarm can be late before we print a
- // warning message. The time duration is in milliseconds.
- private static final long LATE_ALARM_THRESHOLD = 10 * 1000;
-
- // Minimum futurity of a new alarm
- private static final long MIN_FUTURITY = 5 * 1000; // 5 seconds, in millis
-
- // Minimum alarm recurrence interval
- private static final long MIN_INTERVAL = 60 * 1000; // one minute, in millis
-
- // Minimum time between ALLOW_WHILE_IDLE alarms when system is not idle.
- private static final long ALLOW_WHILE_IDLE_SHORT_TIME = 60*1000;
-
- // Minimum time between ALLOW_WHILE_IDLE alarms when system is idling.
- private static final long ALLOW_WHILE_IDLE_LONG_TIME = 15*60*1000;
-
private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP;
private static final int RTC_MASK = 1 << RTC;
private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
@@ -102,7 +90,6 @@
static final int TYPE_NONWAKEUP_MASK = 0x1; // low bit => non-wakeup
static final String TAG = "AlarmManager";
- static final String ClockReceiver_TAG = "ClockReceiver";
static final boolean localLOGV = false;
static final boolean DEBUG_BATCH = localLOGV || false;
static final boolean DEBUG_VALIDATE = localLOGV || false;
@@ -148,7 +135,7 @@
long mNextNonWakeupDeliveryTime;
long mLastTimeChangeClockTime;
long mLastTimeChangeRealtime;
- long mAllowWhileIdleMinTime = ALLOW_WHILE_IDLE_SHORT_TIME;
+ long mAllowWhileIdleMinTime;
int mNumTimeChanged;
/**
@@ -157,6 +144,11 @@
*/
final SparseLongArray mLastAllowWhileIdleDispatch = new SparseLongArray();
+ /**
+ * Broadcast options to use for FLAG_ALLOW_WHILE_IDLE.
+ */
+ Bundle mIdleOptions;
+
private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
new SparseArray<>();
private final SparseArray<AlarmManager.AlarmClockInfo> mTmpSparseAlarmClockArray =
@@ -169,12 +161,137 @@
private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
new SparseArray<>();
+ /**
+ * All times are in milliseconds. These constants are kept synchronized with the system
+ * global Settings. Any access to this class or its fields should be done while
+ * holding the AlarmManagerService.mLock lock.
+ */
+ private final class Constants extends ContentObserver {
+ // Key names stored in the settings value.
+ private static final String KEY_MIN_FUTURITY = "min_futurity";
+ private static final String KEY_MIN_INTERVAL = "min_interval";
+ private static final String KEY_ALLOW_WHILE_IDLE_SHORT_TIME = "allow_while_idle_short_time";
+ private static final String KEY_ALLOW_WHILE_IDLE_LONG_TIME = "allow_while_idle_long_time";
+ private static final String KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION
+ = "allow_while_idle_whitelist_duration";
+
+ private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
+ private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
+ private static final long DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME = 60*1000;
+ private static final long DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME = 15*60*1000;
+ private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000;
+
+ // Minimum futurity of a new alarm
+ public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
+
+ // Minimum alarm recurrence interval
+ public long MIN_INTERVAL = DEFAULT_MIN_INTERVAL;
+
+ // Minimum time between ALLOW_WHILE_IDLE alarms when system is not idle.
+ public long ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME;
+
+ // Minimum time between ALLOW_WHILE_IDLE alarms when system is idling.
+ public long ALLOW_WHILE_IDLE_LONG_TIME = DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME;
+
+ // BroadcastOptions.setTemporaryAppWhitelistDuration() to use for FLAG_ALLOW_WHILE_IDLE.
+ public long ALLOW_WHILE_IDLE_WHITELIST_DURATION
+ = DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
+
+ private ContentResolver mResolver;
+ private final KeyValueListParser mParser = new KeyValueListParser(',');
+ private long mLastAllowWhileIdleWhitelistDuration = -1;
+
+ public Constants(Handler handler) {
+ super(handler);
+ updateAllowWhileIdleMinTimeLocked();
+ updateAllowWhileIdleWhitelistDurationLocked();
+ }
+
+ public void start(ContentResolver resolver) {
+ mResolver = resolver;
+ mResolver.registerContentObserver(Settings.Global.getUriFor(
+ Settings.Global.ALARM_MANAGER_CONSTANTS), false, this);
+ updateConstants();
+ }
+
+ public void updateAllowWhileIdleMinTimeLocked() {
+ mAllowWhileIdleMinTime = mPendingIdleUntil != null
+ ? ALLOW_WHILE_IDLE_LONG_TIME : ALLOW_WHILE_IDLE_SHORT_TIME;
+ }
+
+ public void updateAllowWhileIdleWhitelistDurationLocked() {
+ if (mLastAllowWhileIdleWhitelistDuration != ALLOW_WHILE_IDLE_WHITELIST_DURATION) {
+ mLastAllowWhileIdleWhitelistDuration = ALLOW_WHILE_IDLE_WHITELIST_DURATION;
+ BroadcastOptions opts = BroadcastOptions.makeBasic();
+ opts.setTemporaryAppWhitelistDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION);
+ mIdleOptions = opts.toBundle();
+ }
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ updateConstants();
+ }
+
+ private void updateConstants() {
+ synchronized (mLock) {
+ try {
+ mParser.setString(Settings.Global.getString(mResolver,
+ Settings.Global.ALARM_MANAGER_CONSTANTS));
+ } catch (IllegalArgumentException e) {
+ // Failed to parse the settings string, log this and move on
+ // with defaults.
+ Slog.e(TAG, "Bad device idle settings", e);
+ }
+
+ MIN_FUTURITY = mParser.getLong(KEY_MIN_FUTURITY, DEFAULT_MIN_FUTURITY);
+ MIN_INTERVAL = mParser.getLong(KEY_MIN_INTERVAL, DEFAULT_MIN_INTERVAL);
+ ALLOW_WHILE_IDLE_SHORT_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME,
+ DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME);
+ ALLOW_WHILE_IDLE_LONG_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME,
+ DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME);
+ ALLOW_WHILE_IDLE_WHITELIST_DURATION = mParser.getLong(
+ KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION,
+ DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
+
+ updateAllowWhileIdleMinTimeLocked();
+ updateAllowWhileIdleWhitelistDurationLocked();
+ }
+ }
+
+ void dump(PrintWriter pw) {
+ pw.println(" Settings:");
+
+ pw.print(" "); pw.print(KEY_MIN_FUTURITY); pw.print("=");
+ TimeUtils.formatDuration(MIN_FUTURITY, pw);
+ pw.println();
+
+ pw.print(" "); pw.print(KEY_MIN_INTERVAL); pw.print("=");
+ TimeUtils.formatDuration(MIN_INTERVAL, pw);
+ pw.println();
+
+ pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_SHORT_TIME); pw.print("=");
+ TimeUtils.formatDuration(ALLOW_WHILE_IDLE_SHORT_TIME, pw);
+ pw.println();
+
+ pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_LONG_TIME); pw.print("=");
+ TimeUtils.formatDuration(ALLOW_WHILE_IDLE_LONG_TIME, pw);
+ pw.println();
+
+ pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION); pw.print("=");
+ TimeUtils.formatDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION, pw);
+ pw.println();
+ }
+ }
+
+ final Constants mConstants;
+
// Alarm delivery ordering bookkeeping
static final int PRIO_TICK = 0;
static final int PRIO_WAKEUP = 1;
static final int PRIO_NORMAL = 2;
- class PriorityClass {
+ final class PriorityClass {
int seq;
int priority;
@@ -184,11 +301,10 @@
}
}
- final HashMap<String, PriorityClass> mPriorities =
- new HashMap<String, PriorityClass>();
+ final HashMap<String, PriorityClass> mPriorities = new HashMap<>();
int mCurrentSeq = 0;
- class WakeupEvent {
+ static final class WakeupEvent {
public long when;
public int uid;
public String action;
@@ -482,6 +598,7 @@
public AlarmManagerService(Context context) {
super(context);
+ mConstants = new Constants(mHandler);
}
static long convertToElapsed(long when, int type) {
@@ -595,7 +712,7 @@
}
// Make sure we are using the correct ALLOW_WHILE_IDLE min time.
- mAllowWhileIdleMinTime = ALLOW_WHILE_IDLE_SHORT_TIME;
+ mConstants.updateAllowWhileIdleMinTimeLocked();
// Reschedule everything.
rescheduleKernelAlarmsLocked();
@@ -714,6 +831,13 @@
}
@Override
+ public void onBootPhase(int phase) {
+ if (phase == PHASE_SYSTEM_SERVICES_READY) {
+ mConstants.start(getContext().getContentResolver());
+ }
+ }
+
+ @Override
protected void finalize() throws Throwable {
try {
close(mNativeData);
@@ -784,11 +908,12 @@
// Sanity check the recurrence interval. This will catch people who supply
// seconds when the API expects milliseconds.
- if (interval > 0 && interval < MIN_INTERVAL) {
+ final long minInterval = mConstants.MIN_INTERVAL;
+ if (interval > 0 && interval < minInterval) {
Slog.w(TAG, "Suspiciously short interval " + interval
- + " millis; expanding to " + (int)(MIN_INTERVAL/1000)
+ + " millis; expanding to " + (minInterval/1000)
+ " seconds");
- interval = MIN_INTERVAL;
+ interval = minInterval;
}
if (type < RTC_WAKEUP || type > ELAPSED_REALTIME) {
@@ -805,7 +930,7 @@
final long nowElapsed = SystemClock.elapsedRealtime();
final long nominalTrigger = convertToElapsed(triggerAtTime, type);
// Try to prevent spamming by making sure we aren't firing alarms in the immediate future
- final long minTrigger = nowElapsed + MIN_FUTURITY;
+ final long minTrigger = nowElapsed + mConstants.MIN_FUTURITY;
final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;
final long maxElapsed;
@@ -904,7 +1029,7 @@
if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
mPendingIdleUntil = a;
- mAllowWhileIdleMinTime = ALLOW_WHILE_IDLE_LONG_TIME;
+ mConstants.updateAllowWhileIdleMinTimeLocked();
needRebatch = true;
} else if ((a.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
if (mNextWakeFromIdle == null || mNextWakeFromIdle.whenElapsed > a.whenElapsed) {
@@ -1054,45 +1179,48 @@
void dumpImpl(PrintWriter pw) {
synchronized (mLock) {
pw.println("Current Alarm Manager state:");
+ mConstants.dump(pw);
+ pw.println();
+
final long nowRTC = System.currentTimeMillis();
final long nowELAPSED = SystemClock.elapsedRealtime();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- pw.print("nowRTC="); pw.print(nowRTC);
+ pw.print(" nowRTC="); pw.print(nowRTC);
pw.print("="); pw.print(sdf.format(new Date(nowRTC)));
pw.print(" nowELAPSED="); TimeUtils.formatDuration(nowELAPSED, pw);
pw.println();
- pw.print("mLastTimeChangeClockTime="); pw.print(mLastTimeChangeClockTime);
+ pw.print(" mLastTimeChangeClockTime="); pw.print(mLastTimeChangeClockTime);
pw.print("="); pw.println(sdf.format(new Date(mLastTimeChangeClockTime)));
- pw.print("mLastTimeChangeRealtime=");
+ pw.print(" mLastTimeChangeRealtime=");
TimeUtils.formatDuration(mLastTimeChangeRealtime, pw);
pw.println();
if (!mInteractive) {
- pw.print("Time since non-interactive: ");
+ pw.print(" Time since non-interactive: ");
TimeUtils.formatDuration(nowELAPSED - mNonInteractiveStartTime, pw);
pw.println();
- pw.print("Max wakeup delay: ");
+ pw.print(" Max wakeup delay: ");
TimeUtils.formatDuration(currentNonWakeupFuzzLocked(nowELAPSED), pw);
pw.println();
- pw.print("Time since last dispatch: ");
+ pw.print(" Time since last dispatch: ");
TimeUtils.formatDuration(nowELAPSED - mLastAlarmDeliveryTime, pw);
pw.println();
- pw.print("Next non-wakeup delivery time: ");
+ pw.print(" Next non-wakeup delivery time: ");
TimeUtils.formatDuration(nowELAPSED - mNextNonWakeupDeliveryTime, pw);
pw.println();
}
long nextWakeupRTC = mNextWakeup + (nowRTC - nowELAPSED);
long nextNonWakeupRTC = mNextNonWakeup + (nowRTC - nowELAPSED);
- pw.print("Next non-wakeup alarm: ");
+ pw.print(" Next non-wakeup alarm: ");
TimeUtils.formatDuration(mNextNonWakeup, nowELAPSED, pw);
pw.print(" = "); pw.println(sdf.format(new Date(nextNonWakeupRTC)));
- pw.print("Next wakeup: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
+ pw.print(" Next wakeup: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
pw.print(" = "); pw.println(sdf.format(new Date(nextWakeupRTC)));
- pw.print("Num time change events: "); pw.println(mNumTimeChanged);
+ pw.print(" Num time change events: "); pw.println(mNumTimeChanged);
pw.println();
- pw.println("Next alarm clock information: ");
+ pw.println(" Next alarm clock information: ");
final TreeSet<Integer> users = new TreeSet<>();
for (int i = 0; i < mNextAlarmClockForUser.size(); i++) {
users.add(mNextAlarmClockForUser.keyAt(i));
@@ -1104,7 +1232,7 @@
final AlarmManager.AlarmClockInfo next = mNextAlarmClockForUser.get(user);
final long time = next != null ? next.getTriggerTime() : 0;
final boolean pendingSend = mPendingSendNextAlarmClockChangedForUser.get(user);
- pw.print(" user:"); pw.print(user);
+ pw.print(" user:"); pw.print(user);
pw.print(" pendingSend:"); pw.print(pendingSend);
pw.print(" time:"); pw.print(time);
if (time > 0) {
@@ -1115,25 +1243,25 @@
}
if (mAlarmBatches.size() > 0) {
pw.println();
- pw.print("Pending alarm batches: ");
+ pw.print(" Pending alarm batches: ");
pw.println(mAlarmBatches.size());
for (Batch b : mAlarmBatches) {
pw.print(b); pw.println(':');
- dumpAlarmList(pw, b.alarms, " ", nowELAPSED, nowRTC, sdf);
+ dumpAlarmList(pw, b.alarms, " ", nowELAPSED, nowRTC, sdf);
}
}
if (mPendingIdleUntil != null || mPendingWhileIdleAlarms.size() > 0) {
pw.println();
- pw.println("Idle mode state:");
- pw.print(" Idling until: ");
+ pw.println(" Idle mode state:");
+ pw.print(" Idling until: ");
if (mPendingIdleUntil != null) {
pw.println(mPendingIdleUntil);
mPendingIdleUntil.dump(pw, " ", nowRTC, nowELAPSED, sdf);
} else {
pw.println("null");
}
- pw.println(" Pending alarms:");
- dumpAlarmList(pw, mPendingWhileIdleAlarms, " ", nowELAPSED, nowRTC, sdf);
+ pw.println(" Pending alarms:");
+ dumpAlarmList(pw, mPendingWhileIdleAlarms, " ", nowELAPSED, nowRTC, sdf);
}
if (mNextWakeFromIdle != null) {
pw.println();
@@ -1142,17 +1270,17 @@
}
pw.println();
- pw.print("Past-due non-wakeup alarms: ");
+ pw.print(" Past-due non-wakeup alarms: ");
if (mPendingNonWakeupAlarms.size() > 0) {
pw.println(mPendingNonWakeupAlarms.size());
- dumpAlarmList(pw, mPendingNonWakeupAlarms, " ", nowELAPSED, nowRTC, sdf);
+ dumpAlarmList(pw, mPendingNonWakeupAlarms, " ", nowELAPSED, nowRTC, sdf);
} else {
pw.println("(none)");
}
- pw.print(" Number of delayed alarms: "); pw.print(mNumDelayedAlarms);
+ pw.print(" Number of delayed alarms: "); pw.print(mNumDelayedAlarms);
pw.print(", total delay time: "); TimeUtils.formatDuration(mTotalDelayTime, pw);
pw.println();
- pw.print(" Max delay time: "); TimeUtils.formatDuration(mMaxDelayTime, pw);
+ pw.print(" Max delay time: "); TimeUtils.formatDuration(mMaxDelayTime, pw);
pw.print(", max non-interactive time: ");
TimeUtils.formatDuration(mNonInteractiveTime, pw);
pw.println();
@@ -1161,11 +1289,11 @@
pw.print(" Broadcast ref count: "); pw.println(mBroadcastRefCount);
pw.println();
- pw.print("mAllowWhileIdleMinTime=");
+ pw.print(" mAllowWhileIdleMinTime=");
TimeUtils.formatDuration(mAllowWhileIdleMinTime, pw);
pw.println();
if (mLastAllowWhileIdleDispatch.size() > 0) {
- pw.println("Last allow while idle dispatch times:");
+ pw.println(" Last allow while idle dispatch times:");
for (int i=0; i<mLastAllowWhileIdleDispatch.size(); i++) {
pw.print(" UID ");
UserHandle.formatUid(pw, mLastAllowWhileIdleDispatch.keyAt(i));
@@ -1969,6 +2097,7 @@
mLastAlarmDeliveryTime = nowELAPSED;
for (int i=0; i<triggerList.size(); i++) {
Alarm alarm = triggerList.get(i);
+ final boolean allowWhileIdle = (alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0;
try {
if (localLOGV) {
Slog.v(TAG, "sending alarm " + alarm);
@@ -1987,7 +2116,7 @@
alarm.operation.send(getContext(), 0,
mBackgroundIntent.putExtra(
Intent.EXTRA_ALARM_COUNT, alarm.count),
- mResultReceiver, mHandler);
+ mResultReceiver, mHandler, null, allowWhileIdle ? mIdleOptions : null);
// we have an active broadcast so stay awake.
if (mBroadcastRefCount == 0) {
@@ -2000,7 +2129,7 @@
mInFlight.add(inflight);
mBroadcastRefCount++;
- if ((alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
+ if (allowWhileIdle) {
// Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
mLastAllowWhileIdleDispatch.put(alarm.uid, nowELAPSED);
}
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index fbb6dc9..f9f6714 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -237,6 +237,12 @@
sendEnableMsg(mQuietEnableExternal);
}
}
+
+ if (!isNameAndAddressSet()) {
+ // Sync the Bluetooth name and address from the Bluetooth Adapter
+ if (DBG) Log.d(TAG,"Retrieving Bluetooth Adapter name and address...");
+ getNameAndAddress();
+ }
}
}
};
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 82399da..98f0b45 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -136,11 +136,13 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Inet4Address;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -3920,10 +3922,52 @@
}
return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty();
}
+
+ // TODO: investigate moving this into LinkProperties, if only to make more accurate
+ // the isProvisioned() checks.
+ private static Collection<InetAddress> getLikelyReachableDnsServers(LinkProperties lp) {
+ final ArrayList<InetAddress> dnsServers = new ArrayList<InetAddress>();
+ final List<RouteInfo> allRoutes = lp.getAllRoutes();
+ for (InetAddress nameserver : lp.getDnsServers()) {
+ // If the LinkProperties doesn't include a route to the nameserver, ignore it.
+ final RouteInfo bestRoute = RouteInfo.selectBestRoute(allRoutes, nameserver);
+ if (bestRoute == null) {
+ continue;
+ }
+
+ // TODO: better source address evaluation for destination addresses.
+ if (nameserver instanceof Inet4Address) {
+ if (!lp.hasIPv4Address()) {
+ continue;
+ }
+ } else if (nameserver instanceof Inet6Address) {
+ if (nameserver.isLinkLocalAddress()) {
+ if (((Inet6Address)nameserver).getScopeId() == 0) {
+ // For now, just make sure link-local DNS servers have
+ // scopedIds set, since DNS lookups will fail otherwise.
+ // TODO: verify the scopeId matches that of lp's interface.
+ continue;
+ }
+ } else {
+ if (bestRoute.isIPv6Default() && !lp.hasGlobalIPv6Address()) {
+ // TODO: reconsider all corner cases (disconnected ULA networks, ...).
+ continue;
+ }
+ }
+ }
+
+ dnsServers.add(nameserver);
+ }
+ return Collections.unmodifiableList(dnsServers);
+ }
+
private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId,
boolean flush, boolean useDefaultDns) {
+ // TODO: consider comparing the getLikelyReachableDnsServers() lists, in case the
+ // route to a DNS server has been removed (only really applicable in special cases
+ // where there is no default route).
if (oldLp == null || (newLp.isIdenticalDnses(oldLp) == false)) {
- Collection<InetAddress> dnses = newLp.getDnsServers();
+ Collection<InetAddress> dnses = getLikelyReachableDnsServers(newLp);
if (dnses.size() == 0 && mDefaultDns != null && useDefaultDns) {
dnses = new ArrayList();
dnses.add(mDefaultDns);
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 6eba3f6..82b334a 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -19,7 +19,6 @@
import android.Manifest;
import android.app.ActivityManagerNative;
import android.app.AlarmManager;
-import android.app.AppGlobals;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
@@ -27,7 +26,6 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.ContentObserver;
@@ -47,6 +45,7 @@
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -101,10 +100,6 @@
private static final String ACTION_ENTER_INACTIVE_STATE =
"com.android.server.device_idle.ENTER_INACTIVE_STATE";
- // TODO: These need to be moved to system settings.
-
-
-
private AlarmManager mAlarmManager;
private IBatteryStats mBatteryStats;
private PowerManagerInternal mLocalPowerManager;
@@ -180,7 +175,7 @@
* List of end times for UIDs that are temporarily marked as being allowed to access
* the network and acquire wakelocks. Times are in milliseconds.
*/
- private SparseLongArray mTempWhitelistAppIdEndTimes = new SparseLongArray();
+ private final SparseLongArray mTempWhitelistAppIdEndTimes = new SparseLongArray();
/**
* Current app IDs of temporarily whitelist apps for high-priority messages.
@@ -234,7 +229,7 @@
* global Settings. Any access to this class or its fields should be done while
* holding the DeviceIdleController lock.
*/
- private class Constants extends ContentObserver {
+ private final class Constants extends ContentObserver {
// Key names stored in the settings value.
private static final String KEY_INACTIVE_TIMEOUT = "inactive_to";
private static final String KEY_SENSING_TIMEOUT = "sensing_to";
@@ -403,49 +398,49 @@
void dump(PrintWriter pw) {
pw.println(" Settings:");
- pw.print(" DOZE_INACTIVE_TIMEOUT=");
+ pw.print(" "); pw.print(KEY_INACTIVE_TIMEOUT); pw.print("=");
TimeUtils.formatDuration(INACTIVE_TIMEOUT, pw);
pw.println();
- pw.print(" DOZE_SENSING_TIMEOUT=");
+ pw.print(" "); pw.print(KEY_SENSING_TIMEOUT); pw.print("=");
TimeUtils.formatDuration(SENSING_TIMEOUT, pw);
pw.println();
- pw.print(" DOZE_MOTION_INACTIVE_TIMEOUT=");
+ pw.print(" "); pw.print(KEY_MOTION_INACTIVE_TIMEOUT); pw.print("=");
TimeUtils.formatDuration(MOTION_INACTIVE_TIMEOUT, pw);
pw.println();
- pw.print(" DOZE_IDLE_AFTER_INACTIVE_TIMEOUT=");
+ pw.print(" "); pw.print(KEY_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
TimeUtils.formatDuration(IDLE_AFTER_INACTIVE_TIMEOUT, pw);
pw.println();
- pw.print(" DOZE_IDLE_PENDING_TIMEOUT=");
+ pw.print(" "); pw.print(KEY_IDLE_PENDING_TIMEOUT); pw.print("=");
TimeUtils.formatDuration(IDLE_PENDING_TIMEOUT, pw);
pw.println();
- pw.print(" DOZE_MAX_IDLE_PENDING_TIMEOUT=");
+ pw.print(" "); pw.print(KEY_MAX_IDLE_PENDING_TIMEOUT); pw.print("=");
TimeUtils.formatDuration(MAX_IDLE_PENDING_TIMEOUT, pw);
pw.println();
- pw.print(" DOZE_IDLE_PENDING_FACTOR=");
+ pw.print(" "); pw.print(KEY_IDLE_PENDING_FACTOR); pw.print("=");
pw.println(IDLE_PENDING_FACTOR);
- pw.print(" DOZE_IDLE_TIMEOUT=");
+ pw.print(" "); pw.print(KEY_IDLE_TIMEOUT); pw.print("=");
TimeUtils.formatDuration(IDLE_TIMEOUT, pw);
pw.println();
- pw.print(" DOZE_MAX_IDLE_TIMEOUT=");
+ pw.print(" "); pw.print(KEY_MAX_IDLE_TIMEOUT); pw.print("=");
TimeUtils.formatDuration(MAX_IDLE_TIMEOUT, pw);
pw.println();
- pw.print(" DOZE_IDLE_FACTOR=");
+ pw.print(" "); pw.print(KEY_IDLE_FACTOR); pw.print("=");
pw.println(IDLE_FACTOR);
- pw.print(" DOZE_MIN_TIME_TO_ALARM=");
+ pw.print(" "); pw.print(KEY_MIN_TIME_TO_ALARM); pw.print("=");
TimeUtils.formatDuration(MIN_TIME_TO_ALARM, pw);
pw.println();
- pw.print(" DOZE_MAX_TEMP_APP_WHITELIST_DURATION=");
+ pw.print(" "); pw.print(KEY_MAX_TEMP_APP_WHITELIST_DURATION); pw.print("=");
TimeUtils.formatDuration(MAX_TEMP_APP_WHITELIST_DURATION, pw);
pw.println();
}
@@ -465,6 +460,7 @@
} else if (result == AnyMotionDetector.RESULT_MOVED) {
if (DEBUG) Slog.d(TAG, "RESULT_MOVED received.");
synchronized (this) {
+ EventLogTags.writeDeviceIdle(mState, "sense_moved");
enterInactiveStateLocked();
}
}
@@ -492,7 +488,7 @@
mLocalPowerManager.setDeviceIdleMode(true);
try {
mNetworkPolicyManager.setDeviceIdleMode(true);
- mBatteryStats.noteDeviceIdleMode(true, false, false);
+ mBatteryStats.noteDeviceIdleMode(true, null, Process.myUid());
} catch (RemoteException e) {
}
getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
@@ -501,18 +497,19 @@
mLocalPowerManager.setDeviceIdleMode(false);
try {
mNetworkPolicyManager.setDeviceIdleMode(false);
- mBatteryStats.noteDeviceIdleMode(false, false, false);
+ mBatteryStats.noteDeviceIdleMode(false, null, Process.myUid());
} catch (RemoteException e) {
}
getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
} break;
case MSG_REPORT_ACTIVE: {
- boolean fromMotion = msg.arg1 != 0;
+ String activeReason = (String)msg.obj;
+ int activeUid = msg.arg1;
boolean needBroadcast = msg.arg2 != 0;
mLocalPowerManager.setDeviceIdleMode(false);
try {
mNetworkPolicyManager.setDeviceIdleMode(false);
- mBatteryStats.noteDeviceIdleMode(false, !fromMotion, fromMotion);
+ mBatteryStats.noteDeviceIdleMode(false, activeReason, activeUid);
} catch (RemoteException e) {
}
if (needBroadcast) {
@@ -573,25 +570,33 @@
userId,
/*allowAll=*/ false,
/*requireFull=*/ false,
- "addAppBrieflyToWhitelist", null);
+ "addPowerSaveTempWhitelistApp", null);
final long token = Binder.clearCallingIdentity();
try {
- PackageInfo pi = AppGlobals.getPackageManager()
- .getPackageInfo(packageName, 0, userId);
- if (pi == null) return;
DeviceIdleController.this.addPowerSaveTempWhitelistAppInternal(packageName,
duration, userId);
- } catch (RemoteException re) {
} finally {
Binder.restoreCallingIdentity(token);
}
}
+ @Override public void exitIdle(String reason) {
+ getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
+ null);
+ exitIdleInternal(reason);
+ }
+
@Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
DeviceIdleController.this.dump(fd, pw, args);
}
}
+ public final class LocalService {
+ public void addPowerSaveTempWhitelistAppDirect(int appId, long duration) {
+ DeviceIdleController.this.addPowerSaveTempWhitelistAppDirectInternal(appId, duration);
+ }
+ }
+
public DeviceIdleController(Context context) {
super(context);
mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
@@ -635,6 +640,7 @@
}
publishBinderService(Context.DEVICE_IDLE_CONTROLLER, new BinderService());
+ publishLocalService(LocalService.class, new LocalService());
}
@Override
@@ -765,33 +771,41 @@
try {
int uid = getContext().getPackageManager().getPackageUid(packageName, userId);
int appId = UserHandle.getAppId(uid);
- final long timeNow = System.currentTimeMillis();
- synchronized (this) {
- duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION);
- long currentEndTime = mTempWhitelistAppIdEndTimes.get(appId);
- // Set the new end time
- mTempWhitelistAppIdEndTimes.put(appId, timeNow + duration);
- if (DEBUG) {
- Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist");
- }
- if (currentEndTime == 0) {
- // No pending timeout for the app id, post a delayed message
- postTempActiveTimeoutMessage(appId, duration);
- updateTempWhitelistAppIdsLocked();
- reportTempWhitelistChangedLocked();
- }
- }
+ addPowerSaveTempWhitelistAppDirectInternal(appId, duration);
} catch (NameNotFoundException e) {
}
}
+ /**
+ * Adds an app to the temporary whitelist and resets the endTime for granting the
+ * app an exemption to access network and acquire wakelocks.
+ */
+ public void addPowerSaveTempWhitelistAppDirectInternal(int appId, long duration) {
+ final long timeNow = SystemClock.elapsedRealtime();
+ synchronized (this) {
+ duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION);
+ long currentEndTime = mTempWhitelistAppIdEndTimes.get(appId);
+ // Set the new end time
+ mTempWhitelistAppIdEndTimes.put(appId, timeNow + duration);
+ if (DEBUG) {
+ Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist");
+ }
+ if (currentEndTime == 0) {
+ // No pending timeout for the app id, post a delayed message
+ postTempActiveTimeoutMessage(appId, duration);
+ updateTempWhitelistAppIdsLocked();
+ reportTempWhitelistChangedLocked();
+ }
+ }
+ }
+
private void postTempActiveTimeoutMessage(int uid, long delay) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TEMP_APP_WHITELIST_TIMEOUT, uid, 0),
delay);
}
void checkTempAppWhitelistTimeout(int uid) {
- final long timeNow = System.currentTimeMillis();
+ final long timeNow = SystemClock.elapsedRealtime();
synchronized (this) {
long endTime = mTempWhitelistAppIdEndTimes.get(uid);
if (endTime == 0) {
@@ -812,6 +826,12 @@
}
}
+ public void exitIdleInternal(String reason) {
+ synchronized (this) {
+ becomeActiveLocked(reason, Binder.getCallingUid());
+ }
+ }
+
void updateDisplayLocked() {
mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
// We consider any situation where the display is showing something to be it on,
@@ -824,7 +844,7 @@
becomeInactiveIfAppropriateLocked();
} else if (screenOn) {
mScreenOn = true;
- becomeActiveLocked("screen");
+ becomeActiveLocked("screen", Process.myUid());
}
}
@@ -835,21 +855,21 @@
becomeInactiveIfAppropriateLocked();
} else if (charging) {
mCharging = charging;
- becomeActiveLocked("charging");
+ becomeActiveLocked("charging", Process.myUid());
}
}
- void scheduleReportActiveLocked(boolean fromMotion) {
- Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, fromMotion ? 1 : 0,
- mState == STATE_IDLE ? 1 : 0);
+ void scheduleReportActiveLocked(String activeReason, int activeUid) {
+ Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid,
+ mState == STATE_IDLE ? 1 : 0, activeReason);
mHandler.sendMessage(msg);
}
- void becomeActiveLocked(String reason) {
- if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + reason);
+ void becomeActiveLocked(String activeReason, int activeUid) {
+ if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + activeReason);
if (mState != STATE_ACTIVE) {
- EventLogTags.writeDeviceIdle(STATE_ACTIVE, reason);
- scheduleReportActiveLocked(false);
+ EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason);
+ scheduleReportActiveLocked(activeReason, activeUid);
mState = STATE_ACTIVE;
mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
mNextIdlePendingDelay = 0;
@@ -890,7 +910,7 @@
if ((now+mConstants.MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) {
// Whoops, there is an upcoming alarm. We don't actually want to go idle.
if (mState != STATE_ACTIVE) {
- becomeActiveLocked("alarm");
+ becomeActiveLocked("alarm", Process.myUid());
}
return;
}
@@ -948,7 +968,7 @@
// state to wait again for no motion. Note that we only monitor for significant
// motion after moving out of the inactive state, so no need to worry about that.
if (mState != STATE_ACTIVE) {
- scheduleReportActiveLocked(true);
+ scheduleReportActiveLocked("motion", Process.myUid());
mState = STATE_ACTIVE;
mInactiveTimeout = mConstants.MOTION_INACTIVE_TIMEOUT;
EventLogTags.writeDeviceIdle(mState, "motion");
@@ -1234,7 +1254,7 @@
synchronized (this) {
if (!mIdleDisabled) {
mIdleDisabled = true;
- becomeActiveLocked("disabled");
+ becomeActiveLocked("disabled", Process.myUid());
pw.println("Idle mode disabled");
}
}
@@ -1295,6 +1315,8 @@
}
synchronized (this) {
+ mConstants.dump(pw);
+
int size = mPowerSaveWhitelistApps.size();
if (size > 0) {
pw.println(" Whitelist system apps:");
@@ -1313,17 +1335,34 @@
}
size = mPowerSaveWhitelistAppIds.size();
if (size > 0) {
- pw.println(" Whitelist app uids:");
+ pw.println(" Whitelist app ids:");
for (int i = 0; i < size; i++) {
- pw.print(" UID=");
+ pw.print(" ");
pw.print(mPowerSaveWhitelistAppIds.keyAt(i));
- pw.print(": ");
- pw.print(mPowerSaveWhitelistAppIds.valueAt(i));
pw.println();
}
}
-
- mConstants.dump(pw);
+ size = mTempWhitelistAppIdEndTimes.size();
+ if (size > 0) {
+ pw.println(" Temp whitelist schedule:");
+ final long timeNow = SystemClock.elapsedRealtime();
+ for (int i = 0; i < size; i++) {
+ pw.print(" UID=");
+ pw.print(mTempWhitelistAppIdEndTimes.keyAt(i));
+ pw.print(": ");
+ TimeUtils.formatDuration(mTempWhitelistAppIdEndTimes.valueAt(i), timeNow, pw);
+ pw.println();
+ }
+ }
+ size = mTempWhitelistAppIdArray != null ? mTempWhitelistAppIdArray.length : 0;
+ if (size > 0) {
+ pw.println(" Temp whitelist app ids:");
+ for (int i = 0; i < size; i++) {
+ pw.print(" ");
+ pw.print(mTempWhitelistAppIdArray[i]);
+ pw.println();
+ }
+ }
pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor);
pw.print(" mCurDisplay="); pw.println(mCurDisplay);
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index a5d536e..2f153a0 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -2112,8 +2112,23 @@
if (DEBUG) Slog.v(TAG, "Not hiding: forced show not cancelled by not-always hide");
return false;
}
+
+ // There is a chance that IMM#hideSoftInput() is called in a transient state where
+ // IMMS#InputShown is already updated to be true whereas IMMS#mImeWindowVis is still waiting
+ // to be updated with the new value sent from IME process. Even in such a transient state
+ // historically we have accepted an incoming call of IMM#hideSoftInput() from the
+ // application process as a valid request, and have even promised such a behavior with CTS
+ // since Android Eclair. That's why we need to accept IMM#hideSoftInput() even when only
+ // IMMS#InputShown indicates that the software keyboard is shown.
+ // TODO: Clean up, IMMS#mInputShown, IMMS#mImeWindowVis and mShowRequested.
+ final boolean shouldHideSoftInput = (mCurMethod != null) && (mInputShown ||
+ (mImeWindowVis & InputMethodService.IME_ACTIVE) != 0);
boolean res;
- if ((mImeWindowVis & InputMethodService.IME_ACTIVE) != 0 && mCurMethod != null) {
+ if (shouldHideSoftInput) {
+ // The IME will report its visible state again after the following message finally
+ // delivered to the IME process as an IPC. Hence the inconsistency between
+ // IMMS#mInputShown and IMMS#mImeWindowVis should be resolved spontaneously in
+ // the final state.
executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
MSG_HIDE_SOFT_INPUT, mCurMethod, resultReceiver));
res = true;
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index c76fc1c..743aafb 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -1958,6 +1958,27 @@
return p.getProperties();
}
+ /**
+ * @return null if the provider does not exist
+ * @throws SecurityException if the provider is not allowed to be
+ * accessed by the caller
+ */
+ @Override
+ public String getNetworkProviderPackage() {
+ LocationProviderInterface p;
+ synchronized (mLock) {
+ if (mProvidersByName.get(LocationManager.NETWORK_PROVIDER) == null) {
+ return null;
+ }
+ p = mProvidersByName.get(LocationManager.NETWORK_PROVIDER);
+ }
+
+ if (p instanceof LocationProviderProxy) {
+ return ((LocationProviderProxy) p).getConnectedPackageName();
+ }
+ return null;
+ }
+
@Override
public boolean isProviderEnabled(String provider) {
// Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index a1e2a54..baa55e7 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -19,6 +19,15 @@
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.Manifest.permission.DUMP;
import static android.Manifest.permission.SHUTDOWN;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_NONE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NONE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
+import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
+import static android.net.NetworkPolicyManager.FIREWALL_TYPE_BLACKLIST;
+import static android.net.NetworkPolicyManager.FIREWALL_TYPE_WHITELIST;
import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.TAG_ALL;
import static android.net.NetworkStats.TAG_NONE;
@@ -35,6 +44,7 @@
import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
+import android.annotation.NonNull;
import android.app.ActivityManagerNative;
import android.content.Context;
import android.net.ConnectivityManager;
@@ -192,6 +202,21 @@
/** Set of UIDs that are to be blocked/allowed by firewall controller. */
@GuardedBy("mQuotaLock")
private SparseIntArray mUidFirewallRules = new SparseIntArray();
+ /**
+ * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
+ * to application idles.
+ */
+ @GuardedBy("mQuotaLock")
+ private SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
+ /**
+ * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
+ * to device idles.
+ */
+ @GuardedBy("mQuotaLock")
+ private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
+
+ private boolean mStandbyChainEnabled = false;
+ private boolean mDozableChainEnabled = false;
private Object mIdleTimerLock = new Object();
/** Set of interfaces with active idle timers. */
@@ -282,6 +307,9 @@
}
public void systemReady() {
+ // init firewall states
+ mDozableChainEnabled = false;
+ mStandbyChainEnabled = true;
prepareNativeDaemon();
if (DBG) Slog.d(TAG, "Prepared");
}
@@ -568,9 +596,38 @@
final SparseIntArray uidFirewallRules = mUidFirewallRules;
mUidFirewallRules = new SparseIntArray();
for (int i = 0; i < uidFirewallRules.size(); i++) {
- setFirewallUidRule(uidFirewallRules.keyAt(i), uidFirewallRules.valueAt(i));
+ setFirewallUidRuleInternal(FIREWALL_CHAIN_NONE, uidFirewallRules.keyAt(i),
+ uidFirewallRules.valueAt(i));
}
}
+
+ size = mUidFirewallStandbyRules.size();
+ if (size > 0) {
+ Slog.d(TAG, "Pushing " + size + " active firewall standby UID rules");
+ final SparseIntArray uidFirewallRules = mUidFirewallStandbyRules;
+ mUidFirewallStandbyRules = new SparseIntArray();
+ for (int i = 0; i < uidFirewallRules.size(); i++) {
+ setFirewallUidRuleInternal(FIREWALL_CHAIN_STANDBY, uidFirewallRules.keyAt(i),
+ uidFirewallRules.valueAt(i));
+ }
+ }
+ if (mStandbyChainEnabled) {
+ setFirewallChainEnabled(FIREWALL_CHAIN_STANDBY, true);
+ }
+
+ size = mUidFirewallDozableRules.size();
+ if (size > 0) {
+ Slog.d(TAG, "Pushing " + size + " active firewall dozable UID rules");
+ final SparseIntArray uidFirewallRules = mUidFirewallDozableRules;
+ mUidFirewallDozableRules = new SparseIntArray();
+ for (int i = 0; i < uidFirewallRules.size(); i++) {
+ setFirewallUidRuleInternal(FIREWALL_CHAIN_DOZABLE, uidFirewallRules.keyAt(i),
+ uidFirewallRules.valueAt(i));
+ }
+ }
+ if (mDozableChainEnabled) {
+ setFirewallChainEnabled(FIREWALL_CHAIN_DOZABLE, true);
+ }
}
}
@@ -1954,13 +2011,78 @@
}
@Override
- public void setFirewallUidRule(int uid, int rule) {
+ public void setFirewallChainEnabled(int chain, boolean enable) {
enforceSystemUid();
- if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
- Preconditions.checkState(mFirewallEnabled);
+ final String operation = enable ? "enable_chain" : "disable_chain";
+ try {
+ String chainName;
+ switch(chain) {
+ case FIREWALL_CHAIN_STANDBY:
+ chainName = FIREWALL_CHAIN_NAME_STANDBY;
+ mStandbyChainEnabled = enable;
+ break;
+ case FIREWALL_CHAIN_DOZABLE:
+ chainName = FIREWALL_CHAIN_NAME_DOZABLE;
+ mDozableChainEnabled = enable;
+ break;
+ default:
+ throw new IllegalArgumentException("Bad child chain: " + chain);
+ }
+ mConnector.execute("firewall", operation, chainName);
+ } catch (NativeDaemonConnectorException e) {
+ throw e.rethrowAsParcelableException();
}
+ }
+
+ private int getFirewallType(int chain) {
+ switch (chain) {
+ case FIREWALL_CHAIN_STANDBY:
+ return FIREWALL_TYPE_BLACKLIST;
+ case FIREWALL_CHAIN_DOZABLE:
+ return FIREWALL_TYPE_WHITELIST;
+ default:
+ return isFirewallEnabled() ? FIREWALL_TYPE_WHITELIST : FIREWALL_TYPE_BLACKLIST;
+ }
+ }
+
+ @Override
+ public void setFirewallUidRules(int chain, int[] uids, int[] rules) {
+ enforceSystemUid();
+ SparseIntArray uidFirewallRules = getUidFirewallRules(chain);
+ SparseIntArray newRules = new SparseIntArray();
+ // apply new set of rules
+ for (int index = uids.length - 1; index >= 0; --index) {
+ int uid = uids[index];
+ int rule = rules[index];
+ setFirewallUidRule(chain, uid, rule);
+ newRules.put(uid, rule);
+ }
+ // collect the rules to remove.
+ SparseIntArray rulesToRemove = new SparseIntArray();
+ for (int index = uidFirewallRules.size() - 1; index >= 0; --index) {
+ int uid = uidFirewallRules.keyAt(index);
+ if (newRules.indexOfKey(uid) < 0) {
+ rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT);
+ }
+ }
+ // remove dead rules
+ for (int index = rulesToRemove.size() - 1; index >= 0; --index) {
+ int uid = rulesToRemove.keyAt(index);
+ setFirewallUidRuleInternal(chain, uid, FIREWALL_RULE_DEFAULT);
+ }
+ }
+
+ @Override
+ public void setFirewallUidRule(int chain, int uid, int rule) {
+ enforceSystemUid();
+ setFirewallUidRuleInternal(chain, uid, rule);
+ }
+
+ private void setFirewallUidRuleInternal(int chain, int uid, int rule) {
synchronized (mQuotaLock) {
- final int oldUidFirewallRule = mUidFirewallRules.get(uid);
+ SparseIntArray uidFirewallRules = getUidFirewallRules(chain);
+
+ final int oldUidFirewallRule = uidFirewallRules.get(uid, FIREWALL_RULE_DEFAULT);
if (DBG) {
Slog.d(TAG, "oldRule = " + oldUidFirewallRule
+ ", newRule=" + rule + " for uid=" + uid);
@@ -1973,7 +2095,7 @@
try {
String ruleName;
- if (isFirewallEnabled()) { // Whitelist mode
+ if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
ruleName = "allow";
} else {
@@ -1988,17 +2110,44 @@
}
if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
- mUidFirewallRules.delete(uid);
+ uidFirewallRules.delete(uid);
} else {
- mUidFirewallRules.put(uid, rule);
+ uidFirewallRules.put(uid, rule);
}
- mConnector.execute("firewall", "set_uid_rule", uid, ruleName);
+ mConnector.execute("firewall", "set_uid_rule", getFirewallChainName(chain), uid,
+ ruleName);
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
}
}
+ private @NonNull SparseIntArray getUidFirewallRules(int chain) {
+ switch (chain) {
+ case FIREWALL_CHAIN_STANDBY:
+ return mUidFirewallStandbyRules;
+ case FIREWALL_CHAIN_DOZABLE:
+ return mUidFirewallDozableRules;
+ case FIREWALL_CHAIN_NONE:
+ return mUidFirewallRules;
+ default:
+ throw new IllegalArgumentException("Unknown chain:" + chain);
+ }
+ }
+
+ public @NonNull String getFirewallChainName(int chain) {
+ switch (chain) {
+ case FIREWALL_CHAIN_STANDBY:
+ return FIREWALL_CHAIN_NAME_STANDBY;
+ case FIREWALL_CHAIN_DOZABLE:
+ return FIREWALL_CHAIN_NAME_DOZABLE;
+ case FIREWALL_CHAIN_NONE:
+ return FIREWALL_CHAIN_NAME_NONE;
+ default:
+ throw new IllegalArgumentException("Unknown chain:" + chain);
+ }
+ }
+
private static void enforceSystemUid() {
final int uid = Binder.getCallingUid();
if (uid != Process.SYSTEM_UID) {
@@ -2123,6 +2272,32 @@
pw.println("]");
}
+ pw.println("UID firewall standby chain enabled: " + mStandbyChainEnabled);
+ synchronized (mUidFirewallStandbyRules) {
+ pw.print("UID firewall standby rule: [");
+ final int size = mUidFirewallStandbyRules.size();
+ for (int i = 0; i < size; i++) {
+ pw.print(mUidFirewallStandbyRules.keyAt(i));
+ pw.print(":");
+ pw.print(mUidFirewallStandbyRules.valueAt(i));
+ if (i < size - 1) pw.print(",");
+ }
+ pw.println("]");
+ }
+
+ pw.println("UID firewall dozable chain enabled: " + mDozableChainEnabled);
+ synchronized (mUidFirewallDozableRules) {
+ pw.print("UID firewall dozable rule: [");
+ final int size = mUidFirewallDozableRules.size();
+ for (int i = 0; i < size; i++) {
+ pw.print(mUidFirewallDozableRules.keyAt(i));
+ pw.print(":");
+ pw.print(mUidFirewallDozableRules.valueAt(i));
+ if (i < size - 1) pw.print(",");
+ }
+ pw.println("]");
+ }
+
synchronized (mIdleTimerLock) {
pw.println("Idle timers:");
for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) {
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index 56f9942..94316fe 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -18,18 +18,14 @@
import android.Manifest;
import android.app.ActivityManager;
-import android.app.PendingIntent;
import android.content.Context;
-import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Binder;
-import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.service.persistentdata.IPersistentDataBlockService;
-import android.service.persistentdata.PersistentDataBlockManager;
import android.util.Slog;
import com.android.internal.R;
@@ -432,29 +428,6 @@
}
@Override
- public void wipeIfAllowed(Bundle bundle, PendingIntent pi) {
- // Should only be called by owner
- if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
- throw new SecurityException("Only the Owner is allowed to wipe");
- }
- // Caller must be able to query the the state of the PersistentDataBlock
- enforcePersistentDataBlockAccess();
- String allowedPackage = mContext.getResources()
- .getString(R.string.config_persistentDataPackageName);
- Intent intent = new Intent();
- intent.setPackage(allowedPackage);
- intent.setAction(PersistentDataBlockManager.ACTION_WIPE_IF_ALLOWED);
- intent.putExtras(bundle);
- intent.putExtra(PersistentDataBlockManager.EXTRA_WIPE_IF_ALLOWED_CALLBACK, pi);
- long id = Binder.clearCallingIdentity();
- try {
- mContext.sendBroadcastAsUser(intent, UserHandle.OWNER);
- } finally {
- restoreCallingIdentity(id);
- }
- }
-
- @Override
public void setOemUnlockEnabled(boolean enabled) {
// do not allow monkey to flip the flag
if (ActivityManager.isUserAMonkey()) {
diff --git a/services/core/java/com/android/server/SystemService.java b/services/core/java/com/android/server/SystemService.java
index 6e67970..e0a9ab4 100644
--- a/services/core/java/com/android/server/SystemService.java
+++ b/services/core/java/com/android/server/SystemService.java
@@ -34,7 +34,7 @@
* local interfaces that other services within the system server may use to access
* privileged internal functions.
* <li>Then {@link #onBootPhase(int)} is called as many times as there are boot phases
- * until {@link #PHASE_BOOT_COMPLETE} is sent, which is the last boot phase. Each phase
+ * until {@link #PHASE_BOOT_COMPLETED} is sent, which is the last boot phase. Each phase
* is an opportunity to do special work, like acquiring optional service dependencies,
* waiting to see if SafeMode is enabled, or registering with a service that gets
* started after this one.
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 667abb6..970deba 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -39,6 +39,7 @@
import android.Manifest;
import android.app.AppOpsManager;
import android.app.ApplicationThreadNative;
+import android.app.BroadcastOptions;
import android.app.IActivityContainer;
import android.app.IActivityContainerCallback;
import android.app.IAppTask;
@@ -89,6 +90,7 @@
import com.android.internal.util.Preconditions;
import com.android.server.AppOpsService;
import com.android.server.AttributeCache;
+import com.android.server.DeviceIdleController;
import com.android.server.IntentResolver;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
@@ -941,6 +943,11 @@
UsageStatsManagerInternal mUsageStatsService;
/**
+ * Access to DeviceIdleController service.
+ */
+ DeviceIdleController.LocalService mLocalDeviceIdleController;
+
+ /**
* Information about and control over application operations
*/
final AppOpsService mAppOpsService;
@@ -1438,7 +1445,7 @@
}
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
+ null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
if (mShowDialogs) {
Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
@@ -2481,10 +2488,7 @@
synchronized(bstats) {
synchronized(mPidsSelfLocked) {
if (haveNewCpuStats) {
- final int perc = bstats.startAddingCpuLocked();
- if (perc >= 0) {
- int remainUTime = 0;
- int remainSTime = 0;
+ if (bstats.startAddingCpuLocked()) {
int totalUTime = 0;
int totalSTime = 0;
final int N = mProcessCpuTracker.countStats();
@@ -2494,10 +2498,6 @@
continue;
}
ProcessRecord pr = mPidsSelfLocked.get(st.pid);
- int otherUTime = (st.rel_utime*perc)/100;
- int otherSTime = (st.rel_stime*perc)/100;
- remainUTime += otherUTime;
- remainSTime += otherSTime;
totalUTime += st.rel_utime;
totalSTime += st.rel_stime;
if (pr != null) {
@@ -2506,8 +2506,7 @@
pr.curProcBatteryStats = ps = bstats.getProcessStatsLocked(
pr.info.uid, pr.processName);
}
- ps.addCpuTimeLocked(st.rel_utime - otherUTime,
- st.rel_stime - otherSTime);
+ ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
pr.curCpuTime += st.rel_utime + st.rel_stime;
} else {
BatteryStatsImpl.Uid.Proc ps = st.batteryStats;
@@ -2515,8 +2514,7 @@
st.batteryStats = ps = bstats.getProcessStatsLocked(
bstats.mapUid(st.uid), st.name);
}
- ps.addCpuTimeLocked(st.rel_utime - otherUTime,
- st.rel_stime - otherSTime);
+ ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
}
}
final int userTime = mProcessCpuTracker.getLastUserTime();
@@ -2525,9 +2523,8 @@
final int irqTime = mProcessCpuTracker.getLastIrqTime();
final int softIrqTime = mProcessCpuTracker.getLastSoftIrqTime();
final int idleTime = mProcessCpuTracker.getLastIdleTime();
- bstats.finishAddingCpuLocked(perc, remainUTime,
- remainSTime, totalUTime, totalSTime, userTime, systemTime,
- iowaitTime, irqTime, softIrqTime, idleTime);
+ bstats.finishAddingCpuLocked(totalUTime, totalSTime, userTime,
+ systemTime, iowaitTime, irqTime, softIrqTime, idleTime);
}
}
}
@@ -2559,9 +2556,9 @@
@Override
public void batterySendBroadcast(Intent intent) {
- broadcastIntentLocked(null, null, intent, null,
- null, 0, null, null, null, AppOpsManager.OP_NONE, false, false, -1,
- Process.SYSTEM_UID, UserHandle.USER_ALL);
+ broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
+ AppOpsManager.OP_NONE, null, false, false,
+ -1, Process.SYSTEM_UID, UserHandle.USER_ALL);
}
/**
@@ -3582,6 +3579,8 @@
@Override
public int getPackageProcessState(String packageName) {
+ enforceCallingPermission(android.Manifest.permission.GET_PACKAGE_IMPORTANCE,
+ "getPackageProcessState");
int procState = ActivityManager.PROCESS_STATE_NONEXISTENT;
synchronized (this) {
for (int i=mLruProcesses.size()-1; i>=0; i--) {
@@ -5089,7 +5088,7 @@
Uri.fromParts("package", packageName, null));
intent.putExtra(Intent.EXTRA_UID, pkgUid);
broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
- null, null, 0, null, null, null, false, false, userId);
+ null, null, 0, null, null, null, null, false, false, userId);
} catch (RemoteException e) {
}
} finally {
@@ -5322,9 +5321,9 @@
mStackSupervisor.closeSystemDialogsLocked();
- broadcastIntentLocked(null, null, intent, null,
- null, 0, null, null, null, AppOpsManager.OP_NONE, false, false, -1,
- Process.SYSTEM_UID, UserHandle.USER_ALL);
+ broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
+ AppOpsManager.OP_NONE, null, false, false,
+ -1, Process.SYSTEM_UID, UserHandle.USER_ALL);
}
@Override
@@ -5423,8 +5422,7 @@
intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(uid));
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- false, false,
- MY_PID, Process.SYSTEM_UID, UserHandle.getUserId(uid));
+ null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.getUserId(uid));
}
private void forceStopUserLocked(int userId, String reason) {
@@ -5435,8 +5433,7 @@
intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- false, false,
- MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+ null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
}
private final boolean killPackageProcessesLocked(String packageName, int appId,
@@ -6329,8 +6326,8 @@
},
0, null, null,
android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
- AppOpsManager.OP_NONE, true, false, MY_PID, Process.SYSTEM_UID,
- userId);
+ AppOpsManager.OP_NONE, null, true, false,
+ MY_PID, Process.SYSTEM_UID, userId);
}
}
scheduleStartProfilesLocked();
@@ -11442,8 +11439,7 @@
EventLogTags.writeAmPreBoot(users[curUser], intent.getComponent().getPackageName());
broadcastIntentLocked(null, null, intent, null, this,
0, null, null, null, AppOpsManager.OP_NONE,
- true, false, MY_PID, Process.SYSTEM_UID,
- users[curUser]);
+ null, true, false, MY_PID, Process.SYSTEM_UID, users[curUser]);
}
public void performReceive(Intent intent, int resultCode,
@@ -11535,6 +11531,9 @@
return;
}
+ mLocalDeviceIdleController
+ = LocalServices.getService(DeviceIdleController.LocalService.class);
+
// Make sure we have the current profile info, since it is needed for
// security checks.
updateCurrentProfileIdsLocked();
@@ -11704,7 +11703,7 @@
intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- false, false, MY_PID, Process.SYSTEM_UID, mCurrentUserId);
+ null, false, false, MY_PID, Process.SYSTEM_UID, mCurrentUserId);
intent = new Intent(Intent.ACTION_USER_STARTING);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
@@ -11717,7 +11716,7 @@
}
}, 0, null, null,
INTERACT_ACROSS_USERS, AppOpsManager.OP_NONE,
- true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+ null, true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
} catch (Throwable t) {
Slog.wtf(TAG, "Failed sending first user broadcasts", t);
} finally {
@@ -16101,8 +16100,8 @@
Intent intent = allSticky.get(i);
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, null,
- null, -1, -1, null, null, AppOpsManager.OP_NONE, receivers, null, 0,
- null, null, false, true, true, -1);
+ null, -1, -1, null, null, AppOpsManager.OP_NONE, null, receivers,
+ null, 0, null, null, false, true, true, -1);
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
@@ -16255,9 +16254,8 @@
private final int broadcastIntentLocked(ProcessRecord callerApp,
String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
- Bundle map, String requiredPermission, int appOp,
- boolean ordered, boolean sticky, int callingPid, int callingUid,
- int userId) {
+ Bundle resultExtras, String requiredPermission, int appOp, Bundle options,
+ boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
intent = new Intent(intent);
// By default broadcasts do not go to stopped apps.
@@ -16292,6 +16290,28 @@
}
}
+ BroadcastOptions brOptions = null;
+ if (options != null) {
+ brOptions = new BroadcastOptions(options);
+ if (brOptions.getTemporaryAppWhitelistDuration() > 0) {
+ // See if the caller is allowed to do this. Note we are checking against
+ // the actual real caller (not whoever provided the operation as say a
+ // PendingIntent), because that who is actually supplied the arguments.
+ if (checkComponentPermission(
+ android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
+ Binder.getCallingPid(), Binder.getCallingUid(), -1, true)
+ != PackageManager.PERMISSION_GRANTED) {
+ String msg = "Permission Denial: " + intent.getAction()
+ + " broadcast from " + callerPackage + " (pid=" + callingPid
+ + ", uid=" + callingUid + ")"
+ + " requires "
+ + android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+ }
+ }
+
/*
* Prevent non-system code (defined here to be non-persistent
* processes) from sending protected broadcasts.
@@ -16598,8 +16618,8 @@
final BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType, requiredPermission,
- appOp, registeredReceivers, resultTo, resultCode, resultData, map,
- ordered, sticky, false, userId);
+ appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData,
+ resultExtras, ordered, sticky, false, userId);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
if (!replaced) {
@@ -16687,8 +16707,8 @@
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType,
- requiredPermission, appOp, receivers, resultTo, resultCode,
- resultData, map, ordered, sticky, false, userId);
+ requiredPermission, appOp, brOptions, receivers, resultTo, resultCode,
+ resultData, resultExtras, ordered, sticky, false, userId);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r
+ ": prev had " + queue.mOrderedBroadcasts.size());
@@ -16735,8 +16755,9 @@
public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
- int resultCode, String resultData, Bundle map,
- String requiredPermission, int appOp, boolean serialized, boolean sticky, int userId) {
+ int resultCode, String resultData, Bundle resultExtras,
+ String requiredPermission, int appOp, Bundle options,
+ boolean serialized, boolean sticky, int userId) {
enforceNotIsolatedCaller("broadcastIntent");
synchronized(this) {
intent = verifyBroadcastLocked(intent);
@@ -16747,8 +16768,8 @@
final long origId = Binder.clearCallingIdentity();
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
- intent, resolvedType, resultTo,
- resultCode, resultData, map, requiredPermission, appOp, serialized, sticky,
+ intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
+ requiredPermission, appOp, null, serialized, sticky,
callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
@@ -16757,15 +16778,16 @@
int broadcastIntentInPackage(String packageName, int uid,
Intent intent, String resolvedType, IIntentReceiver resultTo,
- int resultCode, String resultData, Bundle map,
- String requiredPermission, boolean serialized, boolean sticky, int userId) {
+ int resultCode, String resultData, Bundle resultExtras,
+ String requiredPermission, Bundle options, boolean serialized, boolean sticky,
+ int userId) {
synchronized(this) {
intent = verifyBroadcastLocked(intent);
final long origId = Binder.clearCallingIdentity();
int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
- resultTo, resultCode, resultData, map, requiredPermission,
- AppOpsManager.OP_NONE, serialized, sticky, -1, uid, userId);
+ resultTo, resultCode, resultData, resultExtras, requiredPermission,
+ AppOpsManager.OP_NONE, options, serialized, sticky, -1, uid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
@@ -17162,8 +17184,8 @@
| Intent.FLAG_RECEIVER_REPLACE_PENDING
| Intent.FLAG_RECEIVER_FOREGROUND);
broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
- null, AppOpsManager.OP_NONE, false, false, MY_PID,
- Process.SYSTEM_UID, UserHandle.USER_ALL);
+ null, AppOpsManager.OP_NONE, null, false, false,
+ MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
@@ -17172,7 +17194,7 @@
}
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+ null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
}
}
}
@@ -19642,7 +19664,7 @@
intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- false, false, MY_PID, Process.SYSTEM_UID, userId);
+ null, false, false, MY_PID, Process.SYSTEM_UID, userId);
}
if ((userInfo.flags&UserInfo.FLAG_INITIALIZED) == 0) {
@@ -19657,8 +19679,7 @@
onUserInitialized(uss, foreground, oldUserId, userId);
}
}, 0, null, null, null, AppOpsManager.OP_NONE,
- true, false, MY_PID, Process.SYSTEM_UID,
- userId);
+ null, true, false, MY_PID, Process.SYSTEM_UID, userId);
uss.initializing = true;
} else {
getUserManagerLocked().makeInitialized(userInfo.id);
@@ -19680,13 +19701,13 @@
broadcastIntentLocked(null, null, intent,
null, new IIntentReceiver.Stub() {
@Override
- public void performReceive(Intent intent, int resultCode, String data,
- Bundle extras, boolean ordered, boolean sticky, int sendingUser)
- throws RemoteException {
+ public void performReceive(Intent intent, int resultCode,
+ String data, Bundle extras, boolean ordered, boolean sticky,
+ int sendingUser) throws RemoteException {
}
}, 0, null, null,
INTERACT_ACROSS_USERS, AppOpsManager.OP_NONE,
- true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+ null, true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
}
}
} finally {
@@ -19724,7 +19745,7 @@
intent.putExtra(Intent.EXTRA_USER_HANDLE, profileUserId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- false, false, MY_PID, Process.SYSTEM_UID, profileUserId);
+ null, false, false, MY_PID, Process.SYSTEM_UID, profileUserId);
}
}
if (newUserId >= 0) {
@@ -19739,7 +19760,7 @@
intent.putExtra(Intent.EXTRA_USER_HANDLE, profileUserId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- false, false, MY_PID, Process.SYSTEM_UID, profileUserId);
+ null, false, false, MY_PID, Process.SYSTEM_UID, profileUserId);
}
intent = new Intent(Intent.ACTION_USER_SWITCHED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
@@ -19748,7 +19769,7 @@
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null,
android.Manifest.permission.MANAGE_USERS, AppOpsManager.OP_NONE,
- false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+ null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -19925,7 +19946,7 @@
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null,
android.Manifest.permission.RECEIVE_BOOT_COMPLETED, AppOpsManager.OP_NONE,
- true, false, MY_PID, Process.SYSTEM_UID, userId);
+ null, true, false, MY_PID, Process.SYSTEM_UID, userId);
}
}
}
@@ -20057,14 +20078,14 @@
mSystemServiceManager.stopUser(userId);
broadcastIntentLocked(null, null, shutdownIntent,
null, shutdownReceiver, 0, null, null, null, AppOpsManager.OP_NONE,
- true, false, MY_PID, Process.SYSTEM_UID, userId);
+ null, true, false, MY_PID, Process.SYSTEM_UID, userId);
}
};
// Kick things off.
broadcastIntentLocked(null, null, stoppingIntent,
null, stoppingReceiver, 0, null, null,
INTERACT_ACROSS_USERS, AppOpsManager.OP_NONE,
- true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+ null, true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
} finally {
Binder.restoreCallingIdentity(ident);
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index eb5af9e5..0714d36 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1326,7 +1326,12 @@
if (r != starting) {
mStackSupervisor.startSpecificActivityLocked(
r, noStackActivityResumed, false);
- noStackActivityResumed = false;
+ if (activityNdx >= activities.size()) {
+ // Record may be removed if its process needs to restart.
+ activityNdx = activities.size() - 1;
+ } else {
+ noStackActivityResumed = false;
+ }
}
} else if (r.visible) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index c973386..3854e51 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -42,6 +42,7 @@
import android.telephony.TelephonyManager;
import android.util.Slog;
+import android.util.TimeUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.BatteryStatsHelper;
@@ -64,16 +65,22 @@
implements PowerManagerInternal.LowPowerModeListener {
static final String TAG = "BatteryStatsService";
- private boolean mFirstExternalStatsUpdate = true;
static IBatteryStats sService;
final BatteryStatsImpl mStats;
final BatteryStatsHandler mHandler;
Context mContext;
PowerManagerInternal mPowerManagerInternal;
+ final int UPDATE_CPU = 0x01;
+ final int UPDATE_WIFI = 0x02;
+ final int UPDATE_RADIO = 0x04;
+ final int UPDATE_BT = 0x08;
+ final int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT;
+
class BatteryStatsHandler extends Handler implements BatteryStatsImpl.ExternalStatsSync {
public static final int MSG_SYNC_EXTERNAL_STATS = 1;
public static final int MSG_WRITE_TO_DISK = 2;
+ private int mUpdateFlags = 0;
public BatteryStatsHandler(Looper looper) {
super(looper);
@@ -83,11 +90,17 @@
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SYNC_EXTERNAL_STATS:
- updateExternalStats((String)msg.obj, false);
+ final int updateFlags;
+ synchronized (this) {
+ removeMessages(MSG_SYNC_EXTERNAL_STATS);
+ updateFlags = mUpdateFlags;
+ mUpdateFlags = 0;
+ }
+ updateExternalStats((String)msg.obj, updateFlags);
break;
case MSG_WRITE_TO_DISK:
- updateExternalStats("write", true);
+ updateExternalStats("write", UPDATE_ALL);
synchronized (mStats) {
mStats.writeAsyncLocked();
}
@@ -97,9 +110,20 @@
@Override
public void scheduleSync(String reason) {
- if (!hasMessages(MSG_SYNC_EXTERNAL_STATS)) {
- Message msg = Message.obtain(this, MSG_SYNC_EXTERNAL_STATS, reason);
- sendMessage(msg);
+ scheduleSyncImpl(reason, UPDATE_ALL);
+ }
+
+ @Override
+ public void scheduleWifiSync(String reason) {
+ scheduleSyncImpl(reason, UPDATE_WIFI);
+ }
+
+ private void scheduleSyncImpl(String reason, int updateFlags) {
+ synchronized (this) {
+ if (mUpdateFlags == 0) {
+ sendMessage(Message.obtain(this, MSG_SYNC_EXTERNAL_STATS, reason));
+ }
+ mUpdateFlags |= updateFlags;
}
}
}
@@ -137,7 +161,7 @@
public void shutdown() {
Slog.w("BatteryStats", "Writing battery stats before shutdown...");
- updateExternalStats("shutdown", true);
+ updateExternalStats("shutdown", UPDATE_ALL);
synchronized (mStats) {
mStats.shutdownLocked();
}
@@ -237,7 +261,7 @@
//Slog.i("foo", "SENDING BATTERY INFO:");
//mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
Parcel out = Parcel.obtain();
- updateExternalStats("get-stats", true);
+ updateExternalStats("get-stats", UPDATE_ALL);
synchronized (mStats) {
mStats.writeToParcel(out, 0);
}
@@ -252,7 +276,7 @@
//Slog.i("foo", "SENDING BATTERY INFO:");
//mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
Parcel out = Parcel.obtain();
- updateExternalStats("get-stats", true);
+ updateExternalStats("get-stats", UPDATE_ALL);
synchronized (mStats) {
mStats.writeToParcel(out, 0);
}
@@ -603,8 +627,10 @@
// There was a change in WiFi power state.
// Collect data now for the past activity.
- mHandler.scheduleSync("wifi-data");
synchronized (mStats) {
+ if (mStats.isOnBattery()) {
+ mHandler.scheduleWifiSync("wifi-data");
+ }
mStats.noteWifiRadioPowerState(powerState, tsNanos);
}
}
@@ -767,10 +793,10 @@
}
@Override
- public void noteDeviceIdleMode(boolean enabled, boolean fromActive, boolean fromMotion) {
+ public void noteDeviceIdleMode(boolean enabled, String activeReason, int activeUid) {
enforceCallingPermission();
synchronized (mStats) {
- mStats.noteDeviceIdleModeLocked(enabled, fromActive, fromMotion);
+ mStats.noteDeviceIdleModeLocked(enabled, activeReason, activeUid);
}
}
@@ -807,7 +833,7 @@
// Sync external stats first as the battery has changed states. If we don't sync
// immediately here, we may not collect the relevant data later.
- updateExternalStats("battery-state", false);
+ updateExternalStats("battery-state", UPDATE_ALL);
synchronized (mStats) {
mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt);
}
@@ -961,9 +987,9 @@
pw.println("Battery stats reset.");
noOutput = true;
}
- updateExternalStats("dump", true);
+ updateExternalStats("dump", UPDATE_ALL);
} else if ("--write".equals(arg)) {
- updateExternalStats("dump", true);
+ updateExternalStats("dump", UPDATE_ALL);
synchronized (mStats) {
mStats.writeSyncLocked();
pw.println("Battery stats written.");
@@ -1027,7 +1053,7 @@
flags |= BatteryStats.DUMP_DEVICE_WIFI_ONLY;
}
// Fetch data from external sources and update the BatteryStatsImpl object with them.
- updateExternalStats("dump", true);
+ updateExternalStats("dump", UPDATE_ALL);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -1119,6 +1145,12 @@
return null;
}
+ final long timePeriodMs = info.mTimestamp - mLastInfo.mTimestamp;
+ final long lastIdleMs = mLastInfo.mControllerIdleTimeMs;
+ final long lastTxMs = mLastInfo.mControllerTxTimeMs;
+ final long lastRxMs = mLastInfo.mControllerRxTimeMs;
+ final long lastEnergy = mLastInfo.mControllerEnergyUsed;
+
// We will modify the last info object to be the delta, and store the new
// WifiActivityEnergyInfo object as our last one.
final WifiActivityEnergyInfo result = mLastInfo;
@@ -1126,19 +1158,16 @@
result.mStackState = info.getStackState();
// These times seem to be the most reliable.
- result.mControllerTxTimeMs =
- info.mControllerTxTimeMs - mLastInfo.mControllerTxTimeMs;
- result.mControllerRxTimeMs =
- info.mControllerRxTimeMs - mLastInfo.mControllerRxTimeMs;
+ result.mControllerTxTimeMs = info.mControllerTxTimeMs - lastTxMs;
+ result.mControllerRxTimeMs = info.mControllerRxTimeMs - lastRxMs;
// WiFi calculates the idle time as a difference from the on time and the various
// Rx + Tx times. There seems to be some missing time there because this sometimes
// becomes negative. Just cap it at 0 and move on.
// b/21613534
- result.mControllerIdleTimeMs =
- Math.max(0, info.mControllerIdleTimeMs - mLastInfo.mControllerIdleTimeMs);
+ result.mControllerIdleTimeMs = Math.max(0, info.mControllerIdleTimeMs - lastIdleMs);
result.mControllerEnergyUsed =
- Math.max(0, info.mControllerEnergyUsed - mLastInfo.mControllerEnergyUsed);
+ Math.max(0, info.mControllerEnergyUsed - lastEnergy);
if (result.mControllerTxTimeMs < 0 ||
result.mControllerRxTimeMs < 0) {
@@ -1151,6 +1180,34 @@
Slog.v(TAG, "WiFi energy data was reset, new WiFi energy data is " + result);
}
+
+ final long totalTimeMs = result.mControllerIdleTimeMs + result.mControllerRxTimeMs +
+ result.mControllerTxTimeMs;
+ if (totalTimeMs > timePeriodMs) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Total time ");
+ TimeUtils.formatDuration(totalTimeMs, sb);
+ sb.append(" is longer than sample period ");
+ TimeUtils.formatDuration(timePeriodMs, sb);
+ sb.append(".\n");
+ sb.append("Previous WiFi snapshot: ").append("idle=");
+ TimeUtils.formatDuration(lastIdleMs, sb);
+ sb.append(" rx=");
+ TimeUtils.formatDuration(lastRxMs, sb);
+ sb.append(" tx=");
+ TimeUtils.formatDuration(lastTxMs, sb);
+ sb.append(" e=").append(lastEnergy);
+ sb.append("\n");
+ sb.append("Current WiFi snapshot: ").append("idle=");
+ TimeUtils.formatDuration(info.mControllerIdleTimeMs, sb);
+ sb.append(" rx=");
+ TimeUtils.formatDuration(info.mControllerRxTimeMs, sb);
+ sb.append(" tx=");
+ TimeUtils.formatDuration(info.mControllerTxTimeMs, sb);
+ sb.append(" e=").append(info.mControllerEnergyUsed);
+ Slog.wtf(TAG, sb.toString());
+ }
+
mLastInfo = info;
return result;
}
@@ -1184,15 +1241,12 @@
* We first grab a lock specific to this method, then once all the data has been collected,
* we grab the mStats lock and update the data.
*
- * TODO(adamlesinski): When we start distributing bluetooth data to apps, we'll want to
- * separate these external stats so that they can be collected individually and on different
- * intervals.
- *
* @param reason The reason why this collection was requested. Useful for debugging.
- * @param force If false, some stats may decide not to be collected for efficiency as their
- * results aren't needed immediately. When true, collect all stats unconditionally.
+ * @param updateFlags Which external stats to update. Can be a combination of
+ * {@link #UPDATE_CPU}, {@link #UPDATE_RADIO}, {@link #UPDATE_WIFI},
+ * and {@link #UPDATE_BT}.
*/
- void updateExternalStats(String reason, boolean force) {
+ void updateExternalStats(final String reason, final int updateFlags) {
synchronized (mExternalStatsLock) {
if (mContext == null) {
// We haven't started yet (which means the BatteryStatsImpl object has
@@ -1200,34 +1254,46 @@
return;
}
- final WifiActivityEnergyInfo wifiEnergyInfo = pullWifiEnergyInfoLocked();
- final BluetoothActivityEnergyInfo bluetoothEnergyInfo;
- if (force) {
+ if (BatteryStatsImpl.DEBUG_ENERGY) {
+ Slog.d(TAG, "Updating external stats: reason=" + reason);
+ }
+
+ WifiActivityEnergyInfo wifiEnergyInfo = null;
+ if ((updateFlags & UPDATE_WIFI) != 0) {
+ wifiEnergyInfo = pullWifiEnergyInfoLocked();
+ }
+
+ BluetoothActivityEnergyInfo bluetoothEnergyInfo = null;
+ if ((updateFlags & UPDATE_BT) != 0) {
// We only pull bluetooth stats when we have to, as we are not distributing its
// use amongst apps and the sampling frequency does not matter.
bluetoothEnergyInfo = pullBluetoothEnergyInfoLocked();
- } else {
- bluetoothEnergyInfo = null;
}
synchronized (mStats) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
if (mStats.mRecordAllHistory) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
mStats.addHistoryEventLocked(elapsedRealtime, uptime,
BatteryStats.HistoryItem.EVENT_COLLECT_EXTERNAL_STATS, reason, 0);
}
- mStats.updateCpuTimeLocked(mFirstExternalStatsUpdate);
- mStats.updateKernelWakelocksLocked();
- mStats.updateMobileRadioStateLocked(SystemClock.elapsedRealtime());
- mStats.updateWifiStateLocked(wifiEnergyInfo);
- mStats.updateBluetoothStateLocked(bluetoothEnergyInfo);
- }
- if (mFirstExternalStatsUpdate) {
- // We have read the stats for the first time, which means we have a baseline
- // from which to calculate delta.
- mFirstExternalStatsUpdate = false;
+ if ((updateFlags & UPDATE_CPU) != 0) {
+ mStats.updateCpuTimeLocked();
+ mStats.updateKernelWakelocksLocked();
+ }
+
+ if ((updateFlags & UPDATE_RADIO) != 0) {
+ mStats.updateMobileRadioStateLocked(elapsedRealtime);
+ }
+
+ if ((updateFlags & UPDATE_WIFI) != 0) {
+ mStats.updateWifiStateLocked(wifiEnergyInfo);
+ }
+
+ if ((updateFlags & UPDATE_BT) != 0) {
+ mStats.updateBluetoothStateLocked(bluetoothEnergyInfo);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 80b8a93..2335071 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -26,6 +26,7 @@
import android.app.ActivityManager;
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
import android.content.ComponentName;
import android.content.IIntentReceiver;
import android.content.Intent;
@@ -43,6 +44,7 @@
import android.os.UserHandle;
import android.util.EventLog;
import android.util.Slog;
+import com.android.server.DeviceIdleController;
import static com.android.server.am.ActivityManagerDebugConfig.*;
@@ -146,6 +148,8 @@
static final int BROADCAST_INTENT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG;
static final int BROADCAST_TIMEOUT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 1;
+ static final int SCHEDULE_TEMP_WHITELIST_MSG
+ = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 2;
final BroadcastHandler mHandler;
@@ -167,6 +171,13 @@
broadcastTimeoutLocked(true);
}
} break;
+ case SCHEDULE_TEMP_WHITELIST_MSG: {
+ DeviceIdleController.LocalService dic = mService.mLocalDeviceIdleController;
+ if (dic != null) {
+ dic.addPowerSaveTempWhitelistAppDirect(UserHandle.getAppId(msg.arg1),
+ msg.arg2);
+ }
+ } break;
}
}
};
@@ -547,6 +558,19 @@
}
}
+ final void scheduleTempWhitelistLocked(int uid, long duration) {
+ if (duration > Integer.MAX_VALUE) {
+ duration = Integer.MAX_VALUE;
+ }
+ // XXX ideally we should pause the broadcast until everything behind this is done,
+ // or else we will likely start dispatching the broadcast before we have opened
+ // access to the app (there is a lot of asynchronicity behind this). It is probably
+ // not that big a deal, however, because the main purpose here is to allow apps
+ // to hold wake locks, and they will be able to acquire their wake lock immediately
+ // it just won't be enabled until we get through this work.
+ mHandler.obtainMessage(SCHEDULE_TEMP_WHITELIST_MSG, uid, (int)duration).sendToTarget();
+ }
+
final void processNextBroadcast(boolean fromMsg) {
synchronized(mService) {
BroadcastRecord r;
@@ -721,7 +745,9 @@
setBroadcastTimeoutLocked(timeoutTime);
}
- Object nextReceiver = r.receivers.get(recIdx);
+ final BroadcastOptions brOptions = r.options;
+ final Object nextReceiver = r.receivers.get(recIdx);
+
if (nextReceiver instanceof BroadcastFilter) {
// Simple case: this is a registered receiver who gets
// a direct call.
@@ -739,6 +765,11 @@
+ r.ordered + " receiver=" + r.receiver);
r.state = BroadcastRecord.IDLE;
scheduleBroadcastsLocked();
+ } else {
+ if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
+ scheduleTempWhitelistLocked(filter.owningUid,
+ brOptions.getTemporaryAppWhitelistDuration());
+ }
}
return;
}
@@ -882,6 +913,11 @@
+ info.activityInfo.applicationInfo.uid);
}
+ if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
+ scheduleTempWhitelistLocked(receiverUid,
+ brOptions.getTemporaryAppWhitelistDuration());
+ }
+
// Broadcast is being executed, its package can't be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
index c050d03f..b943222 100644
--- a/services/core/java/com/android/server/am/BroadcastRecord.java
+++ b/services/core/java/com/android/server/am/BroadcastRecord.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
import android.content.IIntentReceiver;
import android.content.ComponentName;
import android.content.Intent;
@@ -52,6 +53,7 @@
final String resolvedType; // the resolved data type
final String requiredPermission; // a permission the caller has required
final int appOp; // an app op that is associated with this broadcast
+ final BroadcastOptions options; // BroadcastOptions supplied by caller
final List receivers; // contains BroadcastFilter and ResolveInfo
IIntentReceiver resultTo; // who receives final result if non-null
long enqueueClockTime; // the clock time the broadcast was enqueued
@@ -105,6 +107,9 @@
pw.print(prefix); pw.print("requiredPermission="); pw.print(requiredPermission);
pw.print(" appOp="); pw.println(appOp);
}
+ if (options != null) {
+ pw.print(prefix); pw.print("options="); pw.println(options.toBundle());
+ }
pw.print(prefix); pw.print("enqueueClockTime=");
pw.print(new Date(enqueueClockTime));
pw.print(" dispatchClockTime=");
@@ -180,8 +185,8 @@
BroadcastRecord(BroadcastQueue _queue,
Intent _intent, ProcessRecord _callerApp, String _callerPackage,
int _callingPid, int _callingUid, String _resolvedType, String _requiredPermission,
- int _appOp, List _receivers, IIntentReceiver _resultTo, int _resultCode,
- String _resultData, Bundle _resultExtras, boolean _serialized,
+ int _appOp, BroadcastOptions _options, List _receivers, IIntentReceiver _resultTo,
+ int _resultCode, String _resultData, Bundle _resultExtras, boolean _serialized,
boolean _sticky, boolean _initialSticky,
int _userId) {
queue = _queue;
@@ -194,6 +199,7 @@
resolvedType = _resolvedType;
requiredPermission = _requiredPermission;
appOp = _appOp;
+ options = _options;
receivers = _receivers;
resultTo = _resultTo;
resultCode = _resultCode;
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 531de46..ece3ffb 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -199,9 +199,9 @@
}
public int send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver,
- String requiredPermission) throws TransactionTooLargeException {
+ String requiredPermission, Bundle options) throws TransactionTooLargeException {
return sendInner(code, intent, resolvedType, finishedReceiver,
- requiredPermission, null, null, 0, 0, 0, null, null);
+ requiredPermission, null, null, 0, 0, 0, options, null);
}
int sendInner(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver,
@@ -293,9 +293,9 @@
// If a completion callback has been requested, require
// that the broadcast be delivered synchronously
int sent = owner.broadcastIntentInPackage(key.packageName, uid,
- finalIntent, resolvedType,
- finishedReceiver, code, null, null,
- requiredPermission, (finishedReceiver != null), false, userId);
+ finalIntent, resolvedType, finishedReceiver, code, null, null,
+ requiredPermission, options, (finishedReceiver != null),
+ false, userId);
if (sent == ActivityManager.BROADCAST_SUCCESS) {
sendFinish = false;
}
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 236af37..87cb40e 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -445,6 +445,11 @@
// icon, but this used to be able to slip through, so for
// those dirty apps we will create a notification clearly
// blaming the app.
+ Slog.v(TAG, "Attempted to start a foreground service ("
+ + name
+ + ") with a broken notification (no icon: "
+ + localForegroundNoti
+ + ")");
CharSequence appName = appInfo.loadLabel(
ams.mContext.getPackageManager());
@@ -461,6 +466,12 @@
// it's ugly, but it clearly identifies the app
notiBuilder.setSmallIcon(appInfo.icon);
+ // mark as foreground
+ notiBuilder.setFlag(Notification.FLAG_FOREGROUND_SERVICE, true);
+
+ // we are doing the app a kindness here
+ notiBuilder.setPriority(Notification.PRIORITY_MIN);
+
Intent runningIntent = new Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
runningIntent.setData(Uri.fromParts("package",
@@ -498,6 +509,8 @@
nm.enqueueNotification(localPackageName, localPackageName,
appUid, appPid, null, localForegroundId, localForegroundNoti,
outId, userId);
+
+ foregroundNoti = localForegroundNoti; // save it for amending next time
} catch (RuntimeException e) {
Slog.w(TAG, "Error showing notification for service", e);
// If it gave us a garbage notification, it doesn't
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index d39b25f..47d3bde 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1542,11 +1542,7 @@
// UI update and Broadcast Intent
private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
- if (!isPlatformVoice() && (streamType == AudioSystem.STREAM_RING)) {
- streamType = AudioSystem.STREAM_NOTIFICATION;
- } else {
- streamType = mStreamVolumeAlias[streamType];
- }
+ streamType = mStreamVolumeAlias[streamType];
if (streamType == AudioSystem.STREAM_MUSIC) {
flags = updateFlagsForSystemAudio(flags);
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index 4ccb5ad..f72b598 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -46,10 +46,12 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IDeviceIdleController;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.speech.RecognizerIntent;
@@ -1086,6 +1088,14 @@
voiceIntent = new Intent(android.speech.RecognizerIntent.ACTION_WEB_SEARCH);
Log.i(TAG, "voice-based interactions: about to use ACTION_WEB_SEARCH");
} else {
+ IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+ if (dic != null) {
+ try {
+ dic.exitIdle("voice-search");
+ } catch (RemoteException e) {
+ }
+ }
voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE,
isLocked && mKeyguardManager.isKeyguardSecure());
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index dca762c..569a0fc 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -242,19 +242,17 @@
}
if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
+ // Adjust the volume with a handler not to be blocked by other system service.
if (useSuggested) {
if (AudioSystem.isStreamActive(stream, 0)) {
- mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(stream, direction,
- flags, packageName, uid);
+ postAdjustSuggestedStreamVolume(stream, direction, flags, packageName, uid);
} else {
flags |= previousFlagPlaySound;
- mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(
- AudioManager.USE_DEFAULT_STREAM_TYPE, direction, flags, packageName,
- uid);
+ postAdjustSuggestedStreamVolume(AudioManager.USE_DEFAULT_STREAM_TYPE, direction,
+ flags, packageName, uid);
}
} else {
- mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags,
- packageName, uid);
+ postAdjustStreamVolume(stream, direction, flags, packageName, uid);
}
} else {
if (mVolumeControlType == VolumeProvider.VOLUME_CONTROL_FIXED) {
@@ -461,6 +459,28 @@
return mPackageName + "/" + mTag;
}
+ private void postAdjustSuggestedStreamVolume(final int streamType, final int direction,
+ final int flags, final String callingPackage, final int uid) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(streamType, direction,
+ flags, callingPackage, uid);
+ }
+ });
+ }
+
+ private void postAdjustStreamVolume(final int streamType, final int direction, final int flags,
+ final String callingPackage, final int uid) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mAudioManagerInternal.adjustStreamVolumeForUid(streamType, direction, flags,
+ callingPackage, uid);
+ }
+ });
+ }
+
private String getShortMetadataString() {
int fields = mMetadata == null ? 0 : mMetadata.size();
MediaDescription description = mMetadata == null ? null : mMetadata
diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java
index 0f88883..9db6a06 100644
--- a/services/core/java/com/android/server/net/LockdownVpnTracker.java
+++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java
@@ -17,6 +17,7 @@
package com.android.server.net;
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NONE;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
@@ -201,8 +202,8 @@
setFirewallEgressSourceRule(addr, true);
}
- mNetService.setFirewallUidRule(ROOT_UID, FIREWALL_RULE_ALLOW);
- mNetService.setFirewallUidRule(Os.getuid(), FIREWALL_RULE_ALLOW);
+ mNetService.setFirewallUidRule(FIREWALL_CHAIN_NONE, ROOT_UID, FIREWALL_RULE_ALLOW);
+ mNetService.setFirewallUidRule(FIREWALL_CHAIN_NONE, Os.getuid(), FIREWALL_RULE_ALLOW);
mErrorCount = 0;
mAcceptedIface = iface;
@@ -291,8 +292,8 @@
setFirewallEgressSourceRule(addr, false);
}
- mNetService.setFirewallUidRule(ROOT_UID, FIREWALL_RULE_DEFAULT);
- mNetService.setFirewallUidRule(Os.getuid(), FIREWALL_RULE_DEFAULT);
+ mNetService.setFirewallUidRule(FIREWALL_CHAIN_NONE, ROOT_UID, FIREWALL_RULE_DEFAULT);
+ mNetService.setFirewallUidRule(FIREWALL_CHAIN_NONE,Os.getuid(), FIREWALL_RULE_DEFAULT);
mAcceptedSourceAddr = null;
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index e009455..b0550d6 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -36,8 +36,10 @@
import static android.net.NetworkPolicy.SNOOZE_NEVER;
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
+import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
-import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_BACKGROUND_BATTERY_SAVE;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
@@ -80,7 +82,6 @@
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.INotificationManager;
-import android.app.IProcessObserver;
import android.app.IUidObserver;
import android.app.Notification;
import android.app.PendingIntent;
@@ -141,7 +142,6 @@
import android.util.NtpTrustedTime;
import android.util.Pair;
import android.util.Slog;
-import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.TrustedTime;
@@ -279,6 +279,7 @@
final SparseIntArray mUidPolicy = new SparseIntArray();
/** Currently derived rules for each UID. */
final SparseIntArray mUidRules = new SparseIntArray();
+ final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
/**
* UIDs that have been white-listed to always be able to have network access
@@ -412,8 +413,6 @@
mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
- final PackageManager pm = mContext.getPackageManager();
-
synchronized (mRulesLock) {
updatePowerSaveWhitelistLocked();
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
@@ -1103,7 +1102,7 @@
// will not have a bandwidth limit. Also only do this if restrict
// background data use is *not* enabled, since that takes precendence
// use over those networks can have a cost associated with it).
- final boolean powerSave = (mRestrictPower || mDeviceIdleMode) && !mRestrictBackground;
+ final boolean powerSave = mRestrictPower && !mRestrictBackground;
// First, generate identities of all connected networks so we can
// quickly compare them against all defined policies below.
@@ -2024,6 +2023,29 @@
}
}
+ void updateRulesForDeviceIdleLocked() {
+ if (mDeviceIdleMode) {
+ // sync the whitelists before enable dozable chain. We don't care about the rules if
+ // we are disabling the chain.
+ SparseIntArray uidRules = new SparseIntArray();
+ final List<UserInfo> users = mUserManager.getUsers();
+ for (UserInfo user : users) {
+ for (int i = mPowerSaveTempWhitelistAppIds.size() - 1; i >= 0; i--) {
+ int appId = mPowerSaveTempWhitelistAppIds.keyAt(i);
+ int uid = UserHandle.getUid(user.id, appId);
+ uidRules.put(uid, FIREWALL_RULE_ALLOW);
+ }
+ for (int i = mPowerSaveWhitelistAppIds.size() - 1; i >= 0; i--) {
+ int appId = mPowerSaveWhitelistAppIds.keyAt(i);
+ int uid = UserHandle.getUid(user.id, appId);
+ uidRules.put(uid, FIREWALL_RULE_ALLOW);
+ }
+ }
+ setUidFirewallRules(FIREWALL_CHAIN_DOZABLE, uidRules);
+ }
+ enableFirewallChain(FIREWALL_CHAIN_DOZABLE, mDeviceIdleMode);
+ }
+
/**
* Update rules that might be changed by {@link #mRestrictBackground},
* {@link #mRestrictPower}, or {@link #mDeviceIdleMode} value.
@@ -2034,10 +2056,12 @@
// If we are in restrict power mode, we allow all important apps
// to have data access. Otherwise, we restrict data access to only
// the top apps.
- mCurForegroundState = (!mRestrictBackground && (mRestrictPower || mDeviceIdleMode))
+ mCurForegroundState = (!mRestrictBackground && mRestrictPower)
? ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
: ActivityManager.PROCESS_STATE_TOP;
+ updateRulesForDeviceIdleLocked();
+
// update rules for all installed applications
final List<UserInfo> users = mUserManager.getUsers();
final List<ApplicationInfo> apps = pm.getInstalledApplications(
@@ -2131,7 +2155,7 @@
// uid in background, and global background disabled
uidRules = RULE_REJECT_METERED;
}
- } else if (mRestrictPower || mDeviceIdleMode) {
+ } else if (mRestrictPower) {
final boolean whitelisted = mPowerSaveWhitelistAppIds.get(appId)
|| mPowerSaveTempWhitelistAppIds.get(appId);
if (!whitelisted && !uidForeground
@@ -2162,7 +2186,12 @@
final boolean oldFirewallReject = (oldRules & RULE_REJECT_ALL) != 0;
final boolean firewallReject = (uidRules & RULE_REJECT_ALL) != 0;
if (oldFirewallReject != firewallReject) {
- setUidFirewallRules(uid, firewallReject);
+ setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, firewallReject);
+ if (mDeviceIdleMode && !firewallReject) {
+ // if we are in device idle mode, and we decide to allow this uid. we need to punch
+ // a hole in the device idle chain.
+ setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, false);
+ }
}
// dispatch changed rule to existing listeners
@@ -2314,14 +2343,20 @@
}
/**
- * Add or remove a uid to the firewall blacklist for all network ifaces.
- * @param uid
- * @param rejectOnAll
+ * Set uid rules on a particular firewall chain. This is going to synchronize the rules given
+ * here to netd. It will clean up dead rules and make sure the target chain only contains rules
+ * specified here.
*/
- private void setUidFirewallRules(int uid, boolean rejectOnAll) {
+ private void setUidFirewallRules(int chain, SparseIntArray uidRules) {
try {
- mNetworkManager.setFirewallUidRule(uid,
- rejectOnAll ? FIREWALL_RULE_DENY : FIREWALL_RULE_DEFAULT);
+ int size = uidRules.size();
+ int[] uids = new int[size];
+ int[] rules = new int[size];
+ for(int index = size - 1; index >= 0; --index) {
+ uids[index] = uidRules.keyAt(index);
+ rules[index] = uidRules.valueAt(index);
+ }
+ mNetworkManager.setFirewallUidRules(chain, uids, rules);
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem setting firewall uid rules", e);
} catch (RemoteException e) {
@@ -2329,6 +2364,38 @@
}
}
+ /**
+ * Add or remove a uid to the firewall blacklist for all network ifaces.
+ */
+ private void setUidFirewallRule(int chain, int uid, boolean rejectOnAll) {
+ try {
+ mNetworkManager.setFirewallUidRule(chain, uid,
+ rejectOnAll ? FIREWALL_RULE_DENY : FIREWALL_RULE_ALLOW);
+ } catch (IllegalStateException e) {
+ Log.wtf(TAG, "problem setting firewall uid rules", e);
+ } catch (RemoteException e) {
+ // ignored; service lives in system_server
+ }
+ }
+
+ /**
+ * Add or remove a uid to the firewall blacklist for all network ifaces.
+ */
+ private void enableFirewallChain(int chain, boolean enable) {
+ if (mFirewallChainStates.indexOfKey(chain) >= 0 &&
+ mFirewallChainStates.get(chain) == enable) {
+ // All is the same, nothing to do.
+ return;
+ }
+ try {
+ mNetworkManager.setFirewallChainEnabled(chain, enable);
+ } catch (IllegalStateException e) {
+ Log.wtf(TAG, "problem enable firewall chain", e);
+ } catch (RemoteException e) {
+ // ignored; service lives in system_server
+ }
+ }
+
private long getTotalBytes(NetworkTemplate template, long start, long end) {
try {
return mNetworkStats.getNetworkTotalBytes(template, start, end);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 5b7dd70..cbb90ba 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1586,6 +1586,11 @@
grantRequestedRuntimePermissionsForUser(pkg, someUserId);
}
}
+
+ // We could have touched GID membership, so flush out packages.list
+ synchronized (mPackages) {
+ mSettings.writePackageListLPr();
+ }
}
private void grantRequestedRuntimePermissionsForUser(PackageParser.Package pkg, int userId) {
@@ -7719,7 +7724,7 @@
}
}
}
-
+
if (pkgInfo != null) {
grantPermissionsLPw(pkgInfo, (flags&UPDATE_PERMISSIONS_REPLACE_PKG) != 0, changingPkg);
}
@@ -7999,7 +8004,7 @@
// Persist the runtime permissions state for users with changes.
for (int userId : changedRuntimePermissionUserIds) {
- mSettings.writeRuntimePermissionsForUserLPr(userId, true);
+ mSettings.writeRuntimePermissionsForUserLPr(userId, false);
}
}
@@ -8808,7 +8813,7 @@
}
am.broadcastIntent(null, intent, null, finishedReceiver,
0, null, null, null, android.app.AppOpsManager.OP_NONE,
- finishedReceiver != null, false, id);
+ null, finishedReceiver != null, false, id);
}
} catch (RemoteException ex) {
}
@@ -8982,7 +8987,7 @@
.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
.setPackage(packageName);
am.broadcastIntent(null, bcIntent, null, null, 0, null, null, null,
- android.app.AppOpsManager.OP_NONE, false, false, userId);
+ android.app.AppOpsManager.OP_NONE, null, false, false, userId);
}
} catch (RemoteException e) {
// shouldn't happen
@@ -14085,7 +14090,9 @@
}
}
- if (!checkin && dumpState.isDumping(DumpState.DUMP_DOMAIN_PREFERRED)) {
+ if (!checkin
+ && dumpState.isDumping(DumpState.DUMP_DOMAIN_PREFERRED)
+ && packageName == null) {
pw.println();
int count = mSettings.mPackages.size();
if (count == 0) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index dbcfa19..bd545df 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -56,6 +56,7 @@
import android.os.FactoryTest;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IDeviceIdleController;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
@@ -2734,6 +2735,14 @@
if (!keyguardOn) {
voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
} else {
+ IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+ if (dic != null) {
+ try {
+ dic.exitIdle("voice-search");
+ } catch (RemoteException e) {
+ }
+ }
voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
}
@@ -3739,13 +3748,14 @@
attrs.gravity = Gravity.BOTTOM;
mDockLayer = win.getSurfaceLayer();
} else if (attrs.type == TYPE_VOICE_INTERACTION) {
- pf.left = df.left = of.left = cf.left = vf.left = mUnrestrictedScreenLeft;
+ pf.left = df.left = of.left = mUnrestrictedScreenLeft;
pf.top = df.top = of.top = mUnrestrictedScreenTop;
- pf.right = df.right = of.right = cf.right = vf.right = mUnrestrictedScreenLeft
- + mUnrestrictedScreenWidth;
- pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
- + mUnrestrictedScreenHeight;
+ pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
+ pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
cf.bottom = vf.bottom = mStableBottom;
+ // Note: In Phone landscape mode, the button bar should also be excluded.
+ cf.right = vf.right = mStableRight;
+ cf.left = vf.left = mStableLeft;
cf.top = vf.top = mStableTop;
} else if (win == mStatusBar) {
pf.left = df.left = of.left = mUnrestrictedScreenLeft;
@@ -5191,6 +5201,14 @@
}
void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
+ IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+ if (dic != null) {
+ try {
+ dic.exitIdle("voice-search");
+ } catch (RemoteException e) {
+ }
+ }
Intent voiceIntent =
new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 1b63ca0..ace5997 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -7139,20 +7139,14 @@
public Configuration computeNewConfiguration() {
synchronized (mWindowMap) {
- if (!mDisplayReady) {
- return null;
- }
- Configuration config = computeNewConfigurationLocked();
- if (mWaitingForConfig) {
- mWaitingForConfig = false;
- mLastFinishedFreezeSource = "new-config";
- performLayoutAndPlaceSurfacesLocked();
- }
- return config;
+ return computeNewConfigurationLocked();
}
}
- Configuration computeNewConfigurationLocked() {
+ private Configuration computeNewConfigurationLocked() {
+ if (!mDisplayReady) {
+ return null;
+ }
Configuration config = new Configuration();
config.fontScale = 0;
computeScreenConfigurationLocked(config);
@@ -9678,7 +9672,7 @@
/**
* Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
- * @param w WindowState this method is applied to.
+ * @param w WindowState this method is applied to.
* @param innerDw Width of app window.
* @param innerDh Height of app window.
*/
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index f1f61f3..3b62b61 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -211,6 +211,7 @@
DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_SMS);
DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_FUN);
DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_SAFE_BOOT);
+ DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_CREATE_WINDOWS);
}
// The following user restrictions cannot be changed by any active admin, including device
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 29c65db..76226b4 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -292,7 +292,7 @@
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
- mSystemContext.setTheme(android.R.style.Theme_Material_DayNight_DarkActionBar);
+ mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}
/**
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 75b8278..3767fce 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -981,7 +981,7 @@
}
}
- private class BinderService extends IUsageStatsManager.Stub {
+ private final class BinderService extends IUsageStatsManager.Stub {
private boolean hasPermission(String callingPackage) {
final int callingUid = Binder.getCallingUid();
@@ -1121,7 +1121,7 @@
* ActivityManagerService will call these methods holding the 'am' lock, which means we
* shouldn't be doing any IO work or other long running tasks in these methods.
*/
- private class LocalService extends UsageStatsManagerInternal {
+ private final class LocalService extends UsageStatsManagerInternal {
@Override
public void reportEvent(ComponentName component, int userId, int eventType) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 0b430ca0..47a230a 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -180,8 +180,6 @@
public boolean showLocked(Bundle args, int flags,
IVoiceInteractionSessionShowCallback showCallback) {
- // For now we never allow screenshots.
- flags &= ~VoiceInteractionSession.SHOW_WITH_SCREENSHOT;
if (mBound) {
if (!mFullyBound) {
mFullyBound = mContext.bindServiceAsUser(mBindIntent, mFullConnection,
@@ -190,13 +188,15 @@
new UserHandle(mUser));
}
mShown = true;
+ boolean allDataEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, mUser) != 0;
mShowArgs = args;
mShowFlags = flags;
mHaveAssistData = false;
if ((flags& VoiceInteractionSession.SHOW_WITH_ASSIST) != 0) {
if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ASSIST_STRUCTURE, mCallingUid,
mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED
- && isStructureEnabled()) {
+ && allDataEnabled) {
try {
mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL,
mAssistReceiver);
@@ -212,7 +212,8 @@
mHaveScreenshot = false;
if ((flags& VoiceInteractionSession.SHOW_WITH_SCREENSHOT) != 0) {
if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ASSIST_SCREENSHOT, mCallingUid,
- mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED) {
+ mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED
+ && allDataEnabled) {
try {
mIWindowManager.requestAssistScreenshot(mScreenshotReceiver);
} catch (RemoteException e) {
@@ -466,11 +467,6 @@
mService = null;
}
- private boolean isStructureEnabled() {
- return Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, mUser) != 0;
- }
-
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("mToken="); pw.println(mToken);
pw.print(prefix); pw.print("mShown="); pw.println(mShown);
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 0cd8c19..a0669e4 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -477,39 +477,6 @@
}
/**
- * Sets the SIM call manager to the specified phone account.
- *
- * @param accountHandle The phone account handle of the account to set as the sim call manager.
- * @hide
- */
- public void setSimCallManager(PhoneAccountHandle accountHandle) {
- try {
- if (isServiceConnected()) {
- getTelecomService().setSimCallManager(accountHandle);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelecomService#setSimCallManager");
- }
- }
-
- /**
- * Returns the list of registered SIM call managers.
- *
- * @return List of registered SIM call managers.
- * @hide
- */
- public List<PhoneAccountHandle> getSimCallManagers() {
- try {
- if (isServiceConnected()) {
- return getTelecomService().getSimCallManagers(mContext.getOpPackageName());
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelecomService#getSimCallManagers");
- }
- return new ArrayList<>();
- }
-
- /**
* Returns the current connection manager. Apps must be prepared for this method to return
* {@code null}, indicating that there currently exists no user-chosen default
* {@code PhoneAccount}.
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index ea6a74a..fb0f6da 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -93,16 +93,6 @@
PhoneAccountHandle getSimCallManager();
/**
- * @see TelecomServiceImpl#setSimCallManager
- */
- void setSimCallManager(in PhoneAccountHandle account);
-
- /**
- * @see TelecomServiceImpl#getSimCallManagers
- */
- List<PhoneAccountHandle> getSimCallManagers(String callingPackage);
-
- /**
* @see TelecomServiceImpl#registerPhoneAccount
*/
void registerPhoneAccount(in PhoneAccount metadata);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index f85a820..01cab33 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -125,6 +125,10 @@
public static final String
KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool";
+ /** Control whether users can reach the SIM lock settings. */
+ public static final String
+ KEY_HIDE_SIM_LOCK_SETTINGS_BOOL = "hide_sim_lock_settings_bool";
+
/** Control whether users can edit APNs in Settings. */
public static final String KEY_APN_EXPAND_BOOL = "apn_expand_bool";
@@ -178,6 +182,34 @@
public static final String
KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
+ /**
+ * Override the platform's notion of a network operator being considered roaming.
+ * Value is string array of MCCMNCs to be considered roaming for 3GPP RATs.
+ */
+ public static final String
+ KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY = "gsm_roaming_networks_string_array";
+
+ /**
+ * Override the platform's notion of a network operator being considered not roaming.
+ * Value is string array of MCCMNCs to be considered not roaming for 3GPP RATs.
+ */
+ public static final String
+ KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY = "gsm_nonroaming_networks_string_array";
+
+ /**
+ * Override the platform's notion of a network operator being considered roaming.
+ * Value is string array of SIDs to be considered roaming for 3GPP2 RATs.
+ */
+ public static final String
+ KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY = "cdma_roaming_networks_string_array";
+
+ /**
+ * Override the platform's notion of a network operator being considered non roaming.
+ * Value is string array of SIDs to be considered not roaming for 3GPP2 RATs.
+ */
+ public static final String
+ KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY = "cdma_nonroaming_networks_string_array";
+
/**
* Flag specifying whether VoLTE should be available for carrier, independent of carrier
* provisioning. If false: hard disabled. If true: then depends on carrier provisioning,
@@ -320,6 +352,7 @@
sDefaults.putBoolean(KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL, true);
sDefaults.putBoolean(KEY_HAS_IN_CALL_NOISE_SUPPRESSION_BOOL, false);
sDefaults.putBoolean(KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+ sDefaults.putBoolean(KEY_HIDE_SIM_LOCK_SETTINGS_BOOL, false);
sDefaults.putBoolean(KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL, false);
sDefaults.putBoolean(KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
sDefaults.putBoolean(KEY_PREFER_2G_BOOL, true);
@@ -345,6 +378,11 @@
sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING, "");
sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING, "");
+ sDefaults.putStringArray(KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY, null);
+ sDefaults.putStringArray(KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY, null);
+ sDefaults.putStringArray(KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY, null);
+ sDefaults.putStringArray(KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY, null);
+
// MMS defaults
sDefaults.putBoolean(KEY_MMS_ALIAS_ENABLED_BOOL, false);
sDefaults.putBoolean(KEY_MMS_ALLOW_ATTACH_AUDIO_BOOL, true);
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index 674777e..8443490 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -153,17 +153,17 @@
/**
* The outgoing call failed with an unknown cause.
*/
- public static final int OUTGOING_FAILURE = 43;
+ public static final int OUTGOING_FAILURE = 43;
/**
* The outgoing call was canceled by the {@link android.telecom.ConnectionService}.
*/
- public static final int OUTGOING_CANCELED = 44;
+ public static final int OUTGOING_CANCELED = 44;
/**
* The call, which was an IMS call, disconnected because it merged with another call.
*/
- public static final int IMS_MERGED_SUCCESSFULLY = 45;
+ public static final int IMS_MERGED_SUCCESSFULLY = 45;
/**
* Stk Call Control modified DIAL request to USSD request.
@@ -181,6 +181,12 @@
*/
public static final int DIAL_MODIFIED_TO_DIAL = 48;
+ /**
+ * The call was terminated because CDMA phone service and roaming have already been activated.
+ * {@hide}
+ */
+ public static final int CDMA_ALREADY_ACTIVATED = 49;
+
//*********************************************************************************************
// When adding a disconnect type:
// 1) Please assign the new type the next id value below.
@@ -189,14 +195,14 @@
// 4) Update toString() with the newly added disconnect type.
// 5) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause.
//
- // NextId: 49
+ // NextId: 50
//*********************************************************************************************
/** Smallest valid value for call disconnect codes. */
public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED;
/** Largest valid value for call disconnect codes. */
- public static final int MAXIMUM_VALID_VALUE = DIAL_MODIFIED_TO_DIAL;
+ public static final int MAXIMUM_VALID_VALUE = CDMA_ALREADY_ACTIVATED;
/** Private constructor to avoid class instantiation. */
private DisconnectCause() {
@@ -302,6 +308,8 @@
return "OUTGOING_CANCELED";
case IMS_MERGED_SUCCESSFULLY:
return "IMS_MERGED_SUCCESSFULLY";
+ case CDMA_ALREADY_ACTIVATED:
+ return "CDMA_ALREADY_ACTIVATED";
default:
return "INVALID: " + cause;
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index e085d89..fa1ed54 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1124,13 +1124,14 @@
* {@hide}
*/
public static int getSimStateForSlotIdx(int slotIdx) {
- int simState;
+ int simState = TelephonyManager.SIM_STATE_UNKNOWN;
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
- simState = iSub.getSimStateForSlotIdx(slotIdx);
+ if (iSub != null) {
+ simState = iSub.getSimStateForSlotIdx(slotIdx);
+ }
} catch (RemoteException ex) {
- simState = TelephonyManager.SIM_STATE_UNKNOWN;
}
logd("getSimStateForSubscriber: simState=" + simState + " slotIdx=" + slotIdx);
return simState;
@@ -1144,7 +1145,9 @@
public boolean isActiveSubId(int subId) {
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
- return iSub.isActiveSubId(subId);
+ if (iSub != null) {
+ return iSub.isActiveSubId(subId);
+ }
} catch (RemoteException ex) {
}
return false;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 6a8b065..f77d268 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2139,7 +2139,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.getMergedSubscriberIds();
+ return telephony.getMergedSubscriberIds(mContext.getOpPackageName());
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index c253b4f..44754ab 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -795,7 +795,7 @@
*/
String getLine1AlphaTagForDisplay(int subId, String callingPackage);
- String[] getMergedSubscriberIds();
+ String[] getMergedSubscriberIds(String callingPackage);
/**
* Override the operator branding for the current ICCID.
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index 04ded9d..e5e3e44 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -16,6 +16,7 @@
package android.test.mock;
+import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -317,6 +318,13 @@
}
/** @hide */
+ @SystemApi
+ @Override
+ public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** @hide */
@Override
public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
throw new UnsupportedOperationException();
@@ -336,6 +344,15 @@
}
/** @hide */
+ @SystemApi
+ @Override
+ public void sendOrderedBroadcast(Intent intent, String receiverPermission,
+ Bundle options, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData,
+ Bundle initialExtras) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** @hide */
@Override
public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp,
BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData,
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml
index d282fc9..0f3fb95 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml
@@ -13,37 +13,41 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="64dp"
- android:height="64dp"
- android:viewportWidth="7.30625"
- android:viewportHeight="12.25"
- android:autoMirrored="true">
+ android:autoMirrored="true"
+ android:height="64dp"
+ android:viewportHeight="12.25"
+ android:viewportWidth="7.30625"
+ android:width="64dp" >
<group>
<clip-path
- android:name="clip1"
- android:pathData="
+ android:name="clip1"
+ android:pathData="
M 3.65, 6.125
m-.001, 0
a .001,.001 0 1,0 .002,0
- a .001,.001 0 1,0-.002,0z"/>
- <path
- android:name="one"
- android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0-6.671875-2.109375,0.421875 0.0-1.078125
- l 2.09375-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
- l-5.046875,0.0 0.0-1.0Z"
- android:fillColor="#ff88ff"/>
+ a .001,.001 0 1,0-.002,0z" />
+ <path
+ android:name="one"
+ android:fillColor="#ff88ff"
+ android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0-6.671875-2.109375,0.421875 0.0-1.078125
+ l 2.09375-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
+ l-5.046875,0.0 0.0-1.0Z" />
+ </group>
+ <group>
<clip-path
- android:name="clip2"
- android:pathData="
+ android:name="clip2"
+ android:pathData="
M 3.65, 6.125
m-6, 0
a 6,6 0 1,0 12,0
- a 6,6 0 1,0-12,0z"/>
+ a 6,6 0 1,0-12,0z" />
+
<path
- android:name="two"
- android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0-5.5625,0.0 0.0-1.0q 0.671875-0.6875 1.828125-1.859375
+ android:name="two"
+ android:fillColor="#ff88ff"
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0-5.5625,0.0 0.0-1.0q 0.671875-0.6875 1.828125-1.859375
q 1.1718752-1.1875 1.4687502-1.53125 0.578125-0.625 0.796875-1.0625
q 0.234375-0.453125 0.234375-0.875 0.0-0.703125-0.5-1.140625
q-0.484375-0.4375-1.2656252-0.4375-0.5625,0.0-1.1875,0.1875
@@ -51,7 +55,7 @@
q 0.625-0.15625 1.140625-0.15625 1.3593752,0.0 2.1718752,0.6875
q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125-0.203125,1.015625
q-0.203125,0.484375-0.734375,1.140625-0.15625,0.171875-0.9375,0.984375
- q-0.78125024,0.8125-2.2187502,2.265625Z"
- android:fillColor="#ff88ff"/>
+ q-0.78125024,0.8125-2.2187502,2.265625Z" />
</group>
-</vector>
+
+</vector>
\ No newline at end of file
diff --git a/tools/aapt2/BinaryResourceParser.cpp b/tools/aapt2/BinaryResourceParser.cpp
index 3559f43..4f1947a 100644
--- a/tools/aapt2/BinaryResourceParser.cpp
+++ b/tools/aapt2/BinaryResourceParser.cpp
@@ -116,9 +116,11 @@
BinaryResourceParser::BinaryResourceParser(const std::shared_ptr<ResourceTable>& table,
const std::shared_ptr<IResolver>& resolver,
const Source& source,
+ const std::u16string& defaultPackage,
const void* data,
size_t len) :
- mTable(table), mResolver(resolver), mSource(source), mData(data), mDataLen(len) {
+ mTable(table), mResolver(resolver), mSource(source), mDefaultPackage(defaultPackage),
+ mData(data), mDataLen(len) {
}
bool BinaryResourceParser::parse() {
@@ -177,6 +179,9 @@
if (!type) {
return false;
}
+ if (outSymbol->package.empty()) {
+ outSymbol->package = mTable->getPackage();
+ }
outSymbol->type = *type;
// Since we scan the symbol table in order, we can start looking for the
@@ -350,7 +355,22 @@
size_t len = strnlen16(reinterpret_cast<const char16_t*>(packageHeader->name),
sizeof(packageHeader->name) / sizeof(packageHeader->name[0]));
- mTable->setPackage(StringPiece16(reinterpret_cast<const char16_t*>(packageHeader->name), len));
+ if (mTable->getPackage().empty() && len == 0) {
+ mTable->setPackage(mDefaultPackage);
+ } else if (len > 0) {
+ StringPiece16 thisPackage(reinterpret_cast<const char16_t*>(packageHeader->name), len);
+ if (mTable->getPackage().empty()) {
+ mTable->setPackage(thisPackage);
+ } else if (thisPackage != mTable->getPackage()) {
+ Logger::error(mSource)
+ << "incompatible packages: "
+ << mTable->getPackage()
+ << " vs. "
+ << thisPackage
+ << std::endl;
+ return false;
+ }
+ }
ResChunkPullParser parser(getChunkData(packageHeader->header),
getChunkDataLen(packageHeader->header));
diff --git a/tools/aapt2/BinaryResourceParser.h b/tools/aapt2/BinaryResourceParser.h
index 32876cd..3aab301 100644
--- a/tools/aapt2/BinaryResourceParser.h
+++ b/tools/aapt2/BinaryResourceParser.h
@@ -45,6 +45,7 @@
BinaryResourceParser(const std::shared_ptr<ResourceTable>& table,
const std::shared_ptr<IResolver>& resolver,
const Source& source,
+ const std::u16string& defaultPackage,
const void* data, size_t len);
BinaryResourceParser(const BinaryResourceParser&) = delete; // No copy.
@@ -97,12 +98,12 @@
const Source mSource;
+ // The package name of the resource table.
+ std::u16string mDefaultPackage;
+
const void* mData;
const size_t mDataLen;
- // The package name of the resource table.
- std::u16string mPackage;
-
// The array of symbol entries. Each element points to an offset
// in the table and an index into the symbol table string pool.
const SymbolTable_entry* mSymbolEntries = nullptr;
diff --git a/tools/aapt2/Linker.cpp b/tools/aapt2/Linker.cpp
index f3f04a5..c37cc93 100644
--- a/tools/aapt2/Linker.cpp
+++ b/tools/aapt2/Linker.cpp
@@ -160,7 +160,7 @@
void Linker::visit(Reference& reference, ValueVisitorArgs& a) {
Args& args = static_cast<Args&>(a);
- if (!reference.name.isValid()) {
+ if (reference.name.entry.empty()) {
// We can't have a completely bad reference.
if (!reference.id.isValid()) {
Logger::error() << "srsly? " << args.referrer << std::endl;
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
index 41c229d..54a7329 100644
--- a/tools/aapt2/Main.cpp
+++ b/tools/aapt2/Main.cpp
@@ -756,8 +756,8 @@
zipFile->uncompress(entry));
assert(uncompressedData);
- BinaryResourceParser parser(table, resolver, source, uncompressedData.get(),
- entry->getUncompressedLen());
+ BinaryResourceParser parser(table, resolver, source, options.appInfo.package,
+ uncompressedData.get(), entry->getUncompressedLen());
if (!parser.parse()) {
return false;
}
@@ -1085,50 +1085,47 @@
}
bool isStaticLib = false;
+ if (options.phase == AaptOptions::Phase::Link) {
+ flag::requiredFlag("--manifest", "AndroidManifest.xml of your app",
+ [&options](const StringPiece& arg) {
+ options.manifest = Source{ arg.toString() };
+ });
+
+ flag::optionalFlag("-I", "add an Android APK to link against",
+ [&options](const StringPiece& arg) {
+ options.libraries.push_back(Source{ arg.toString() });
+ });
+
+ flag::optionalFlag("--java", "directory in which to generate R.java",
+ [&options](const StringPiece& arg) {
+ options.generateJavaClass = Source{ arg.toString() };
+ });
+
+ flag::optionalFlag("--proguard", "file in which to output proguard rules",
+ [&options](const StringPiece& arg) {
+ options.generateProguardRules = Source{ arg.toString() };
+ });
+
+ flag::optionalSwitch("--static-lib", "generate a static Android library", true,
+ &isStaticLib);
+
+ flag::optionalFlag("--binding", "Output directory for binding XML files",
+ [&options](const StringPiece& arg) {
+ options.bindingOutput = Source{ arg.toString() };
+ });
+ flag::optionalSwitch("--no-version", "Disables automatic style and layout versioning",
+ false, &options.versionStylesAndLayouts);
+ }
+
if (options.phase == AaptOptions::Phase::Compile ||
options.phase == AaptOptions::Phase::Link) {
- if (options.phase == AaptOptions::Phase::Compile) {
- flag::requiredFlag("--package", "Android package name",
- [&options](const StringPiece& arg) {
- options.appInfo.package = util::utf8ToUtf16(arg);
- });
- } else if (options.phase == AaptOptions::Phase::Link) {
- flag::requiredFlag("--manifest", "AndroidManifest.xml of your app",
- [&options](const StringPiece& arg) {
- options.manifest = Source{ arg.toString() };
- });
-
- flag::optionalFlag("-I", "add an Android APK to link against",
- [&options](const StringPiece& arg) {
- options.libraries.push_back(Source{ arg.toString() });
- });
-
- flag::optionalFlag("--java", "directory in which to generate R.java",
- [&options](const StringPiece& arg) {
- options.generateJavaClass = Source{ arg.toString() };
- });
-
- flag::optionalFlag("--proguard", "file in which to output proguard rules",
- [&options](const StringPiece& arg) {
- options.generateProguardRules = Source{ arg.toString() };
- });
-
- flag::optionalSwitch("--static-lib", "generate a static Android library", true,
- &isStaticLib);
-
- flag::optionalFlag("--binding", "Output directory for binding XML files",
- [&options](const StringPiece& arg) {
- options.bindingOutput = Source{ arg.toString() };
- });
- flag::optionalSwitch("--no-version", "Disables automatic style and layout versioning",
- false, &options.versionStylesAndLayouts);
- }
-
// Common flags for all steps.
flag::requiredFlag("-o", "Output path", [&options](const StringPiece& arg) {
options.output = Source{ arg.toString() };
});
- } else if (options.phase == AaptOptions::Phase::DumpStyleGraph) {
+ }
+
+ if (options.phase == AaptOptions::Phase::DumpStyleGraph) {
flag::requiredFlag("--style", "Name of the style to dump",
[&options](const StringPiece& arg, std::string* outError) -> bool {
Reference styleReference;
@@ -1191,7 +1188,7 @@
zipFile->uncompress(entry));
assert(uncompressedData);
- BinaryResourceParser parser(table, resolver, source, uncompressedData.get(),
+ BinaryResourceParser parser(table, resolver, source, {}, uncompressedData.get(),
entry->getUncompressedLen());
if (!parser.parse()) {
return false;
@@ -1223,16 +1220,17 @@
if (!loadAppInfo(options.manifest, &options.appInfo)) {
return false;
}
- }
- // Verify we have some common options set.
- if (options.appInfo.package.empty()) {
- Logger::error() << "no package name specified." << std::endl;
- return false;
+ if (options.appInfo.package.empty()) {
+ Logger::error() << "no package name specified." << std::endl;
+ return false;
+ }
}
// Every phase needs a resource table.
std::shared_ptr<ResourceTable> table = std::make_shared<ResourceTable>();
+
+ // The package name is empty when in the compile phase.
table->setPackage(options.appInfo.package);
if (options.appInfo.package == u"android") {
table->setPackageId(0x01);
diff --git a/tools/aapt2/TableFlattener.cpp b/tools/aapt2/TableFlattener.cpp
index 539c48f..b7c04f0 100644
--- a/tools/aapt2/TableFlattener.cpp
+++ b/tools/aapt2/TableFlattener.cpp
@@ -79,7 +79,7 @@
// Write the key.
if (!Res_INTERNALID(key.id.id) && !key.id.isValid()) {
- assert(key.name.isValid());
+ assert(!key.name.entry.empty());
mSymbols->push_back(std::make_pair(ResourceNameRef(key.name),
mOut->size() - sizeof(*outMapEntry)));
}
@@ -284,13 +284,6 @@
bool TableFlattener::flatten(BigBuffer* out, const ResourceTable& table) {
const size_t beginning = out->size();
- if (table.getPackage().size() == 0) {
- Logger::error()
- << "ResourceTable has no package name."
- << std::endl;
- return false;
- }
-
if (table.getPackageId() == ResourceTable::kUnsetPackageId) {
Logger::error()
<< "ResourceTable has no package ID set."
diff --git a/tools/aapt2/data/Makefile b/tools/aapt2/data/Makefile
index 3387135..91ff5fe 100644
--- a/tools/aapt2/data/Makefile
+++ b/tools/aapt2/data/Makefile
@@ -50,7 +50,7 @@
# returns: out/values-v4.apk: res/values-v4/styles.xml res/values-v4/colors.xml
define make-collect-rule
$(LOCAL_OUT)/$1.apk: $(filter $(LOCAL_RESOURCE_DIR)/$1/%,$(PRIVATE_RESOURCES))
- $(AAPT) compile --package $(LOCAL_PACKAGE) -o $$@ $$^
+ $(AAPT) compile -o $$@ $$^
endef
# Collect: out/values-v4.apk <- res/values-v4/styles.xml res/values-v4/colors.xml
diff --git a/tools/aapt2/data/lib/Makefile b/tools/aapt2/data/lib/Makefile
index 372c225..741be9a 100644
--- a/tools/aapt2/data/lib/Makefile
+++ b/tools/aapt2/data/lib/Makefile
@@ -48,7 +48,7 @@
# returns: out/values-v4.apk: res/values-v4/styles.xml res/values-v4/colors.xml
define make-collect-rule
$(LOCAL_OUT)/$1.apk: $(filter $(LOCAL_RESOURCE_DIR)/$1/%,$(PRIVATE_RESOURCES))
- $(AAPT) compile --package $(LOCAL_PACKAGE) -o $$@ $$^
+ $(AAPT) compile -o $$@ $$^
endef
# Collect: out/values-v4.apk <- res/values-v4/styles.xml res/values-v4/colors.xml
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 6be5a95..422b2aa 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -1506,6 +1506,12 @@
}
@Override
+ public void sendBroadcast(Intent arg0, String arg1, Bundle arg2) {
+ // pass
+
+ }
+
+ @Override
public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
// pass
}
@@ -1525,6 +1531,14 @@
}
@Override
+ public void sendOrderedBroadcast(Intent arg0, String arg1,
+ Bundle arg7, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5,
+ Bundle arg6) {
+ // pass
+
+ }
+
+ @Override
public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp,
BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
String initialData, Bundle initialExtras) {