Merge "Fix error in width of nanoAppId"
diff --git a/api/current.txt b/api/current.txt
index d68610e..6a62fde 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -609,7 +609,7 @@
field public static final int fontProviderAuthority = 16844114; // 0x1010552
field public static final int fontProviderPackage = 16844122; // 0x101055a
field public static final int fontProviderQuery = 16844115; // 0x1010553
- field public static final int fontStyle = 16844081; // 0x1010531
+ field public static final int fontStyle = 16844095; // 0x101053f
field public static final int fontWeight = 16844083; // 0x1010533
field public static final int footerDividersEnabled = 16843311; // 0x101022f
field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521
@@ -710,6 +710,7 @@
field public static final int imeSubtypeMode = 16843501; // 0x10102ed
field public static final int immersive = 16843456; // 0x10102c0
field public static final int importantForAccessibility = 16843690; // 0x10103aa
+ field public static final int importantForAutofill = 16844123; // 0x101055b
field public static final int inAnimation = 16843127; // 0x1010177
field public static final int includeFontPadding = 16843103; // 0x101015f
field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -1460,7 +1461,7 @@
field public static final int viewportWidth = 16843778; // 0x1010402
field public static final int visibility = 16842972; // 0x10100dc
field public static final int visible = 16843156; // 0x1010194
- field public static final int visibleToInstantApps = 16844095; // 0x101053f
+ field public static final int visibleToInstantApps = 16844081; // 0x1010531
field public static final int vmSafeMode = 16843448; // 0x10102b8
field public static final int voiceIcon = 16843908; // 0x1010484
field public static final int voiceLanguage = 16843349; // 0x1010255
@@ -6562,8 +6563,9 @@
method public int getAutoFillHint();
method public android.view.autofill.AutoFillId getAutoFillId();
method public java.lang.String[] getAutoFillOptions();
- method public android.view.autofill.AutoFillType getAutoFillType();
+ method public deprecated android.view.autofill.AutoFillType getAutoFillType();
method public android.view.autofill.AutoFillValue getAutoFillValue();
+ method public int getAutofillType();
method public android.app.assist.AssistStructure.ViewNode getChildAt(int);
method public int getChildCount();
method public java.lang.String getClassName();
@@ -10703,7 +10705,7 @@
ctor public PackageManager.NameNotFoundException(java.lang.String);
}
- public class PackageStats implements android.os.Parcelable {
+ public deprecated class PackageStats implements android.os.Parcelable {
ctor public PackageStats(java.lang.String);
ctor public PackageStats(android.os.Parcel);
ctor public PackageStats(android.content.pm.PackageStats);
@@ -43586,6 +43588,7 @@
field public static final int STATE_OFF = 1; // 0x1
field public static final int STATE_ON = 2; // 0x2
field public static final int STATE_UNKNOWN = 0; // 0x0
+ field public static final int STATE_VR = 5; // 0x5
}
public static final class Display.HdrCapabilities implements android.os.Parcelable {
@@ -45051,8 +45054,9 @@
method public android.os.IBinder getApplicationWindowToken();
method public int getAutoFillHint();
method public int getAutoFillMode();
- method public android.view.autofill.AutoFillType getAutoFillType();
+ method public final deprecated android.view.autofill.AutoFillType getAutoFillType();
method public android.view.autofill.AutoFillValue getAutoFillValue();
+ method public int getAutofillType();
method public android.graphics.drawable.Drawable getBackground();
method public android.content.res.ColorStateList getBackgroundTintList();
method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -45096,6 +45100,7 @@
method protected int getHorizontalScrollbarHeight();
method public int getId();
method public int getImportantForAccessibility();
+ method public int getImportantForAutofill();
method public boolean getKeepScreenOn();
method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
method public int getLabelFor();
@@ -45225,6 +45230,7 @@
method public boolean isHorizontalScrollBarEnabled();
method public boolean isHovered();
method public boolean isImportantForAccessibility();
+ method public final boolean isImportantForAutofill();
method public boolean isInEditMode();
method public boolean isInLayout();
method public boolean isInTouchMode();
@@ -45407,6 +45413,7 @@
method public void setHovered(boolean);
method public void setId(int);
method public void setImportantForAccessibility(int);
+ method public void setImportantForAutofill(int);
method public void setKeepScreenOn(boolean);
method public void setKeyboardNavigationCluster(boolean);
method public void setLabelFor(int);
@@ -45510,6 +45517,11 @@
field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
+ field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
+ field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
+ field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
+ field public static final int AUTOFILL_TYPE_TEXT = 1; // 0x1
+ field public static final int AUTOFILL_TYPE_TOGGLE = 2; // 0x2
field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DATE = 512; // 0x200
field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DAY = 4096; // 0x1000
field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = 1024; // 0x400
@@ -45567,6 +45579,9 @@
field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 2; // 0x2
field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 4; // 0x4
field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
+ field public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0; // 0x0
+ field public static final int IMPORTANT_FOR_AUTOFILL_NO = 2; // 0x2
+ field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
field public static final int INVISIBLE = 4; // 0x4
field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
@@ -46179,8 +46194,9 @@
method public abstract void setAlpha(float);
method public abstract void setAutoFillHint(int);
method public abstract void setAutoFillOptions(java.lang.String[]);
- method public abstract void setAutoFillType(android.view.autofill.AutoFillType);
+ method public abstract deprecated void setAutoFillType(android.view.autofill.AutoFillType);
method public abstract void setAutoFillValue(android.view.autofill.AutoFillValue);
+ method public abstract void setAutofillType(int);
method public abstract void setCheckable(boolean);
method public abstract void setChecked(boolean);
method public abstract void setChildCount(int);
@@ -47436,17 +47452,27 @@
}
public final class AutoFillManager {
+ method public void registerCallback(android.view.autofill.AutoFillManager.AutofillCallback);
method public void reset();
method public void startAutoFillRequest(android.view.View);
method public void startAutoFillRequestOnVirtualView(android.view.View, int, android.graphics.Rect);
method public void stopAutoFillRequest(android.view.View);
method public void stopAutoFillRequestOnVirtualView(android.view.View, int);
+ method public void unregisterCallback(android.view.autofill.AutoFillManager.AutofillCallback);
method public void valueChanged(android.view.View);
method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue);
field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
}
+ public static abstract class AutoFillManager.AutofillCallback {
+ ctor public AutoFillManager.AutofillCallback();
+ method public void onAutofillEvent(android.view.View, int);
+ method public void onAutofillEventVirtual(android.view.View, int, int);
+ field public static final int EVENT_INPUT_HIDDEN = 2; // 0x2
+ field public static final int EVENT_INPUT_SHOWN = 1; // 0x1
+ }
+
public final class AutoFillType implements android.os.Parcelable {
method public int describeContents();
method public static android.view.autofill.AutoFillType forDate();
@@ -47911,9 +47937,9 @@
}
public abstract interface TextClassifier {
- method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
- method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
- method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+ method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int, android.os.LocaleList);
+ method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int, android.os.LocaleList);
+ method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.os.LocaleList);
field public static final android.view.textclassifier.TextClassifier NO_OP;
field public static final java.lang.String TYPE_ADDRESS = "address";
field public static final java.lang.String TYPE_EMAIL = "email";
diff --git a/api/removed.txt b/api/removed.txt
index c5dbf8d..148f3f1 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -369,6 +369,16 @@
}
+package android.view.textclassifier {
+
+ public abstract interface TextClassifier {
+ method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
+ method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
+ method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+ }
+
+}
+
package android.webkit {
public class WebViewClient {
diff --git a/api/system-current.txt b/api/system-current.txt
index 48f8ce5..339f40b 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -721,7 +721,7 @@
field public static final int fontProviderAuthority = 16844114; // 0x1010552
field public static final int fontProviderPackage = 16844122; // 0x101055a
field public static final int fontProviderQuery = 16844115; // 0x1010553
- field public static final int fontStyle = 16844081; // 0x1010531
+ field public static final int fontStyle = 16844095; // 0x101053f
field public static final int fontWeight = 16844083; // 0x1010533
field public static final int footerDividersEnabled = 16843311; // 0x101022f
field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521
@@ -822,6 +822,7 @@
field public static final int imeSubtypeMode = 16843501; // 0x10102ed
field public static final int immersive = 16843456; // 0x10102c0
field public static final int importantForAccessibility = 16843690; // 0x10103aa
+ field public static final int importantForAutofill = 16844123; // 0x101055b
field public static final int inAnimation = 16843127; // 0x1010177
field public static final int includeFontPadding = 16843103; // 0x101015f
field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -1576,7 +1577,7 @@
field public static final int viewportWidth = 16843778; // 0x1010402
field public static final int visibility = 16842972; // 0x10100dc
field public static final int visible = 16843156; // 0x1010194
- field public static final int visibleToInstantApps = 16844095; // 0x101053f
+ field public static final int visibleToInstantApps = 16844081; // 0x1010531
field public static final int vmSafeMode = 16843448; // 0x10102b8
field public static final int voiceIcon = 16843908; // 0x1010484
field public static final int voiceLanguage = 16843349; // 0x1010255
@@ -6811,8 +6812,9 @@
method public int getAutoFillHint();
method public android.view.autofill.AutoFillId getAutoFillId();
method public java.lang.String[] getAutoFillOptions();
- method public android.view.autofill.AutoFillType getAutoFillType();
+ method public deprecated android.view.autofill.AutoFillType getAutoFillType();
method public android.view.autofill.AutoFillValue getAutoFillValue();
+ method public int getAutofillType();
method public android.app.assist.AssistStructure.ViewNode getChildAt(int);
method public int getChildCount();
method public java.lang.String getClassName();
@@ -11423,7 +11425,7 @@
public static abstract class PackageManager.PermissionFlags implements java.lang.annotation.Annotation {
}
- public class PackageStats implements android.os.Parcelable {
+ public deprecated class PackageStats implements android.os.Parcelable {
ctor public PackageStats(java.lang.String);
ctor public PackageStats(android.os.Parcel);
ctor public PackageStats(android.content.pm.PackageStats);
@@ -16491,6 +16493,7 @@
method public android.hardware.hdmi.HdmiPlaybackClient getPlaybackClient();
method public android.hardware.hdmi.HdmiTvClient getTvClient();
method public void removeHotplugEventListener(android.hardware.hdmi.HdmiControlManager.HotplugEventListener);
+ method public void setStandbyMode(boolean);
field public static final java.lang.String ACTION_OSD_MESSAGE = "android.hardware.hdmi.action.OSD_MESSAGE";
field public static final int AVR_VOLUME_MUTED = 101; // 0x65
field public static final int CLEAR_TIMER_STATUS_CEC_DISABLE = 162; // 0xa2
@@ -47047,6 +47050,7 @@
field public static final int STATE_OFF = 1; // 0x1
field public static final int STATE_ON = 2; // 0x2
field public static final int STATE_UNKNOWN = 0; // 0x0
+ field public static final int STATE_VR = 5; // 0x5
}
public static final class Display.HdrCapabilities implements android.os.Parcelable {
@@ -48512,8 +48516,9 @@
method public android.os.IBinder getApplicationWindowToken();
method public int getAutoFillHint();
method public int getAutoFillMode();
- method public android.view.autofill.AutoFillType getAutoFillType();
+ method public final deprecated android.view.autofill.AutoFillType getAutoFillType();
method public android.view.autofill.AutoFillValue getAutoFillValue();
+ method public int getAutofillType();
method public android.graphics.drawable.Drawable getBackground();
method public android.content.res.ColorStateList getBackgroundTintList();
method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -48557,6 +48562,7 @@
method protected int getHorizontalScrollbarHeight();
method public int getId();
method public int getImportantForAccessibility();
+ method public int getImportantForAutofill();
method public boolean getKeepScreenOn();
method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
method public int getLabelFor();
@@ -48686,6 +48692,7 @@
method public boolean isHorizontalScrollBarEnabled();
method public boolean isHovered();
method public boolean isImportantForAccessibility();
+ method public final boolean isImportantForAutofill();
method public boolean isInEditMode();
method public boolean isInLayout();
method public boolean isInTouchMode();
@@ -48868,6 +48875,7 @@
method public void setHovered(boolean);
method public void setId(int);
method public void setImportantForAccessibility(int);
+ method public void setImportantForAutofill(int);
method public void setKeepScreenOn(boolean);
method public void setKeyboardNavigationCluster(boolean);
method public void setLabelFor(int);
@@ -48971,6 +48979,11 @@
field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
+ field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
+ field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
+ field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
+ field public static final int AUTOFILL_TYPE_TEXT = 1; // 0x1
+ field public static final int AUTOFILL_TYPE_TOGGLE = 2; // 0x2
field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DATE = 512; // 0x200
field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DAY = 4096; // 0x1000
field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = 1024; // 0x400
@@ -49028,6 +49041,9 @@
field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 2; // 0x2
field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 4; // 0x4
field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
+ field public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0; // 0x0
+ field public static final int IMPORTANT_FOR_AUTOFILL_NO = 2; // 0x2
+ field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
field public static final int INVISIBLE = 4; // 0x4
field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
@@ -49640,8 +49656,9 @@
method public abstract void setAlpha(float);
method public abstract void setAutoFillHint(int);
method public abstract void setAutoFillOptions(java.lang.String[]);
- method public abstract void setAutoFillType(android.view.autofill.AutoFillType);
+ method public abstract deprecated void setAutoFillType(android.view.autofill.AutoFillType);
method public abstract void setAutoFillValue(android.view.autofill.AutoFillValue);
+ method public abstract void setAutofillType(int);
method public abstract void setCheckable(boolean);
method public abstract void setChecked(boolean);
method public abstract void setChildCount(int);
@@ -50900,17 +50917,27 @@
}
public final class AutoFillManager {
+ method public void registerCallback(android.view.autofill.AutoFillManager.AutofillCallback);
method public void reset();
method public void startAutoFillRequest(android.view.View);
method public void startAutoFillRequestOnVirtualView(android.view.View, int, android.graphics.Rect);
method public void stopAutoFillRequest(android.view.View);
method public void stopAutoFillRequestOnVirtualView(android.view.View, int);
+ method public void unregisterCallback(android.view.autofill.AutoFillManager.AutofillCallback);
method public void valueChanged(android.view.View);
method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue);
field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
}
+ public static abstract class AutoFillManager.AutofillCallback {
+ ctor public AutoFillManager.AutofillCallback();
+ method public void onAutofillEvent(android.view.View, int);
+ method public void onAutofillEventVirtual(android.view.View, int, int);
+ field public static final int EVENT_INPUT_HIDDEN = 2; // 0x2
+ field public static final int EVENT_INPUT_SHOWN = 1; // 0x1
+ }
+
public final class AutoFillType implements android.os.Parcelable {
method public int describeContents();
method public static android.view.autofill.AutoFillType forDate();
@@ -51375,9 +51402,9 @@
}
public abstract interface TextClassifier {
- method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
- method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
- method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+ method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int, android.os.LocaleList);
+ method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int, android.os.LocaleList);
+ method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.os.LocaleList);
field public static final android.view.textclassifier.TextClassifier NO_OP;
field public static final java.lang.String TYPE_ADDRESS = "address";
field public static final java.lang.String TYPE_EMAIL = "email";
diff --git a/api/system-removed.txt b/api/system-removed.txt
index a3093e2..bd535d2 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -363,6 +363,16 @@
}
+package android.view.textclassifier {
+
+ public abstract interface TextClassifier {
+ method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
+ method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
+ method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+ }
+
+}
+
package android.webkit {
public class WebViewClient {
diff --git a/api/test-current.txt b/api/test-current.txt
index f8e6785..fc96532 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -609,7 +609,7 @@
field public static final int fontProviderAuthority = 16844114; // 0x1010552
field public static final int fontProviderPackage = 16844122; // 0x101055a
field public static final int fontProviderQuery = 16844115; // 0x1010553
- field public static final int fontStyle = 16844081; // 0x1010531
+ field public static final int fontStyle = 16844095; // 0x101053f
field public static final int fontWeight = 16844083; // 0x1010533
field public static final int footerDividersEnabled = 16843311; // 0x101022f
field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521
@@ -710,6 +710,7 @@
field public static final int imeSubtypeMode = 16843501; // 0x10102ed
field public static final int immersive = 16843456; // 0x10102c0
field public static final int importantForAccessibility = 16843690; // 0x10103aa
+ field public static final int importantForAutofill = 16844123; // 0x101055b
field public static final int inAnimation = 16843127; // 0x1010177
field public static final int includeFontPadding = 16843103; // 0x101015f
field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -1460,7 +1461,7 @@
field public static final int viewportWidth = 16843778; // 0x1010402
field public static final int visibility = 16842972; // 0x10100dc
field public static final int visible = 16843156; // 0x1010194
- field public static final int visibleToInstantApps = 16844095; // 0x101053f
+ field public static final int visibleToInstantApps = 16844081; // 0x1010531
field public static final int vmSafeMode = 16843448; // 0x10102b8
field public static final int voiceIcon = 16843908; // 0x1010484
field public static final int voiceLanguage = 16843349; // 0x1010255
@@ -6589,8 +6590,9 @@
method public int getAutoFillHint();
method public android.view.autofill.AutoFillId getAutoFillId();
method public java.lang.String[] getAutoFillOptions();
- method public android.view.autofill.AutoFillType getAutoFillType();
+ method public deprecated android.view.autofill.AutoFillType getAutoFillType();
method public android.view.autofill.AutoFillValue getAutoFillValue();
+ method public int getAutofillType();
method public android.app.assist.AssistStructure.ViewNode getChildAt(int);
method public int getChildCount();
method public java.lang.String getClassName();
@@ -10739,7 +10741,7 @@
ctor public PackageManager.NameNotFoundException(java.lang.String);
}
- public class PackageStats implements android.os.Parcelable {
+ public deprecated class PackageStats implements android.os.Parcelable {
ctor public PackageStats(java.lang.String);
ctor public PackageStats(android.os.Parcel);
ctor public PackageStats(android.content.pm.PackageStats);
@@ -43944,6 +43946,7 @@
field public static final int STATE_OFF = 1; // 0x1
field public static final int STATE_ON = 2; // 0x2
field public static final int STATE_UNKNOWN = 0; // 0x0
+ field public static final int STATE_VR = 5; // 0x5
}
public static final class Display.HdrCapabilities implements android.os.Parcelable {
@@ -45411,8 +45414,9 @@
method public android.os.IBinder getApplicationWindowToken();
method public int getAutoFillHint();
method public int getAutoFillMode();
- method public android.view.autofill.AutoFillType getAutoFillType();
+ method public final deprecated android.view.autofill.AutoFillType getAutoFillType();
method public android.view.autofill.AutoFillValue getAutoFillValue();
+ method public int getAutofillType();
method public android.graphics.drawable.Drawable getBackground();
method public android.content.res.ColorStateList getBackgroundTintList();
method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -45456,6 +45460,7 @@
method protected int getHorizontalScrollbarHeight();
method public int getId();
method public int getImportantForAccessibility();
+ method public int getImportantForAutofill();
method public boolean getKeepScreenOn();
method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
method public int getLabelFor();
@@ -45586,6 +45591,7 @@
method public boolean isHorizontalScrollBarEnabled();
method public boolean isHovered();
method public boolean isImportantForAccessibility();
+ method public final boolean isImportantForAutofill();
method public boolean isInEditMode();
method public boolean isInLayout();
method public boolean isInTouchMode();
@@ -45770,6 +45776,7 @@
method public void setHovered(boolean);
method public void setId(int);
method public void setImportantForAccessibility(int);
+ method public void setImportantForAutofill(int);
method public void setKeepScreenOn(boolean);
method public void setKeyboardNavigationCluster(boolean);
method public void setLabelFor(int);
@@ -45873,6 +45880,11 @@
field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
+ field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
+ field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
+ field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
+ field public static final int AUTOFILL_TYPE_TEXT = 1; // 0x1
+ field public static final int AUTOFILL_TYPE_TOGGLE = 2; // 0x2
field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DATE = 512; // 0x200
field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DAY = 4096; // 0x1000
field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = 1024; // 0x400
@@ -45930,6 +45942,9 @@
field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 2; // 0x2
field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 4; // 0x4
field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
+ field public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0; // 0x0
+ field public static final int IMPORTANT_FOR_AUTOFILL_NO = 2; // 0x2
+ field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
field public static final int INVISIBLE = 4; // 0x4
field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
@@ -46546,8 +46561,9 @@
method public abstract void setAlpha(float);
method public abstract void setAutoFillHint(int);
method public abstract void setAutoFillOptions(java.lang.String[]);
- method public abstract void setAutoFillType(android.view.autofill.AutoFillType);
+ method public abstract deprecated void setAutoFillType(android.view.autofill.AutoFillType);
method public abstract void setAutoFillValue(android.view.autofill.AutoFillValue);
+ method public abstract void setAutofillType(int);
method public abstract void setCheckable(boolean);
method public abstract void setChecked(boolean);
method public abstract void setChildCount(int);
@@ -47805,17 +47821,27 @@
}
public final class AutoFillManager {
+ method public void registerCallback(android.view.autofill.AutoFillManager.AutofillCallback);
method public void reset();
method public void startAutoFillRequest(android.view.View);
method public void startAutoFillRequestOnVirtualView(android.view.View, int, android.graphics.Rect);
method public void stopAutoFillRequest(android.view.View);
method public void stopAutoFillRequestOnVirtualView(android.view.View, int);
+ method public void unregisterCallback(android.view.autofill.AutoFillManager.AutofillCallback);
method public void valueChanged(android.view.View);
method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue);
field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
}
+ public static abstract class AutoFillManager.AutofillCallback {
+ ctor public AutoFillManager.AutofillCallback();
+ method public void onAutofillEvent(android.view.View, int);
+ method public void onAutofillEventVirtual(android.view.View, int, int);
+ field public static final int EVENT_INPUT_HIDDEN = 2; // 0x2
+ field public static final int EVENT_INPUT_SHOWN = 1; // 0x1
+ }
+
public final class AutoFillType implements android.os.Parcelable {
method public int describeContents();
method public static android.view.autofill.AutoFillType forDate();
@@ -48280,9 +48306,9 @@
}
public abstract interface TextClassifier {
- method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
- method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
- method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+ method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int, android.os.LocaleList);
+ method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int, android.os.LocaleList);
+ method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.os.LocaleList);
field public static final android.view.textclassifier.TextClassifier NO_OP;
field public static final java.lang.String TYPE_ADDRESS = "address";
field public static final java.lang.String TYPE_EMAIL = "email";
diff --git a/api/test-removed.txt b/api/test-removed.txt
index c5dbf8d..148f3f1 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -369,6 +369,16 @@
}
+package android.view.textclassifier {
+
+ public abstract interface TextClassifier {
+ method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
+ method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
+ method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+ }
+
+}
+
package android.webkit {
public class WebViewClient {
diff --git a/cmds/uiautomator/library/Android.mk b/cmds/uiautomator/library/Android.mk
index f932388..e70bd11 100644
--- a/cmds/uiautomator/library/Android.mk
+++ b/cmds/uiautomator/library/Android.mk
@@ -49,7 +49,7 @@
-api $(uiautomator_internal_api_file) \
-removedApi $(uiautomator_internal_removed_api_file)
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR := build/tools/droiddoc/templates-sdk
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR := external/doclava/res/assets/templates-sdk
LOCAL_UNINSTALLABLE_MODULE := true
LOCAL_MODULE := uiautomator-stubs
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 8e0098f..2e0ca02 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -538,7 +538,7 @@
// TODO(b/33197203): once we have more flags, it might be better to store the individual
// fields (viewId and childId) of the field.
AutoFillId mAutoFillId;
- AutoFillType mAutoFillType;
+ @View.AutofillType int mAutofillType;
@View.AutoFillHint int mAutoFillHint;
AutoFillValue mAutoFillValue;
String[] mAutoFillOptions;
@@ -623,7 +623,7 @@
if ((flags&FLAGS_HAS_AUTO_FILL_DATA) != 0) {
mSanitized = in.readInt() == 1;
mAutoFillId = in.readParcelable(null);
- mAutoFillType = in.readParcelable(null);
+ mAutofillType = in.readInt();
mAutoFillHint = in.readInt();
mAutoFillValue = in.readParcelable(null);
mAutoFillOptions = in.readStringArray();
@@ -757,7 +757,7 @@
writeSensitive = mSanitized || !sanitizeOnWrite;
out.writeInt(mSanitized ? 1 : 0);
out.writeParcelable(mAutoFillId, 0);
- out.writeParcelable(mAutoFillType, 0);
+ out.writeInt(mAutofillType);
out.writeInt(mAutoFillHint);
final AutoFillValue sanitizedValue = writeSensitive ? mAutoFillValue : null;
out.writeParcelable(sanitizedValue, 0);
@@ -851,14 +851,32 @@
}
/**
+ * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype()
+ */
+ @Deprecated
+ public AutoFillType getAutoFillType() {
+ switch (getAutofillType()) {
+ case View.AUTOFILL_TYPE_TEXT:
+ return AutoFillType.forText();
+ case View.AUTOFILL_TYPE_TOGGLE:
+ return AutoFillType.forToggle();
+ case View.AUTOFILL_TYPE_LIST:
+ return AutoFillType.forList();
+ case View.AUTOFILL_TYPE_DATE:
+ return AutoFillType.forDate();
+ default:
+ return null;
+ }
+ }
+
+ /**
* Gets the the type of value that can be used to auto-fill the view contents.
*
* <p>It's only set when the {@link AssistStructure} is used for auto-filling purposes, not
* for assist.
*/
- // TODO(b/33197203, b/33802548): add CTS/unit test
- public AutoFillType getAutoFillType() {
- return mAutoFillType;
+ public @View.AutofillType int getAutofillType() {
+ return mAutofillType;
}
/**
@@ -1562,7 +1580,22 @@
@Override
public void setAutoFillType(AutoFillType type) {
- mNode.mAutoFillType = type;
+ if (type == null) return;
+
+ if (type.isText()) {
+ mNode.mAutofillType = View.AUTOFILL_TYPE_TEXT;
+ } else if (type.isToggle()) {
+ mNode.mAutofillType = View.AUTOFILL_TYPE_TOGGLE;
+ } else if (type.isList()) {
+ mNode.mAutofillType = View.AUTOFILL_TYPE_LIST;
+ } else if (type.isDate()) {
+ mNode.mAutofillType = View.AUTOFILL_TYPE_DATE;
+ }
+ }
+
+ @Override
+ public void setAutofillType(@View.AutofillType int type) {
+ mNode.mAutofillType = type;
}
@Override
@@ -1711,7 +1744,7 @@
Log.i(TAG, prefix + " NO AUTO-FILL ID");
} else {
Log.i(TAG, prefix + "AutoFill info: id= " + autoFillId
- + ", type=" + node.getAutoFillType()
+ + ", type=" + node.getAutofillType()
+ ", options=" + Arrays.toString(node.getAutoFillOptions())
+ ", inputType=" + node.getInputType()
+ ", hint=" + Integer.toHexString(node.getAutoFillHint())
diff --git a/core/java/android/content/AsyncTaskLoader.java b/core/java/android/content/AsyncTaskLoader.java
index 7241e0d..b7545bf 100644
--- a/core/java/android/content/AsyncTaskLoader.java
+++ b/core/java/android/content/AsyncTaskLoader.java
@@ -170,6 +170,9 @@
protected boolean onCancelLoad() {
if (DEBUG) Log.v(TAG, "onCancelLoad: mTask=" + mTask);
if (mTask != null) {
+ if (!mStarted) {
+ mContentChanged = true;
+ }
if (mCancellingTask != null) {
// There was a pending task already waiting for a previous
// one being canceled; just drop it.
diff --git a/core/java/android/content/om/IOverlayManager.aidl b/core/java/android/content/om/IOverlayManager.aidl
index 4f5d960..86c1aa8 100644
--- a/core/java/android/content/om/IOverlayManager.aidl
+++ b/core/java/android/content/om/IOverlayManager.aidl
@@ -89,6 +89,11 @@
boolean setEnabled(in String packageName, in boolean enable, in int userId);
/**
+ * Version of setEnabled that will also disable any other overlays for the target package.
+ */
+ boolean setEnabledExclusive(in String packageName, in boolean enable, in int userId);
+
+ /**
* Change the priority of the given overlay to be just higher than the
* overlay with package name newParentPackageName. Both overlay packages
* must have the same target and user.
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 664e76b..3a875bc 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -34,6 +34,7 @@
import android.app.PackageDeleteObserver;
import android.app.PackageInstallObserver;
import android.app.admin.DevicePolicyManager;
+import android.app.usage.StorageStatsManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -5466,8 +5467,10 @@
* the status of the operation. observer may be null to indicate that
* no callback is desired.
*
+ * @deprecated use {@link StorageStatsManager} instead.
* @hide
*/
+ @Deprecated
public abstract void getPackageSizeInfoAsUser(String packageName, @UserIdInt int userId,
IPackageStatsObserver observer);
@@ -5475,8 +5478,10 @@
* Like {@link #getPackageSizeInfoAsUser(String, int, IPackageStatsObserver)}, but
* returns the size for the calling user.
*
+ * @deprecated use {@link StorageStatsManager} instead.
* @hide
*/
+ @Deprecated
public void getPackageSizeInfo(String packageName, IPackageStatsObserver observer) {
getPackageSizeInfoAsUser(packageName, UserHandle.myUserId(), observer);
}
diff --git a/core/java/android/content/pm/PackageStats.java b/core/java/android/content/pm/PackageStats.java
index c746af4..27b3506 100644
--- a/core/java/android/content/pm/PackageStats.java
+++ b/core/java/android/content/pm/PackageStats.java
@@ -16,6 +16,7 @@
package android.content.pm;
+import android.app.usage.StorageStatsManager;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
@@ -24,9 +25,13 @@
import java.util.Objects;
/**
- * implementation of PackageStats associated with a
- * application package.
+ * implementation of PackageStats associated with a application package.
+ *
+ * @deprecated this class is an orphan that could never be obtained from a valid
+ * public API. If you need package storage statistics use the new
+ * {@link StorageStatsManager} APIs.
*/
+@Deprecated
public class PackageStats implements Parcelable {
/** Name of the package to which this stats applies. */
public String packageName;
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 493ed8c..7bfb5d0 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -731,7 +731,7 @@
@SystemApi
@TestApi
public static final int SESSION_OPERATION_MODE_NORMAL =
- ICameraDeviceUser.NORMAL_MODE;
+ 0; // ICameraDeviceUser.NORMAL_MODE;
/**
* Constrained high-speed operation mode.
@@ -742,7 +742,7 @@
@SystemApi
@TestApi
public static final int SESSION_OPERATION_MODE_CONSTRAINED_HIGH_SPEED =
- ICameraDeviceUser.CONSTRAINED_HIGH_SPEED_MODE;
+ 1; // ICameraDeviceUser.CONSTRAINED_HIGH_SPEED_MODE;
/**
* First vendor-specific operating mode
@@ -753,7 +753,7 @@
@SystemApi
@TestApi
public static final int SESSION_OPERATION_MODE_VENDOR_START =
- ICameraDeviceUser.VENDOR_MODE_START;
+ 0x8000; // ICameraDeviceUser.VENDOR_MODE_START;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 98a5749..b276008 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -213,6 +213,10 @@
// If true, scales the brightness to half of desired.
public boolean lowPowerMode;
+ // The factor to adjust the screen brightness in low power mode in the range
+ // 0 (screen off) to 1 (no change)
+ public float screenLowPowerBrightnessFactor;
+
// If true, applies a brightness boost.
public boolean boostScreenBrightness;
@@ -235,6 +239,7 @@
useProximitySensor = false;
screenBrightness = PowerManager.BRIGHTNESS_ON;
screenAutoBrightnessAdjustment = 0.0f;
+ screenLowPowerBrightnessFactor = 0.5f;
useAutoBrightness = false;
blockScreenOn = false;
dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
@@ -258,6 +263,7 @@
useProximitySensor = other.useProximitySensor;
screenBrightness = other.screenBrightness;
screenAutoBrightnessAdjustment = other.screenAutoBrightnessAdjustment;
+ screenLowPowerBrightnessFactor = other.screenLowPowerBrightnessFactor;
brightnessSetByUser = other.brightnessSetByUser;
useAutoBrightness = other.useAutoBrightness;
blockScreenOn = other.blockScreenOn;
@@ -279,6 +285,8 @@
&& useProximitySensor == other.useProximitySensor
&& screenBrightness == other.screenBrightness
&& screenAutoBrightnessAdjustment == other.screenAutoBrightnessAdjustment
+ && screenLowPowerBrightnessFactor
+ == other.screenLowPowerBrightnessFactor
&& brightnessSetByUser == other.brightnessSetByUser
&& useAutoBrightness == other.useAutoBrightness
&& blockScreenOn == other.blockScreenOn
@@ -299,6 +307,7 @@
+ ", useProximitySensor=" + useProximitySensor
+ ", screenBrightness=" + screenBrightness
+ ", screenAutoBrightnessAdjustment=" + screenAutoBrightnessAdjustment
+ + ", screenLowPowerBrightnessFactor=" + screenLowPowerBrightnessFactor
+ ", brightnessSetByUser=" + brightnessSetByUser
+ ", useAutoBrightness=" + useAutoBrightness
+ ", blockScreenOn=" + blockScreenOn
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index ff87b67..27e2a50 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -338,6 +338,20 @@
}
/**
+ * Controls standby mode of the system. It will also try to turn on/off the connected devices if
+ * necessary.
+ *
+ * @param isStandbyModeOn target status of the system's standby mode
+ */
+ public void setStandbyMode(boolean isStandbyModeOn) {
+ try {
+ mService.setStandbyMode(isStandbyModeOn);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Listener used to get hotplug event from HDMI port.
*/
public interface HotplugEventListener {
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index c1e924e..67e2d18 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -71,4 +71,5 @@
void clearTimerRecording(int recorderAddress, int sourceType, in byte[] recordSource);
void sendMhlVendorCommand(int portId, int offset, int length, in byte[] data);
void addHdmiMhlVendorCommandListener(IHdmiMhlVendorCommandListener listener);
+ void setStandbyMode(boolean isStandbyModeOn);
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index d50a838..dc170ed 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2410,6 +2410,10 @@
// Step duration mode: the screen is on, off, dozed, etc; value is Display.STATE_* - 1.
public static final int STEP_LEVEL_MODE_SCREEN_STATE = 0x03;
+ // The largest value for screen state that is tracked in battery states. Any values above
+ // this should be mapped back to one of the tracked values before being tracked here.
+ public static final int MAX_TRACKED_SCREEN_STATE = Display.STATE_DOZE_SUSPEND;
+
// Step duration mode: power save is on.
public static final int STEP_LEVEL_MODE_POWER_SAVE = 0x04;
@@ -3137,8 +3141,8 @@
for (Map.Entry<String, ? extends Timer> ent : kernelWakelocks.entrySet()) {
sb.setLength(0);
printWakeLockCheckin(sb, ent.getValue(), rawRealtime, null, which, "");
- dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(),
- sb.toString());
+ dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA,
+ "\"" + ent.getKey() + "\"", sb.toString());
}
}
final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
@@ -3339,7 +3343,8 @@
final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
final int count = timer.getCountLocked(which);
if (totalTime != 0) {
- dumpLine(pw, uid, category, SYNC_DATA, syncs.keyAt(isy), totalTime, count);
+ dumpLine(pw, uid, category, SYNC_DATA, "\"" + syncs.keyAt(isy) + "\"",
+ totalTime, count);
}
}
@@ -3350,7 +3355,8 @@
final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
final int count = timer.getCountLocked(which);
if (totalTime != 0) {
- dumpLine(pw, uid, category, JOB_DATA, jobs.keyAt(ij), totalTime, count);
+ dumpLine(pw, uid, category, JOB_DATA, "\"" + jobs.keyAt(ij) + "\"",
+ totalTime, count);
}
}
@@ -3422,8 +3428,8 @@
if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0
|| starts != 0 || numAnrs != 0 || numCrashes != 0) {
- dumpLine(pw, uid, category, PROCESS_DATA, processStats.keyAt(ipr), userMillis,
- systemMillis, foregroundMillis, starts, numAnrs, numCrashes);
+ dumpLine(pw, uid, category, PROCESS_DATA, "\"" + processStats.keyAt(ipr) + "\"",
+ userMillis, systemMillis, foregroundMillis, starts, numAnrs, numCrashes);
}
}
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index af05ee7..50b4f8c 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -777,10 +777,15 @@
* "29.5GB" in UI.
*/
public static long roundStorageSize(long size) {
- long res = 1;
- while (res < size) {
- res <<= 1;
+ long val = 1;
+ long pow = 1;
+ while ((val * pow) < size) {
+ val <<= 1;
+ if (val > 512) {
+ val = 1;
+ pow *= 1000;
+ }
}
- return res;
+ return val * pow;
}
}
diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java
index e025494..b09c51c 100644
--- a/core/java/android/os/HwBinder.java
+++ b/core/java/android/os/HwBinder.java
@@ -43,9 +43,7 @@
int code, HwParcel request, HwParcel reply, int flags)
throws RemoteException;
- public native final void registerService(
- ArrayList<String> interfaceChain,
- String serviceName)
+ public native final void registerService(String serviceName)
throws RemoteException;
public static native final IHwBinder getService(
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 1d464c0..b715780 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -2,22 +2,23 @@
**
** Copyright 2007, 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
+** 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
+** 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
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
** limitations under the License.
*/
package android.os;
import android.os.WorkSource;
+import android.os.PowerSaveState;
/** @hide */
@@ -45,6 +46,7 @@
void nap(long time);
boolean isInteractive();
boolean isPowerSaveMode();
+ PowerSaveState getPowerSaveState(int serviceType);
boolean setPowerSaveMode(boolean mode);
boolean isDeviceIdleMode();
boolean isLightDeviceIdleMode();
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 31b3bc9..a713eef 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -971,6 +971,24 @@
}
/**
+ * Get data about the battery saver mode for a specific service
+ * @param serviceType unique key for the service, one of
+ * {@link com.android.server.power.BatterySaverPolicy.ServiceType}
+ * @return Battery saver state data.
+ *
+ * @hide
+ * @see com.android.server.power.BatterySaverPolicy
+ * @see PowerSaveState
+ */
+ public PowerSaveState getPowerSaveState(int serviceType) {
+ try {
+ return mService.getPowerSaveState(serviceType);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Returns true if the device is currently in idle mode. This happens when a device
* has been sitting unused and unmoving for a sufficiently long period of time, so that
* it decides to go into a lower power-use state. This may involve things like turning
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index d0db255..44addfc 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -131,12 +131,13 @@
public abstract void setDozeOverrideFromDreamManager(
int screenState, int screenBrightness);
- public abstract boolean getLowPowerModeEnabled();
+ public abstract PowerSaveState getLowPowerState(int serviceType);
public abstract void registerLowPowerModeObserver(LowPowerModeListener listener);
public interface LowPowerModeListener {
- public void onLowPowerModeChanged(boolean enabled);
+ int getServiceType();
+ void onLowPowerModeChanged(PowerSaveState state);
}
public abstract boolean setDeviceIdleMode(boolean enabled);
diff --git a/core/java/android/os/PowerSaveState.aidl b/core/java/android/os/PowerSaveState.aidl
new file mode 100644
index 0000000..e3f572d
--- /dev/null
+++ b/core/java/android/os/PowerSaveState.aidl
@@ -0,0 +1,19 @@
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.os;
+
+parcelable PowerSaveState;
\ No newline at end of file
diff --git a/core/java/android/os/PowerSaveState.java b/core/java/android/os/PowerSaveState.java
new file mode 100644
index 0000000..9269e76
--- /dev/null
+++ b/core/java/android/os/PowerSaveState.java
@@ -0,0 +1,95 @@
+/* Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package android.os;
+
+/**
+ * Data class for battery saver state. It contains the data
+ * <p>
+ * 1. Whether battery saver mode is enabled
+ * 2. Specific parameters to use in battery saver mode(i.e. screen brightness, gps mode)
+ *
+ * @hide
+ */
+public class PowerSaveState implements Parcelable {
+ public final boolean batterySaverEnabled;
+ public final int gpsMode;
+ public final float brightnessFactor;
+
+ public PowerSaveState(Builder builder) {
+ batterySaverEnabled = builder.mBatterySaverEnabled;
+ gpsMode = builder.mGpsMode;
+ brightnessFactor = builder.mBrightnessFactor;
+ }
+
+ public PowerSaveState(Parcel in) {
+ batterySaverEnabled = in.readByte() != 0;
+ gpsMode = in.readInt();
+ brightnessFactor = in.readFloat();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeByte((byte) (batterySaverEnabled ? 1 : 0));
+ dest.writeInt(gpsMode);
+ dest.writeFloat(brightnessFactor);
+ }
+
+ public static final class Builder {
+ private boolean mBatterySaverEnabled = false;
+ private int mGpsMode = 0;
+ private float mBrightnessFactor = 0.5f;
+
+ public Builder() {}
+
+ public Builder setBatterySaverEnabled(boolean enabled) {
+ mBatterySaverEnabled = enabled;
+ return this;
+ }
+
+ public Builder setGpsMode(int mode) {
+ mGpsMode = mode;
+ return this;
+ }
+
+ public Builder setBrightnessFactor(float factor) {
+ mBrightnessFactor = factor;
+ return this;
+ }
+
+ public PowerSaveState build() {
+ return new PowerSaveState(this);
+ }
+ }
+
+ public static final Parcelable.Creator<PowerSaveState>
+ CREATOR = new Parcelable.Creator<PowerSaveState>() {
+
+ @Override
+ public PowerSaveState createFromParcel(Parcel source) {
+ return new PowerSaveState(source);
+ }
+
+ @Override
+ public PowerSaveState[] newArray(int size) {
+ return new PowerSaveState[size];
+ }
+ };
+}
\ No newline at end of file
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index a1f8dfb..e1fb37b 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -56,6 +56,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.AppFuseMount;
import com.android.internal.os.FuseAppLoop;
import com.android.internal.os.RoSystemProperties;
@@ -1006,7 +1007,8 @@
for (String path : INTERNAL_STORAGE_SIZE_PATHS) {
final long numberBlocks = readLong(path);
if (numberBlocks > 0) {
- return new Pair<>(path, Long.valueOf(numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE));
+ return new Pair<>(path,
+ FileUtils.roundStorageSize(numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE));
}
}
return null;
@@ -1386,6 +1388,7 @@
public @NonNull ParcelFileDescriptor openProxyFileDescriptor(
int mode, ProxyFileDescriptorCallback callback, ThreadFactory factory)
throws IOException {
+ MetricsLogger.count(mContext, "storage_open_proxy_file_descriptor", 1);
// Retry is needed because the mount point mFuseAppLoop is using may be unmounted before
// invoking StorageManagerService#openProxyFileDescriptor. In this case, we need to re-mount
// the bridge by calling mountProxyFileDescriptorBridge.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 280400a..e3a9d80 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -295,7 +295,9 @@
* In some cases, a matching Activity may not exist, so ensure you
* safeguard against this.
* <p>
- * Input: Nothing.
+ * Input: Optionally, the Intent's data URI can specify the application package name to
+ * directly invoke the management GUI specific to the package name. For example
+ * "package:com.my.app".
* <p>
* Output: Nothing.
*/
@@ -8963,6 +8965,30 @@
public static final String DEVICE_IDLE_CONSTANTS_WATCH = "device_idle_constants_watch";
/**
+ * Battery Saver specific settings
+ * This is encoded as a key=value list, separated by commas. Ex:
+ *
+ * "vibration_disabled=true,adjust_brightness_factor=0.5"
+ *
+ * The following keys are supported:
+ *
+ * <pre>
+ * vibration_disabled (boolean)
+ * animation_disabled (boolean)
+ * soundtrigger_disabled (boolean)
+ * fullbackup_deferred (boolean)
+ * keyvaluebackup_deferred (boolean)
+ * firewall_disabled (boolean)
+ * gps_mode (int)
+ * adjust_brightness_disabled (boolean)
+ * adjust_brightness_factor (float)
+ * </pre>
+ * @hide
+ * @see com.android.server.power.BatterySaverPolicy
+ */
+ public static final String BATTERY_SAVER_CONSTANTS = "battery_saver_constants";
+
+ /**
* App standby (app idle) specific settings.
* This is encoded as a key=value list, separated by commas. Ex:
*
diff --git a/core/java/android/util/MathUtils.java b/core/java/android/util/MathUtils.java
index 32aac13..5c718f1 100644
--- a/core/java/android/util/MathUtils.java
+++ b/core/java/android/util/MathUtils.java
@@ -24,7 +24,6 @@
* @hide Pending API council approval
*/
public final class MathUtils {
- private static final Random sRandom = new Random();
private static final float DEG_TO_RAD = 3.1415926f / 180.0f;
private static final float RAD_TO_DEG = 180.0f / 3.1415926f;
@@ -185,28 +184,6 @@
return maxStart + (maxStart - maxStop) * ((value - minStart) / (minStop - minStart));
}
- public static int random(int howbig) {
- return (int) (sRandom.nextFloat() * howbig);
- }
-
- public static int random(int howsmall, int howbig) {
- if (howsmall >= howbig) return howsmall;
- return (int) (sRandom.nextFloat() * (howbig - howsmall) + howsmall);
- }
-
- public static float random(float howbig) {
- return sRandom.nextFloat() * howbig;
- }
-
- public static float random(float howsmall, float howbig) {
- if (howsmall >= howbig) return howsmall;
- return sRandom.nextFloat() * (howbig - howsmall) + howsmall;
- }
-
- public static void randomSeed(long seed) {
- sRandom.setSeed(seed);
- }
-
/**
* Returns the sum of the two parameters, or throws an exception if the resulting sum would
* cause an overflow or underflow.
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 7ec7ba7..5494377 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -302,7 +302,6 @@
*
* @see #getState
* @see android.os.PowerManager#isInteractive
- * @hide
*/
public static final int STATE_VR = 5;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 040a59b..8cfd6a7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1115,6 +1115,89 @@
*/
@AutoFillHint private int mAutoFillHint;
+ /** @hide */
+ @IntDef({
+ AUTOFILL_TYPE_NONE,
+ AUTOFILL_TYPE_TEXT,
+ AUTOFILL_TYPE_TOGGLE,
+ AUTOFILL_TYPE_LIST,
+ AUTOFILL_TYPE_DATE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AutofillType {}
+
+ /**
+ * Autofill type for views that cannot be autofilled.
+ */
+ public static final int AUTOFILL_TYPE_NONE = 0;
+
+ /**
+ * Autofill type for a text field, which is filled by a {@link CharSequence}.
+ *
+ * <p>{@link AutoFillValue} instances for autofilling a {@link View} can be obtained through
+ * {@link AutoFillValue#forText(CharSequence)}, and the value passed to auto-fill a
+ * {@link View} can be fetched through {@link AutoFillValue#getTextValue()}.
+ */
+ public static final int AUTOFILL_TYPE_TEXT = 1;
+
+ /**
+ * Autofill type for a togglable field, which is filled by a {@code boolean}.
+ *
+ * <p>{@link AutoFillValue} instances for auto-filling a {@link View} can be obtained through
+ * {@link AutoFillValue#forToggle(boolean)}, and the value passed to auto-fill a
+ * {@link View} can be fetched through {@link AutoFillValue#getToggleValue()}.
+ */
+ public static final int AUTOFILL_TYPE_TOGGLE = 2;
+
+ /**
+ * Autofill type for a selection list field, which is filled by an {@code int}
+ * representing the element index inside the list (starting at {@code 0}).
+ *
+ * <p>{@link AutoFillValue} instances for autofilling a {@link View} can be obtained through
+ * {@link AutoFillValue#forList(int)}, and the value passed to auto-fill a
+ * {@link View} can be fetched through {@link AutoFillValue#getListValue()}.
+ *
+ * <p>The available options in the selection list are typically provided by
+ * {@link android.app.assist.AssistStructure.ViewNode#getAutoFillOptions()}.
+ */
+ public static final int AUTOFILL_TYPE_LIST = 3;
+
+
+ /**
+ * Autofill type for a field that contains a date, which is represented by a long representing
+ * the number of milliseconds since the standard base time known as "the epoch", namely
+ * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
+ *
+ * <p>{@link AutoFillValue} instances for autofilling a {@link View} can be obtained through
+ * {@link AutoFillValue#forDate(long)}, and the values passed to
+ * auto-fill a {@link View} can be fetched through {@link AutoFillValue#getDateValue()}.
+ */
+ public static final int AUTOFILL_TYPE_DATE = 4;
+
+ /** @hide */
+ @IntDef({
+ IMPORTANT_FOR_AUTOFILL_AUTO,
+ IMPORTANT_FOR_AUTOFILL_YES,
+ IMPORTANT_FOR_AUTOFILL_NO
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AutofillImportance {}
+
+ /**
+ * Automatically determine whether a view is important for auto-fill.
+ */
+ public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
+
+ /**
+ * The view is important for important for auto-fill.
+ */
+ public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
+
+ /**
+ * The view is not important for auto-fill.
+ */
+ public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
+
/**
* This view is enabled. Interpretation varies by subclass.
* Use with ENABLED_MASK when calling setFlags.
@@ -2686,7 +2769,7 @@
* 1 PFLAG3_FINGER_DOWN
* 1 PFLAG3_FOCUSED_BY_DEFAULT
* 11 PFLAG3_AUTO_FILL_MODE_MASK
- * xx * NO LONGER NEEDED, SHOULD BE REUSED *
+ * 11 PFLAG3_IMPORTANT_FOR_AUTOFILL
* 1 PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
* 1 PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
* 1 PFLAG3_TEMPORARY_DETACH
@@ -2924,6 +3007,20 @@
| AUTO_FILL_MODE_AUTO | AUTO_FILL_MODE_MANUAL) << PFLAG3_AUTO_FILL_MODE_SHIFT;
/**
+ * Shift for the bits in {@link #mPrivateFlags3} related to the
+ * "importantForAutofill" attribute.
+ */
+ static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 21;
+
+ /**
+ * Mask for obtaining the bits which specify how to determine
+ * whether a view is important for autofill.
+ */
+ static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
+ | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO)
+ << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
+
+ /**
* Whether this view has rendered elements that overlap (see {@link
* #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
* {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
@@ -4950,6 +5047,11 @@
setAutoFillHint(a.getInt(attr, AUTO_FILL_HINT_NONE));
}
break;
+ case R.styleable.View_importantForAutofill:
+ if (a.peekValue(attr) != null) {
+ setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
+ }
+ break;
}
}
@@ -7178,14 +7280,14 @@
}
if (forAutoFill) {
- final AutoFillType autoFillType = getAutoFillType();
+ final @AutofillType int autofillType = getAutofillType();
// Don't need to fill auto-fill info if view does not support it.
// For example, only TextViews that are editable support auto-fill
- if (autoFillType != null) {
+ if (autofillType != AUTOFILL_TYPE_NONE) {
// The auto-fill id needs to be unique, but its value doesn't matter, so it's better
// to reuse the accessibility id to save space.
structure.setAutoFillId(getAccessibilityViewId());
- structure.setAutoFillType(autoFillType);
+ structure.setAutofillType(autofillType);
structure.setAutoFillHint(getAutoFillHint());
structure.setAutoFillValue(getAutoFillValue());
}
@@ -7291,7 +7393,7 @@
/**
* Automatically fills the content of this view with the {@code value}.
*
- * <p>By default does nothing, but views should override it (and {@link #getAutoFillType()},
+ * <p>By default does nothing, but views should override it (and {@link #getAutofillType()},
* {@link #getAutoFillValue()}, and {@link #onProvideAutoFillStructure(ViewStructure, int)}
* to support the AutoFill Framework.
*
@@ -7330,15 +7432,34 @@
}
/**
+ * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
+ */
+ @Deprecated
+ @Nullable
+ public final AutoFillType getAutoFillType() {
+ switch (getAutofillType()) {
+ case AUTOFILL_TYPE_TEXT:
+ return AutoFillType.forText();
+ case AUTOFILL_TYPE_TOGGLE:
+ return AutoFillType.forToggle();
+ case AUTOFILL_TYPE_LIST:
+ return AutoFillType.forList();
+ case AUTOFILL_TYPE_DATE:
+ return AutoFillType.forDate();
+ default:
+ return null;
+ }
+ }
+
+ /**
* Describes the auto-fill type that should be used on calls to
* {@link #autoFill(AutoFillValue)} and {@link #autoFillVirtual(int, AutoFillValue)}.
*
- * <p>By default returns {@code null}, but views should override it (and
+ * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it (and
* {@link #autoFill(AutoFillValue)} to support the AutoFill Framework.
*/
- @Nullable
- public AutoFillType getAutoFillType() {
- return null;
+ public @AutofillType int getAutofillType() {
+ return AUTOFILL_TYPE_NONE;
}
/**
@@ -7357,7 +7478,7 @@
* Gets the {@link View}'s current auto-fill value.
*
* <p>By default returns {@code null}, but views should override it (and
- * {@link #autoFill(AutoFillValue)}, and {@link #getAutoFillType()} to support the AutoFill
+ * {@link #autoFill(AutoFillValue)}, and {@link #getAutofillType()} to support the AutoFill
* Framework.
*/
@Nullable
@@ -7365,13 +7486,125 @@
return null;
}
+ /**
+ * Gets the mode for determining whether this View is important for autofill.
+ *
+ * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
+ *
+ * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
+ * {@link #setImportantForAutofill(int)}.
+ *
+ * @attr ref android.R.styleable#View_importantForAutofill
+ */
+ @ViewDebug.ExportedProperty(mapping = {
+ @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
+ @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
+ @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no")})
+ public @AutofillImportance int getImportantForAutofill() {
+ return (mPrivateFlags3
+ & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
+ }
+
+ /**
+ * Sets the mode for determining whether this View is important for autofill.
+ *
+ * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
+ *
+ * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
+ * or {@link #IMPORTANT_FOR_AUTOFILL_NO}.
+ *
+ * @attr ref android.R.styleable#View_importantForAutofill
+ */
+ public void setImportantForAutofill(@AutofillImportance int mode) {
+ mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
+ mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
+ & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
+ }
+
+ /**
+ * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
+ * associated with this View should be included in a {@link ViewStructure} used for
+ * autofill purposes.
+ *
+ * <p>Generally speaking, a view is important for autofill if:
+ * <ol>
+ * <li>The view can-be autofilled by an {@link android.service.autofill.AutoFillService}.
+ * <li>The view contents can help an {@link android.service.autofill.AutoFillService} to
+ * autofill other views.
+ * <ol>
+ *
+ * <p>For example, view containers should typically return {@code false} for performance reasons
+ * (since the important info is provided by their children), but if the container is actually
+ * whose children are part of a compound view, it should return {@code true} (and then override
+ * {@link #dispatchProvideAutoFillStructure(ViewStructure, int)} to simply call
+ * {@link #onProvideAutoFillStructure(ViewStructure, int)} so its children are not included in
+ * the structure). On the other hand, views representing labels or editable fields should
+ * typically return {@code true}, but in some cases they could return {@code false} (for
+ * example, if they're part of a "Captcha" mechanism).
+ *
+ * <p>By default, this method returns {@code true} if {@link #getImportantForAutofill()} returns
+ * {@link #IMPORTANT_FOR_AUTOFILL_YES}, {@code false } if it returns
+ * {@link #IMPORTANT_FOR_AUTOFILL_NO}, and use some heuristics to define the importance when it
+ * returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}. Hence, it should rarely be overridden - Views
+ * should use {@link #setImportantForAutofill(int)} instead.
+ *
+ * <p><strong>Note:</strong> returning {@code false} does not guarantee the view will be
+ * excluded from the structure; for example, if the user explicitly requested auto-fill, the
+ * View might be always included.
+ *
+ * <p>This decision applies just for the view, not its children - if the view children are not
+ * important for autofill, the view should override
+ * {@link #dispatchProvideAutoFillStructure(ViewStructure, int)} to simply call
+ * {@link #onProvideAutoFillStructure(ViewStructure, int)} (instead of calling
+ * {@link #dispatchProvideAutoFillStructure(ViewStructure, int)} for each child).
+ *
+ * @return whether the view is considered important for autofill.
+ *
+ * @see #IMPORTANT_FOR_AUTOFILL_AUTO
+ * @see #IMPORTANT_FOR_AUTOFILL_YES
+ * @see #IMPORTANT_FOR_AUTOFILL_NO
+ */
+ public final boolean isImportantForAutofill() {
+ final int flag = getImportantForAutofill();
+
+ // First, check if view explicity set it to YES or NO
+ if ((flag & IMPORTANT_FOR_AUTOFILL_YES) != 0) {
+ return true;
+ }
+ if ((flag & IMPORTANT_FOR_AUTOFILL_NO) != 0) {
+ return false;
+ }
+
+ // Then use some heuristics to handle AUTO.
+
+ // Always include views that have a explicity resource id.
+ final int id = mID;
+ if (id != NO_ID && !isViewIdGenerated(id)) {
+ final Resources res = getResources();
+ String entry = null;
+ String pkg = null;
+ try {
+ entry = res.getResourceEntryName(id);
+ pkg = res.getResourcePackageName(id);
+ } catch (Resources.NotFoundException e) {
+ // ignore
+ }
+ if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
+ return true;
+ }
+ }
+
+ // Otherwise, assume it's not important...
+ return false;
+ }
+
@Nullable
private AutoFillManager getAutoFillManager() {
return mContext.getSystemService(AutoFillManager.class);
}
private boolean isAutoFillable() {
- return getAutoFillType() != null && !isAutoFillBlocked();
+ return getAutofillType() != AUTOFILL_TYPE_NONE && !isAutoFillBlocked();
}
private void populateVirtualStructure(ViewStructure structure,
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 3dd3ba8..214249f 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -595,6 +595,7 @@
public ViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+
initViewGroup();
initFromAttributes(context, attrs, defStyleAttr, defStyleRes);
}
@@ -3341,82 +3342,122 @@
dispatchProvideStructureForAssistOrAutoFill(structure, true);
}
+ /** @hide */
+ private ArrayList<View> getChildrenForAutofill() {
+ final ArrayList<View> list = new ArrayList<>();
+ populateChildrenForAutofill(list);
+ return list;
+ }
+
+ /** @hide */
+ private void populateChildrenForAutofill(ArrayList<View> list) {
+ final int count = mChildrenCount;
+ for (int i = 0; i < count; i++) {
+ final View child = mChildren[i];
+ if (child.isImportantForAutofill()) {
+ list.add(child);
+ } else if (child instanceof ViewGroup) {
+ ((ViewGroup) child).populateChildrenForAutofill(list);
+ }
+ }
+ }
+
private void dispatchProvideStructureForAssistOrAutoFill(ViewStructure structure,
boolean forAutoFill) {
boolean blocked = forAutoFill ? isAutoFillBlocked() : isAssistBlocked();
+ if (blocked || structure.getChildCount() != 0) {
+ return;
+ }
+ final View[] childrenArray;
+ final ArrayList<View> childrenList;
+ final int childrenCount;
- if (!blocked) {
- if (structure.getChildCount() == 0) {
- final int childrenCount = getChildCount();
- if (childrenCount > 0) {
- structure.setChildCount(childrenCount);
- ArrayList<View> preorderedList = buildOrderedChildList();
- boolean customOrder = preorderedList == null
- && isChildrenDrawingOrderEnabled();
- final View[] children = mChildren;
- for (int i=0; i<childrenCount; i++) {
- int childIndex;
- try {
- childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
- } catch (IndexOutOfBoundsException e) {
- childIndex = i;
- if (mContext.getApplicationInfo().targetSdkVersion
- < Build.VERSION_CODES.M) {
- Log.w(TAG, "Bad getChildDrawingOrder while collecting assist @ "
- + i + " of " + childrenCount, e);
- // At least one app is failing when we call getChildDrawingOrder
- // at this point, so deal semi-gracefully with it by falling back
- // on the basic order.
- customOrder = false;
- if (i > 0) {
- // If we failed at the first index, there really isn't
- // anything to do -- we will just proceed with the simple
- // sequence order.
- // Otherwise, we failed in the middle, so need to come up
- // with an order for the remaining indices and use that.
- // Failed at the first one, easy peasy.
- int[] permutation = new int[childrenCount];
- SparseBooleanArray usedIndices = new SparseBooleanArray();
- // Go back and collected the indices we have done so far.
- for (int j=0; j<i; j++) {
- permutation[j] = getChildDrawingOrder(childrenCount, j);
- usedIndices.put(permutation[j], true);
- }
- // Fill in the remaining indices with indices that have not
- // yet been used.
- int nextIndex = 0;
- for (int j=i; j<childrenCount; j++) {
- while (usedIndices.get(nextIndex, false)) {
- nextIndex++;
- }
- permutation[j] = nextIndex;
- nextIndex++;
- }
- // Build the final view list.
- preorderedList = new ArrayList<>(childrenCount);
- for (int j=0; j<childrenCount; j++) {
- preorderedList.add(children[permutation[j]]);
- }
+ if (forAutoFill) {
+ childrenArray = null;
+ // TODO(b/33197203): the current algorithm allocates a new list for each children that
+ // is a view group; ideally, we should use mAttachInfo.mTempArrayList instead, but that
+ // would complicated the algorithm a lot...
+ childrenList = getChildrenForAutofill();
+
+ childrenCount = childrenList.size();
+ } else {
+ childrenArray = mChildren;
+ childrenList = null;
+ childrenCount = getChildCount();
+ }
+
+ if (childrenCount > 0) {
+ structure.setChildCount(childrenCount);
+ ArrayList<View> preorderedList = buildOrderedChildList();
+ boolean customOrder = preorderedList == null
+ && isChildrenDrawingOrderEnabled();
+ for (int i = 0; i < childrenCount; i++) {
+ int childIndex;
+ try {
+ childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
+ } catch (IndexOutOfBoundsException e) {
+ childIndex = i;
+ if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.M) {
+ Log.w(TAG, "Bad getChildDrawingOrder while collecting assist @ "
+ + i + " of " + childrenCount, e);
+ // At least one app is failing when we call getChildDrawingOrder
+ // at this point, so deal semi-gracefully with it by falling back
+ // on the basic order.
+ customOrder = false;
+ if (i > 0) {
+ // If we failed at the first index, there really isn't
+ // anything to do -- we will just proceed with the simple
+ // sequence order.
+ // Otherwise, we failed in the middle, so need to come up
+ // with an order for the remaining indices and use that.
+ // Failed at the first one, easy peasy.
+ int[] permutation = new int[childrenCount];
+ SparseBooleanArray usedIndices = new SparseBooleanArray();
+ // Go back and collected the indices we have done so far.
+ for (int j = 0; j < i; j++) {
+ permutation[j] = getChildDrawingOrder(childrenCount, j);
+ usedIndices.put(permutation[j], true);
+ }
+ // Fill in the remaining indices with indices that have not
+ // yet been used.
+ int nextIndex = 0;
+ for (int j = i; j < childrenCount; j++) {
+ while (usedIndices.get(nextIndex, false)) {
+ nextIndex++;
}
- } else {
- throw e;
+ permutation[j] = nextIndex;
+ nextIndex++;
+ }
+ // Build the final view list.
+ preorderedList = new ArrayList<>(childrenCount);
+ for (int j = 0; j < childrenCount; j++) {
+ final int index = permutation[j];
+ final View child = forAutoFill
+ ? childrenList.get(index)
+ : childrenArray[index];
+ preorderedList.add(child);
}
}
-
- final View child = getAndVerifyPreorderedView(
- preorderedList, children, childIndex);
- final ViewStructure cstructure = structure.newChild(i);
-
- // Must explicitly check which recursive method to call.
- if (forAutoFill) {
- // NOTE: flags are not currently supported, hence 0
- child.dispatchProvideAutoFillStructure(cstructure, 0);
- } else {
- child.dispatchProvideStructure(cstructure);
- }
+ } else {
+ throw e;
}
- if (preorderedList != null) preorderedList.clear();
}
+
+ final View child = forAutoFill
+ ? getAndVerifyPreorderedView(preorderedList, childrenList, childIndex)
+ : getAndVerifyPreorderedView(preorderedList, childrenArray, childIndex);
+ final ViewStructure cstructure = structure.newChild(i);
+
+ // Must explicitly check which recursive method to call.
+ if (forAutoFill) {
+ // NOTE: flags are not currently supported, hence 0
+ child.dispatchProvideAutoFillStructure(cstructure, 0);
+ } else {
+ child.dispatchProvideStructure(cstructure);
+ }
+ }
+ if (preorderedList != null) {
+ preorderedList.clear();
}
}
}
@@ -3436,6 +3477,21 @@
return child;
}
+ private static View getAndVerifyPreorderedView(ArrayList<View> preorderedList,
+ ArrayList<View> children, int childIndex) {
+ final View child;
+ if (preorderedList != null) {
+ child = preorderedList.get(childIndex);
+ if (child == null) {
+ throw new RuntimeException("Invalid preorderedList contained null child at index "
+ + childIndex);
+ }
+ } else {
+ child = children.get(childIndex);
+ }
+ return child;
+ }
+
/** @hide */
@Override
public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 92f78b9..c7c2bb8 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -311,12 +311,17 @@
public abstract ViewStructure asyncNewChildForAutoFill(int index, int virtualId, int flags);
/**
- * Sets the {@link AutoFillType} that can be used to auto-fill this node.
+ * @deprecated TODO(b/35956626): remove once clients use setAutoFilltype()
*/
- // TODO(b/33197203, b/33802548): add CTS/unit test
+ @Deprecated
public abstract void setAutoFillType(AutoFillType info);
/**
+ * Sets the {@link View#getAutofillType()} that can be used to autofill this node.
+ */
+ public abstract void setAutofillType(@View.AutofillType int type);
+
+ /**
* Sets the a hint that helps the auto-fill service to select the appropriate data to fill the
* view.
*/
diff --git a/core/java/android/view/autofill/AutoFillManager.java b/core/java/android/view/autofill/AutoFillManager.java
index e8325e8..8beaf4e 100644
--- a/core/java/android/view/autofill/AutoFillManager.java
+++ b/core/java/android/view/autofill/AutoFillManager.java
@@ -19,7 +19,9 @@
import static android.view.autofill.Helper.DEBUG;
import static android.view.autofill.Helper.VERBOSE;
+import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
@@ -30,7 +32,10 @@
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
+import android.view.WindowManagerGlobal;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.List;
@@ -76,6 +81,8 @@
private final IAutoFillManager mService;
private IAutoFillManagerClient mServiceClient;
+ private AutofillCallback mCallback;
+
private Context mContext;
private boolean mHasSession;
@@ -276,11 +283,11 @@
}
}
- private AutoFillId getAutoFillId(View view) {
+ private static AutoFillId getAutoFillId(View view) {
return new AutoFillId(view.getAccessibilityViewId());
}
- private AutoFillId getAutoFillId(View parent, int childId) {
+ private static AutoFillId getAutoFillId(View parent, int childId) {
return new AutoFillId(parent.getAccessibilityViewId(), childId);
}
@@ -289,10 +296,12 @@
if (DEBUG) {
Log.d(TAG, "startSession(): id=" + id + ", bounds=" + bounds + ", value=" + value);
}
+
try {
mService.startSession(mContext.getActivityToken(), windowToken,
- mServiceClient.asBinder(), id, bounds, value, mContext.getUserId());
- AutoFillClient client = getClient();
+ mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
+ mCallback != null);
+ final AutoFillClient client = getClient();
if (client != null) {
client.resetableStateAvailable();
}
@@ -344,6 +353,119 @@
}
}
+ /**
+ * Registers a {@link AutofillCallback} to receive autofill events.
+ *
+ * @param callback callback to receive events.
+ */
+ public void registerCallback(@Nullable AutofillCallback callback) {
+ if (callback == null) return;
+
+ final boolean hadCallback = mCallback != null;
+ mCallback = callback;
+
+ if (mHasSession && !hadCallback) {
+ try {
+ mService.setHasCallback(mContext.getActivityToken(), mContext.getUserId(), true);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Unregisters a {@link AutofillCallback} to receive autofill events.
+ *
+ * @param callback callback to stop receiving events.
+ */
+ public void unregisterCallback(@Nullable AutofillCallback callback) {
+ if (callback == null || mCallback == null || callback != mCallback) return;
+
+ mCallback = null;
+
+ if (mHasSession) {
+ try {
+ mService.setHasCallback(mContext.getActivityToken(), mContext.getUserId(), false);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ private void onAutofillEvent(IBinder windowToken, AutoFillId id, int event) {
+ if (mCallback == null) return;
+ if (id == null) {
+ Log.w(TAG, "onAutofillEvent(): no id for event " + event);
+ return;
+ }
+
+ final View root = WindowManagerGlobal.getInstance().getWindowView(windowToken);
+ if (root == null) {
+ Log.w(TAG, "onAutofillEvent() for " + id + ": root view gone");
+ return;
+ }
+ final View view = root.findViewByAccessibilityIdTraversal(id.getViewId());
+ if (view == null) {
+ Log.w(TAG, "onAutofillEvent() for " + id + ": view gone");
+ return;
+ }
+ if (id.isVirtual()) {
+ mCallback.onAutofillEventVirtual(view, id.getVirtualChildId(), event);
+ } else {
+ mCallback.onAutofillEvent(view, event);
+ }
+ }
+
+ /**
+ * Callback for auto-fill related events.
+ *
+ * <p>Typically used for applications that display their own "auto-complete" views, so they can
+ * enable / disable such views when the auto-fill UI affordance is shown / hidden.
+ */
+ public abstract static class AutofillCallback {
+
+ /** @hide */
+ @IntDef({EVENT_INPUT_SHOWN, EVENT_INPUT_HIDDEN})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AutofillEventType {}
+
+ /**
+ * The auto-fill input UI affordance associated with the view was shown.
+ *
+ * <p>If the view provides its own auto-complete UI affordance and its currently shown, it
+ * should be hidden upon receiving this event.
+ */
+ public static final int EVENT_INPUT_SHOWN = 1;
+
+ /**
+ * The auto-fill input UI affordance associated with the view was hidden.
+ *
+ * <p>If the view provides its own auto-complete UI affordance that was hidden upon a
+ * {@link #EVENT_INPUT_SHOWN} event, it could be shown again now.
+ */
+ public static final int EVENT_INPUT_HIDDEN = 2;
+
+ /**
+ * Called after a change in the autofill state associated with a view.
+ *
+ * @param view view associated with the change.
+ *
+ * @param event currently either {@link #EVENT_INPUT_SHOWN} or {@link #EVENT_INPUT_HIDDEN}.
+ */
+ public void onAutofillEvent(@NonNull View view, @AutofillEventType int event) {}
+
+ /**
+ * Called after a change in the autofill state associated with a virtual view.
+ *
+ * @param view parent view associated with the change.
+ * @param childId id identifying the virtual child inside the parent view.
+ *
+ * @param event currently either {@link #EVENT_INPUT_SHOWN} or {@link #EVENT_INPUT_HIDDEN}.
+ */
+ public void onAutofillEventVirtual(@NonNull View view, int childId,
+ @AutofillEventType int event) {}
+ }
+
private static final class AutoFillManagerClient extends IAutoFillManagerClient.Stub {
private final WeakReference<AutoFillManager> mAutoFillManager;
@@ -385,5 +507,17 @@
});
}
}
+
+ @Override
+ public void onAutofillEvent(IBinder windowToken, AutoFillId id, int event) {
+ final AutoFillManager autoFillManager = mAutoFillManager.get();
+ if (autoFillManager != null) {
+ autoFillManager.mContext.getMainThreadHandler().post(() -> {
+ if (autoFillManager.getClient() != null) {
+ autoFillManager.onAutofillEvent(windowToken, id, event);
+ }
+ });
+ }
+ }
}
}
diff --git a/core/java/android/view/autofill/AutoFillType.aidl b/core/java/android/view/autofill/AutoFillType.aidl
index a63d7c5..4606b48 100644
--- a/core/java/android/view/autofill/AutoFillType.aidl
+++ b/core/java/android/view/autofill/AutoFillType.aidl
@@ -16,4 +16,7 @@
package android.view.autofill;
+/*
+ * TODO(b/35956626): remove once clients use getAutoFilltype()
+ */
parcelable AutoFillType;
\ No newline at end of file
diff --git a/core/java/android/view/autofill/AutoFillType.java b/core/java/android/view/autofill/AutoFillType.java
index 536d5e0..37966b2 100644
--- a/core/java/android/view/autofill/AutoFillType.java
+++ b/core/java/android/view/autofill/AutoFillType.java
@@ -26,6 +26,8 @@
* Defines the type of a object that can be used to auto-fill a {@link View} so the
* {@link android.service.autofill.AutoFillService} can use the proper {@link AutoFillValue} to
* fill it.
+ *
+ * TODO(b/35956626): remove once clients use getAutoFilltype
*/
public final class AutoFillType implements Parcelable {
@@ -95,8 +97,6 @@
* <p>{@link AutoFillValue} instances for auto-filling a {@link View} can be obtained through
* {@link AutoFillValue#forDate(long)}, and the values passed to
* auto-fill a {@link View} can be fetched through {@link AutoFillValue#getDateValue()}.
- *
- * <p>This type has no sub-types.
*/
public boolean isDate() {
return mType == TYPE_DATE;
diff --git a/core/java/android/view/autofill/AutoFillValue.java b/core/java/android/view/autofill/AutoFillValue.java
index c24e04e..11fab68 100644
--- a/core/java/android/view/autofill/AutoFillValue.java
+++ b/core/java/android/view/autofill/AutoFillValue.java
@@ -45,38 +45,36 @@
}
/**
- * Gets the value to auto-fill a text field.
+ * Gets the value to autofill a text field.
*
- * <p>See {@link AutoFillType#isText()} for more info.
+ * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.
*/
public CharSequence getTextValue() {
return mText;
}
/**
- * Gets the value to auto-fill a toggable field.
+ * Gets the value to autofill a toggable field.
*
- * <p>See {@link AutoFillType#isToggle()} for more info.
+ * <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.
*/
public boolean getToggleValue() {
return mToggle;
}
/**
- * Gets the value to auto-fill a selection list field.
+ * Gets the value to autofill a selection list field.
*
- * <p>See {@link AutoFillType#isList()} for more info.
+ * <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.
*/
public int getListValue() {
return mListIndex;
}
/**
- * Gets the value representing the the number of milliseconds since the standard base time known
- * as "the epoch", namely January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}
- * of a date field.
+ * Gets the value to autofill a date field.
*
- * <p>See {@link AutoFillType#isDate()} for more info.
+ * <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.
*/
public long getDateValue() {
return mDate;
@@ -174,9 +172,9 @@
// TODO(b/33197203): add unit tests for each supported type (new / get should return same value)
/**
- * Creates a new {@link AutoFillValue} to auto-fill a {@link View} representing a text field.
+ * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a text field.
*
- * <p>See {@link AutoFillType#isText()} for more info.
+ * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.
*/
// TODO(b/33197203): use cache
@Nullable
@@ -185,29 +183,29 @@
}
/**
- * Creates a new {@link AutoFillValue} to auto-fill a {@link View} representing a toggable
+ * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a toggable
* field.
*
- * <p>See {@link AutoFillType#isToggle()} for more info.
+ * <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.
*/
public static AutoFillValue forToggle(boolean value) {
return new AutoFillValue(null, 0, value, 0);
}
/**
- * Creates a new {@link AutoFillValue} to auto-fill a {@link View} representing a selection
+ * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a selection
* list.
*
- * <p>See {@link AutoFillType#isList()} for more info.
+ * <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.
*/
public static AutoFillValue forList(int value) {
return new AutoFillValue(null, value, false, 0);
}
/**
- * Creates a new {@link AutoFillValue} to auto-fill a {@link View} representing a date.
+ * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a date.
*
- * <p>See {@link AutoFillType#isDate()} for more info.
+ * <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.
*/
public static AutoFillValue forDate(long date) {
return new AutoFillValue(null, 0, false, date);
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index d054e97..b36c0f1 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -31,10 +31,12 @@
interface IAutoFillManager {
boolean addClient(in IAutoFillManagerClient client, int userId);
oneway void startSession(in IBinder activityToken, IBinder windowToken, in IBinder appCallback,
- in AutoFillId autoFillId, in Rect bounds, in AutoFillValue value, int userId);
+ in AutoFillId autoFillId, in Rect bounds, in AutoFillValue value, int userId,
+ boolean hasCallback);
oneway void updateSession(in IBinder activityToken, in AutoFillId id, in Rect bounds,
in AutoFillValue value, int flags, int userId);
oneway void finishSession(in IBinder activityToken, int userId);
oneway void setAuthenticationResult(in Bundle data,
in IBinder activityToken, int userId);
+ oneway void setHasCallback(in IBinder activityToken, int userId, boolean hasIt);
}
diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
index 45f363d..9eef7d0 100644
--- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
@@ -20,6 +20,7 @@
import android.content.Intent;
import android.content.IntentSender;
+import android.os.IBinder;
import android.view.autofill.AutoFillId;
import android.view.autofill.AutoFillValue;
@@ -43,4 +44,9 @@
* Authenticates a fill response or a data set.
*/
void authenticate(in IntentSender intent, in Intent fillInIntent);
+
+ /**
+ * Notifies the client when the auto-fill UI changed.
+ */
+ void onAutofillEvent(in IBinder windowToken, in AutoFillId id, int event);
}
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index 791543e..46f7a81 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -18,7 +18,9 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.StringDef;
+import android.os.LocaleList;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -51,20 +53,43 @@
@Override
public TextSelection suggestSelection(
- CharSequence text, int selectionStartIndex, int selectionEndIndex) {
+ CharSequence text,
+ int selectionStartIndex,
+ int selectionEndIndex,
+ LocaleList defaultLocales) {
return new TextSelection.Builder(selectionStartIndex, selectionEndIndex).build();
}
@Override
public TextClassificationResult getTextClassificationResult(
- CharSequence text, int startIndex, int endIndex) {
+ CharSequence text, int startIndex, int endIndex, LocaleList defaultLocales) {
return TextClassificationResult.EMPTY;
}
@Override
- public LinksInfo getLinks(CharSequence text, int linkMask) {
+ public LinksInfo getLinks(CharSequence text, int linkMask, LocaleList defaultLocales) {
return LinksInfo.NO_OP;
}
+
+ // TODO: Remove
+ @Override
+ public TextSelection suggestSelection(
+ CharSequence text, int selectionStartIndex, int selectionEndIndex) {
+ throw new UnsupportedOperationException("Removed");
+ }
+
+ // TODO: Remove
+ @Override
+ public TextClassificationResult getTextClassificationResult(
+ CharSequence text, int startIndex, int endIndex) {
+ throw new UnsupportedOperationException("Removed");
+ }
+
+ // TODO: Remove
+ @Override
+ public LinksInfo getLinks(CharSequence text, int linkMask) {
+ throw new UnsupportedOperationException("Removed");
+ }
};
/**
@@ -75,15 +100,20 @@
* by the sub sequence starting at selectionStartIndex and ending at selectionEndIndex)
* @param selectionStartIndex start index of the selected part of text
* @param selectionEndIndex end index of the selected part of text
+ * @param defaultLocales ordered list of locale preferences that can be used to disambiguate
+ * the provided text. If no locale preferences exist, set this to null or an empty locale
+ * list in which case the classifier will decide whether to use no locale information, use
+ * a default locale, or use the system default.
*
* @throws IllegalArgumentException if text is null; selectionStartIndex is negative;
- * selectionEndIndex is greater than text.length() or less than selectionStartIndex
+ * selectionEndIndex is greater than text.length() or not greater than selectionStartIndex
*/
@NonNull
TextSelection suggestSelection(
@NonNull CharSequence text,
@IntRange(from = 0) int selectionStartIndex,
- @IntRange(from = 0) int selectionEndIndex);
+ @IntRange(from = 0) int selectionEndIndex,
+ @Nullable LocaleList defaultLocales);
/**
* Returns a {@link TextClassificationResult} object that can be used to generate a widget for
@@ -93,13 +123,20 @@
* by the sub sequence starting at startIndex and ending at endIndex)
* @param startIndex start index of the text to classify
* @param endIndex end index of the text to classify
+ * @param defaultLocales ordered list of locale preferences that can be used to disambiguate
+ * the provided text. If no locale preferences exist, set this to null or an empty locale
+ * list in which case the classifier will decide whether to use no locale information, use
+ * a default locale, or use the system default.
*
* @throws IllegalArgumentException if text is null; startIndex is negative;
- * endIndex is greater than text.length() or less than startIndex
+ * endIndex is greater than text.length() or not greater than startIndex
*/
@NonNull
TextClassificationResult getTextClassificationResult(
- @NonNull CharSequence text, int startIndex, int endIndex);
+ @NonNull CharSequence text,
+ @IntRange(from = 0) int startIndex,
+ @IntRange(from = 0) int endIndex,
+ @Nullable LocaleList defaultLocales);
/**
* Returns a {@link LinksInfo} that may be applied to the text to annotate it with links
@@ -108,8 +145,25 @@
* @param text the text to generate annotations for
* @param linkMask See {@link android.text.util.Linkify} for a list of linkMasks that may be
* specified. Subclasses of this interface may specify additional linkMasks
+ * @param defaultLocales ordered list of locale preferences that can be used to disambiguate
+ * the provided text. If no locale preferences exist, set this to null or an empty locale
+ * list in which case the classifier will decide whether to use no locale information, use
+ * a default locale, or use the system default.
*
* @throws IllegalArgumentException if text is null
*/
- LinksInfo getLinks(@NonNull CharSequence text, int linkMask);
+ LinksInfo getLinks(
+ @NonNull CharSequence text, int linkMask, @Nullable LocaleList defaultLocales);
+
+ // TODO: Remove
+ /** @removed */
+ TextSelection suggestSelection(
+ CharSequence text, int selectionStartIndex, int selectionEndIndex);
+ // TODO: Remove
+ /** @removed */
+ TextClassificationResult getTextClassificationResult(
+ CharSequence text, int startIndex, int endIndex);
+ // TODO: Remove
+ /** @removed */
+ LinksInfo getLinks(CharSequence text, int linkMask);
}
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 536d7e0..0486f9f 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -26,6 +26,7 @@
import android.graphics.drawable.Drawable;
import android.icu.text.BreakIterator;
import android.net.Uri;
+import android.os.LocaleList;
import android.os.ParcelFileDescriptor;
import android.provider.Browser;
import android.text.Spannable;
@@ -74,7 +75,8 @@
@Override
public TextSelection suggestSelection(
- @NonNull CharSequence text, int selectionStartIndex, int selectionEndIndex) {
+ @NonNull CharSequence text, int selectionStartIndex, int selectionEndIndex,
+ LocaleList defaultLocales) {
validateInput(text, selectionStartIndex, selectionEndIndex);
try {
if (text.length() > 0) {
@@ -101,12 +103,12 @@
}
// Getting here means something went wrong, return a NO_OP result.
return TextClassifier.NO_OP.suggestSelection(
- text, selectionStartIndex, selectionEndIndex);
+ text, selectionStartIndex, selectionEndIndex, defaultLocales);
}
@Override
public TextClassificationResult getTextClassificationResult(
- @NonNull CharSequence text, int startIndex, int endIndex) {
+ @NonNull CharSequence text, int startIndex, int endIndex, LocaleList defaultLocales) {
validateInput(text, startIndex, endIndex);
try {
if (text.length() > 0) {
@@ -125,11 +127,12 @@
Log.e(LOG_TAG, "Error getting assist info.", t);
}
// Getting here means something went wrong, return a NO_OP result.
- return TextClassifier.NO_OP.getTextClassificationResult(text, startIndex, endIndex);
+ return TextClassifier.NO_OP.getTextClassificationResult(
+ text, startIndex, endIndex, defaultLocales);
}
@Override
- public LinksInfo getLinks(CharSequence text, int linkMask) {
+ public LinksInfo getLinks(CharSequence text, int linkMask, LocaleList defaultLocales) {
Preconditions.checkArgument(text != null);
try {
return LinksInfoFactory.create(
@@ -139,7 +142,27 @@
Log.e(LOG_TAG, "Error getting links info.", t);
}
// Getting here means something went wrong, return a NO_OP result.
- return TextClassifier.NO_OP.getLinks(text, linkMask);
+ return TextClassifier.NO_OP.getLinks(text, linkMask, defaultLocales);
+ }
+
+ // TODO: Remove
+ @Override
+ public TextSelection suggestSelection(
+ CharSequence text, int selectionStartIndex, int selectionEndIndex) {
+ throw new UnsupportedOperationException("Removed");
+ }
+
+ // TODO: Remove
+ @Override
+ public TextClassificationResult getTextClassificationResult(
+ CharSequence text, int startIndex, int endIndex) {
+ throw new UnsupportedOperationException("Removed");
+ }
+
+ // TODO: Remove
+ @Override
+ public LinksInfo getLinks(CharSequence text, int linkMask) {
+ throw new UnsupportedOperationException("Removed");
}
private SmartSelection getSmartSelection() throws FileNotFoundException {
@@ -195,7 +218,7 @@
/**
* @throws IllegalArgumentException if text is null; startIndex is negative;
- * endIndex is greater than text.length() or less than startIndex
+ * endIndex is greater than text.length() or is not greater than startIndex
*/
private static void validateInput(@NonNull CharSequence text, int startIndex, int endIndex) {
Preconditions.checkArgument(text != null);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 4757757..3fbeb03 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -630,6 +630,12 @@
protected WebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes,
Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) {
super(context, attrs, defStyleAttr, defStyleRes);
+
+ // WebView is important by default, unless app developer overrode attribute.
+ if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+ setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
+ }
+
if (context == null) {
throw new IllegalArgumentException("Invalid context argument");
}
diff --git a/core/java/android/widget/AbsSpinner.java b/core/java/android/widget/AbsSpinner.java
index bc3dfff..e6cd566 100644
--- a/core/java/android/widget/AbsSpinner.java
+++ b/core/java/android/widget/AbsSpinner.java
@@ -26,6 +26,8 @@
import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewStructure;
+import android.view.autofill.AutoFillValue;
import com.android.internal.R;
@@ -68,6 +70,12 @@
public AbsSpinner(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+
+ // Spinner is important by default, unless app developer overrode attribute.
+ if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+ setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
+ }
+
initAbsSpinner();
final TypedArray a = context.obtainStyledAttributes(
@@ -480,4 +488,43 @@
public CharSequence getAccessibilityClassName() {
return AbsSpinner.class.getName();
}
+
+ // TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable)
+
+ @Override
+ public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
+ super.onProvideAutoFillStructure(structure, flags);
+
+ if (getAdapter() == null) return;
+
+ // TODO(b/33197203): implement sanitization so initial value is only sanitized when coming
+ // from resources.
+
+ final int count = getAdapter().getCount();
+ if (count > 0) {
+ final String[] options = new String[count];
+ for (int i = 0; i < count; i++) {
+ options[i] = getAdapter().getItem(i).toString();
+ }
+ structure.setAutoFillOptions(options);
+ }
+ }
+
+ @Override
+ public void autoFill(AutoFillValue value) {
+ if (!isEnabled()) return;
+
+ final int position = value.getListValue();
+ setSelection(position);
+ }
+
+ @Override
+ public @AutofillType int getAutofillType() {
+ return isEnabled() ? AUTOFILL_TYPE_LIST : AUTOFILL_TYPE_NONE;
+ }
+
+ @Override
+ public AutoFillValue getAutoFillValue() {
+ return isEnabled() ? AutoFillValue.forList(getSelectedItemPosition()) : null;
+ }
}
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 141b52f..dce33a0 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -36,7 +36,6 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.autofill.AutoFillManager;
-import android.view.autofill.AutoFillType;
import android.view.autofill.AutoFillValue;
import com.android.internal.R;
@@ -590,8 +589,8 @@
}
@Override
- public AutoFillType getAutoFillType() {
- return isEnabled() ? AutoFillType.forToggle() : null;
+ public @AutofillType int getAutofillType() {
+ return isEnabled() ? AUTOFILL_TYPE_TOGGLE : AUTOFILL_TYPE_NONE;
}
@Override
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 0ffefd0..c905172 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -34,7 +34,6 @@
import android.view.ViewStructure;
import android.view.accessibility.AccessibilityEvent;
import android.view.autofill.AutoFillManager;
-import android.view.autofill.AutoFillType;
import android.view.autofill.AutoFillValue;
import com.android.internal.R;
@@ -146,6 +145,11 @@
public DatePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ // DatePicker is important by default, unless app developer overrode attribute.
+ if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+ setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
+ }
+
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker,
defStyleAttr, defStyleRes);
final boolean isDialogMode = a.getBoolean(R.styleable.DatePicker_dialogMode, false);
@@ -775,8 +779,8 @@
}
@Override
- public AutoFillType getAutoFillType() {
- return isEnabled() ? AutoFillType.forDate() : null;
+ public @AutofillType int getAutofillType() {
+ return isEnabled() ? AUTOFILL_TYPE_DATE : AUTOFILL_TYPE_NONE;
}
@Override
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index cd80651..7e6f2e4 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -156,6 +156,11 @@
initImageView();
+ // ImageView is not important by default, unless app developer overrode attribute.
+ if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+ setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO);
+ }
+
final TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.ImageView, defStyleAttr, defStyleRes);
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index be5fc53..bb8cd28 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -26,7 +26,6 @@
import android.view.ViewGroup;
import android.view.ViewStructure;
import android.view.autofill.AutoFillManager;
-import android.view.autofill.AutoFillType;
import android.view.autofill.AutoFillValue;
import com.android.internal.R;
@@ -86,6 +85,11 @@
public RadioGroup(Context context, AttributeSet attrs) {
super(context, attrs);
+ // RadioGroup is important by default, unless app developer overrode attribute.
+ if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+ setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
+ }
+
// retrieve selected radio button as requested by the user in the
// XML layout file
TypedArray attributes = context.obtainStyledAttributes(
@@ -435,8 +439,8 @@
}
@Override
- public AutoFillType getAutoFillType() {
- return isEnabled() ? AutoFillType.forList() : null;
+ public @AutofillType int getAutofillType() {
+ return isEnabled() ? AUTOFILL_TYPE_LIST : AUTOFILL_TYPE_NONE;
}
@Override
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index b751935..a032383 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -21,6 +21,7 @@
import android.annotation.UiThread;
import android.annotation.WorkerThread;
import android.os.AsyncTask;
+import android.os.LocaleList;
import android.text.Selection;
import android.text.Spannable;
import android.text.TextUtils;
@@ -60,7 +61,7 @@
mEditor = Preconditions.checkNotNull(editor);
final TextView textView = mEditor.getTextView();
mTextClassificationHelper = new TextClassificationHelper(
- textView.getTextClassifier(), textView.getText(), 0, 1);
+ textView.getTextClassifier(), textView.getText(), 0, 1, textView.getTextLocales());
}
public void startActionModeAsync() {
@@ -170,7 +171,8 @@
private void resetTextClassificationHelper() {
final TextView textView = mEditor.getTextView();
mTextClassificationHelper.reset(textView.getTextClassifier(), textView.getText(),
- textView.getSelectionStart(), textView.getSelectionEnd());
+ textView.getSelectionStart(), textView.getSelectionEnd(),
+ textView.getTextLocales());
}
/**
@@ -297,6 +299,7 @@
private int mSelectionStart;
/** End index relative to mText. */
private int mSelectionEnd;
+ private LocaleList mLocales;
/** Trimmed text starting from mTrimStart in mText. */
private CharSequence mTrimmedText;
@@ -308,18 +311,19 @@
private int mRelativeEnd;
TextClassificationHelper(TextClassifier textClassifier,
- CharSequence text, int selectionStart, int selectionEnd) {
- reset(textClassifier, text, selectionStart, selectionEnd);
+ CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) {
+ reset(textClassifier, text, selectionStart, selectionEnd, locales);
}
@UiThread
public void reset(TextClassifier textClassifier,
- CharSequence text, int selectionStart, int selectionEnd) {
+ CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) {
mTextClassifier = Preconditions.checkNotNull(textClassifier);
mText = Preconditions.checkNotNull(text).toString();
Preconditions.checkArgument(selectionEnd > selectionStart);
mSelectionStart = selectionStart;
mSelectionEnd = selectionEnd;
+ mLocales = locales;
}
@WorkerThread
@@ -329,14 +333,14 @@
mSelectionStart,
mSelectionEnd,
mTextClassifier.getTextClassificationResult(
- mTrimmedText, mRelativeStart, mRelativeEnd));
+ mTrimmedText, mRelativeStart, mRelativeEnd, mLocales));
}
@WorkerThread
public SelectionResult suggestSelection() {
trimText();
final TextSelection sel = mTextClassifier.suggestSelection(
- mTrimmedText, mRelativeStart, mRelativeEnd);
+ mTrimmedText, mRelativeStart, mRelativeEnd, mLocales);
mSelectionStart = Math.max(0, sel.getSelectionStartIndex() + mTrimStart);
mSelectionEnd = Math.min(mText.length(), sel.getSelectionEndIndex() + mTrimStart);
return classifyText();
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index 1eff26e..3811e1a 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -45,8 +45,6 @@
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.autofill.AutoFillType;
-import android.view.autofill.AutoFillValue;
import android.widget.PopupWindow.OnDismissListener;
import com.android.internal.R;
@@ -937,24 +935,6 @@
}
}
- @Override
- public void autoFill(AutoFillValue value) {
- if (!isEnabled()) return;
-
- final int position = value.getListValue();
- setSelection(position);
- }
-
- @Override
- public AutoFillType getAutoFillType() {
- return AutoFillType.forList();
- }
-
- @Override
- public AutoFillValue getAutoFillValue() {
- return isEnabled() ? AutoFillValue.forList(getSelectedItemPosition()) : null;
- }
-
static class SavedState extends AbsSpinner.SavedState {
boolean showDropdown;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5307a08..b901ab4 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -141,7 +141,6 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AnimationUtils;
import android.view.autofill.AutoFillManager;
-import android.view.autofill.AutoFillType;
import android.view.autofill.AutoFillValue;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.CompletionInfo;
@@ -790,6 +789,11 @@
Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ // TextView is important by default, unless app developer overrode attribute.
+ if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+ setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
+ }
+
mText = "";
final Resources res = getResources();
@@ -10018,9 +10022,8 @@
}
@Override
- @Nullable
- public AutoFillType getAutoFillType() {
- return isTextEditable() ? AutoFillType.forText() : null;
+ public @AutofillType int getAutofillType() {
+ return isTextEditable() ? AUTOFILL_TYPE_TEXT : AUTOFILL_TYPE_NONE;
}
@Override
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 1df202e..3a19f21 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -32,7 +32,6 @@
import android.view.ViewStructure;
import android.view.accessibility.AccessibilityEvent;
import android.view.autofill.AutoFillManager;
-import android.view.autofill.AutoFillType;
import android.view.autofill.AutoFillValue;
import com.android.internal.R;
@@ -112,6 +111,11 @@
public TimePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ // DatePicker is important by default, unless app developer overrode attribute.
+ if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+ setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
+ }
+
final TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.TimePicker, defStyleAttr, defStyleRes);
final boolean isDialogMode = a.getBoolean(R.styleable.TimePicker_dialogMode, false);
@@ -530,8 +534,8 @@
}
@Override
- public AutoFillType getAutoFillType() {
- return isEnabled() ? AutoFillType.forDate() : null;
+ public @AutofillType int getAutofillType() {
+ return isEnabled() ? AUTOFILL_TYPE_DATE : AUTOFILL_TYPE_NONE;
}
@Override
diff --git a/core/java/com/android/internal/alsa/AlsaDevicesParser.java b/core/java/com/android/internal/alsa/AlsaDevicesParser.java
index 81b7943..5203723 100644
--- a/core/java/com/android/internal/alsa/AlsaDevicesParser.java
+++ b/core/java/com/android/internal/alsa/AlsaDevicesParser.java
@@ -184,7 +184,7 @@
}
}
- private ArrayList<AlsaDeviceRecord> mDeviceRecords = new ArrayList<AlsaDeviceRecord>();
+ private final ArrayList<AlsaDeviceRecord> mDeviceRecords = new ArrayList<AlsaDeviceRecord>();
public AlsaDevicesParser() {}
@@ -199,9 +199,11 @@
//
// Predicates
//
+/*
public boolean hasPlaybackDevices() {
return mHasPlaybackDevices;
}
+*/
public boolean hasPlaybackDevices(int card) {
for (AlsaDeviceRecord deviceRecord : mDeviceRecords) {
@@ -214,9 +216,11 @@
return false;
}
+/*
public boolean hasCaptureDevices() {
return mHasCaptureDevices;
}
+*/
public boolean hasCaptureDevices(int card) {
for (AlsaDeviceRecord deviceRecord : mDeviceRecords) {
@@ -229,9 +233,11 @@
return false;
}
+/*
public boolean hasMIDIDevices() {
return mHasMIDIDevices;
}
+*/
public boolean hasMIDIDevices(int card) {
for (AlsaDeviceRecord deviceRecord : mDeviceRecords) {
diff --git a/core/java/com/android/internal/alsa/LineTokenizer.java b/core/java/com/android/internal/alsa/LineTokenizer.java
index 43047a9..b395da9 100644
--- a/core/java/com/android/internal/alsa/LineTokenizer.java
+++ b/core/java/com/android/internal/alsa/LineTokenizer.java
@@ -23,7 +23,7 @@
public class LineTokenizer {
public static final int kTokenNotFound = -1;
- private String mDelimiters = "";
+ private final String mDelimiters;
public LineTokenizer(String delimiters) {
mDelimiters = delimiters;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 85aa6e6..2aeddb3 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -3706,6 +3706,20 @@
public void noteScreenStateLocked(int state) {
state = mPretendScreenOff ? Display.STATE_OFF : state;
+
+ // Battery stats relies on there being 4 states. To accommodate this, new states beyond the
+ // original 4 are mapped to one of the originals.
+ if (state > MAX_TRACKED_SCREEN_STATE) {
+ switch (state) {
+ case Display.STATE_VR:
+ state = Display.STATE_ON;
+ break;
+ default:
+ Slog.wtf(TAG, "Unknown screen state (not mapped): " + state);
+ break;
+ }
+ }
+
if (mScreenState != state) {
recordDailyStatsIfNeededLocked(true);
final int oldState = mScreenState;
@@ -3715,9 +3729,9 @@
if (state != Display.STATE_UNKNOWN) {
int stepState = state-1;
- if (stepState < 4) {
- mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
- mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
+ if ((stepState & STEP_LEVEL_MODE_SCREEN_STATE) == stepState) {
+ mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
+ mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
} else {
Slog.wtf(TAG, "Unexpected screen state: " + state);
}
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index 5a50fbf..78e8797 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -35,6 +35,8 @@
import android.util.Slog;
import android.util.Xml;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
@@ -46,6 +48,8 @@
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -83,6 +87,12 @@
private static final File lastHeaderFile = new File(
Environment.getDataSystemDirectory(), LAST_HEADER_FILE);
+ // example: fs_stat,/dev/block/platform/soc/by-name/userdata,0x5
+ private static final String FS_STAT_PATTERN = "fs_stat,[^,]*/([^/,]+),(0x[0-9a-fA-F]+)";
+ // ro.boottime.init.mount_all. + postfix for mount_all duration
+ private static final String[] MOUNT_DURATION_PROPS_POSTFIX =
+ new String[] { "early", "default", "late" };
+
@Override
public void onReceive(final Context context, Intent intent) {
// Log boot events in the background to avoid blocking the main thread with I/O
@@ -200,10 +210,11 @@
addFileToDropBox(db, timestamps, headers, "/cache/recovery/last_kmsg",
-LOG_SIZE, "SYSTEM_RECOVERY_KMSG");
addAuditErrorsToDropBox(db, timestamps, headers, -LOG_SIZE, "SYSTEM_AUDIT");
- addFsckErrorsToDropBox(db, timestamps, headers, -LOG_SIZE, "SYSTEM_FSCK");
} else {
if (db != null) db.addText("SYSTEM_RESTART", headers);
}
+ addFsckErrorsToDropBoxAndLogFsStat(db, timestamps, headers, -LOG_SIZE, "SYSTEM_FSCK");
+ logFsMountTime();
// Scan existing tombstones (in case any new ones appeared)
File[] tombstoneFiles = TOMBSTONE_DIR.listFiles();
@@ -297,11 +308,14 @@
db.addText(tag, headers + sb.toString());
}
- private static void addFsckErrorsToDropBox(DropBoxManager db,
+ private static void addFsckErrorsToDropBoxAndLogFsStat(DropBoxManager db,
HashMap<String, Long> timestamps, String headers, int maxSize, String tag)
throws IOException {
- boolean upload_needed = false;
- if (db == null || !db.isTagEnabled(tag)) return; // Logging disabled
+ boolean uploadEnabled = true;
+ if (db == null || !db.isTagEnabled(tag)) {
+ uploadEnabled = false;
+ }
+ boolean uploadNeeded = false;
Slog.i(TAG, "Checking for fsck errors");
File file = new File("/dev/fscklogs/log");
@@ -310,14 +324,21 @@
String log = FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n");
StringBuilder sb = new StringBuilder();
- for (String line : log.split("\n")) {
+ Pattern pattern = Pattern.compile(FS_STAT_PATTERN);
+ for (String line : log.split("\n")) { // should check all lines
if (line.contains("FILE SYSTEM WAS MODIFIED")) {
- upload_needed = true;
- break;
+ uploadNeeded = true;
+ } else if (line.contains("fs_stat")){
+ Matcher matcher = pattern.matcher(line);
+ if (matcher.find()) {
+ handleFsckFsStat(matcher);
+ } else {
+ Slog.w(TAG, "cannot parse fs_stat:" + line);
+ }
}
}
- if (upload_needed) {
+ if (uploadEnabled && uploadNeeded ) {
addFileToDropBox(db, timestamps, headers, "/dev/fscklogs/log", maxSize, tag);
}
@@ -325,6 +346,29 @@
file.delete();
}
+ private static void logFsMountTime() {
+ for (String propPostfix : MOUNT_DURATION_PROPS_POSTFIX) {
+ int duration = SystemProperties.getInt("ro.boottime.init.mount_all." + propPostfix, 0);
+ if (duration != 0) {
+ MetricsLogger.histogram(null, "boot_mount_all_duration_" + propPostfix, duration);
+ }
+ }
+ }
+
+ private static void handleFsckFsStat(Matcher match) {
+ String partition = match.group(1);
+ int stat;
+ try {
+ stat = Integer.decode(match.group(2));
+ } catch (NumberFormatException e) {
+ Slog.w(TAG, "cannot parse fs_stat: partition:" + partition + " stat:" + match.group(2));
+ return;
+ }
+
+ MetricsLogger.histogram(null, "boot_fs_stat_" + partition, stat);
+ Slog.i(TAG, "fs_stat, partition:" + partition + " stat:" + match.group(2));
+ }
+
private static HashMap<String, Long> readTimestamps() {
synchronized (sFile) {
HashMap<String, Long> timestamps = new HashMap<String, Long>();
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index e4493b1..f852194 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -8,6 +8,8 @@
#include "SkImageInfo.h"
#include "SkColor.h"
#include "SkColorPriv.h"
+#include "SkColorSpace.h"
+#include "SkColorSpaceXform.h"
#include "SkHalf.h"
#include "SkMatrix44.h"
#include "SkPM4f.h"
@@ -29,6 +31,7 @@
#include "core_jni_helpers.h"
#include <jni.h>
+#include <string.h>
#include <memory>
#include <string>
@@ -448,11 +451,32 @@
// reset to to actual choice from caller
dst = dstBitmap.getAddr(x, y);
- // now copy/convert each scanline
- for (int y = 0; y < height; y++) {
- proc(dst, src, width, x, y);
- src += srcStride;
- dst = (char*)dst + dstBitmap.rowBytes();
+
+ SkColorSpace* colorSpace = dstBitmap.colorSpace();
+ if (GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
+ // now copy/convert each scanline
+ for (int y = 0; y < height; y++) {
+ proc(dst, src, width, x, y);
+ src += srcStride;
+ dst = (char*)dst + dstBitmap.rowBytes();
+ }
+ } else {
+ auto sRGB = SkColorSpace::MakeSRGB();
+ auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
+
+ std::unique_ptr<SkColor[]> row(new SkColor[width]);
+
+ // now copy/convert each scanline
+ for (int y = 0; y < height; y++) {
+ memcpy(row.get(), src, sizeof(SkColor) * width);
+ xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(),
+ SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(), width,
+ SkAlphaType::kUnpremul_SkAlphaType);
+
+ proc(dst, row.get(), width, x, y);
+ src += srcStride;
+ dst = (char*)dst + dstBitmap.rowBytes();
+ }
}
dstBitmap.notifyPixelsChanged();
@@ -1179,12 +1203,7 @@
if (!bitmapHolder.valid()) return JNI_TRUE;
SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
- return colorSpace == nullptr ||
- colorSpace == SkColorSpace::MakeSRGB().get() ||
- colorSpace == SkColorSpace::MakeRGB(
- SkColorSpace::kSRGB_RenderTargetGamma,
- SkColorSpace::kSRGB_Gamut,
- SkColorSpace::kNonLinearBlending_ColorSpaceFlag).get();
+ return GraphicsJNI::isColorSpaceSRGB(colorSpace);
}
static jboolean Bitmap_getColorSpace(JNIEnv* env, jobject, jlong bitmapHandle,
@@ -1246,6 +1265,16 @@
SkColor dst[1];
proc(dst, src, 1, bitmap.getColorTable());
+
+ SkColorSpace* colorSpace = bitmap.colorSpace();
+ if (!GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
+ auto sRGB = SkColorSpace::MakeSRGB();
+ auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
+ xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0],
+ SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0], 1,
+ SkAlphaType::kUnpremul_SkAlphaType);
+ }
+
return static_cast<jint>(dst[0]);
}
@@ -1268,11 +1297,30 @@
SkColorTable* ctable = bitmap.getColorTable();
jint* dst = env->GetIntArrayElements(pixelArray, NULL);
SkColor* d = (SkColor*)dst + offset;
- while (--height >= 0) {
- proc(d, src, width, ctable);
- d += stride;
- src = (void*)((const char*)src + bitmap.rowBytes());
+
+ SkColorSpace* colorSpace = bitmap.colorSpace();
+ if (GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
+ while (--height >= 0) {
+ proc(d, src, width, ctable);
+ d += stride;
+ src = (void*)((const char*)src + bitmap.rowBytes());
+ }
+ } else {
+ auto sRGB = SkColorSpace::MakeSRGB();
+ auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
+
+ while (--height >= 0) {
+ proc(d, src, width, ctable);
+
+ xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, d,
+ SkColorSpaceXform::kBGRA_8888_ColorFormat, d, width,
+ SkAlphaType::kUnpremul_SkAlphaType);
+
+ d += stride;
+ src = (void*)((const char*)src + bitmap.rowBytes());
+ }
}
+
env->ReleaseIntArrayElements(pixelArray, dst, 0);
}
@@ -1293,6 +1341,15 @@
return;
}
+ SkColorSpace* colorSpace = bitmap.colorSpace();
+ if (!GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
+ auto sRGB = SkColorSpace::MakeSRGB();
+ auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
+ xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &color,
+ SkColorSpaceXform::kBGRA_8888_ColorFormat, &color, 1,
+ SkAlphaType::kUnpremul_SkAlphaType);
+ }
+
proc(bitmap.getAddr(x, y), &color, 1, x, y);
bitmap.notifyPixelsChanged();
}
diff --git a/core/jni/android/graphics/GraphicBuffer.cpp b/core/jni/android/graphics/GraphicBuffer.cpp
index e661c21..73e53c6 100644
--- a/core/jni/android/graphics/GraphicBuffer.cpp
+++ b/core/jni/android/graphics/GraphicBuffer.cpp
@@ -30,8 +30,6 @@
#include <ui/GraphicBuffer.h>
#include <ui/PixelFormat.h>
-#include <gui/IGraphicBufferAlloc.h>
-#include <gui/ISurfaceComposer.h>
#include <hwui/Bitmap.h>
#include <SkCanvas.h>
@@ -111,21 +109,14 @@
static jlong android_graphics_GraphicBuffer_create(JNIEnv* env, jobject clazz,
jint width, jint height, jint format, jint usage) {
- sp<ISurfaceComposer> composer(ComposerService::getComposerService());
- sp<IGraphicBufferAlloc> alloc(composer->createGraphicBufferAlloc());
- if (alloc == NULL) {
- if (kDebugGraphicBuffer) {
- ALOGW("createGraphicBufferAlloc() failed in GraphicBuffer.create()");
- }
- return NULL;
- }
+ sp<GraphicBuffer> buffer = new GraphicBuffer(
+ uint32_t(width), uint32_t(height), PixelFormat(format), uint32_t(usage),
+ std::string("android_graphics_GraphicBuffer_create pid [") +
+ std::to_string(getpid()) +"]");
- status_t error;
- sp<GraphicBuffer> buffer(alloc->createGraphicBuffer(width, height, format, 1, usage, &error));
- if (buffer == NULL) {
- if (kDebugGraphicBuffer) {
- ALOGW("createGraphicBuffer() failed in GraphicBuffer.create()");
- }
+ status_t error = buffer->initCheck();
+ if (error < 0) {
+ ALOGW_IF(kDebugGraphicBuffer, "createGraphicBuffer() failed in GraphicBuffer.create()");
return NULL;
}
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 5d73101..7c56c7b 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -460,6 +460,15 @@
}
}
+bool GraphicsJNI::isColorSpaceSRGB(SkColorSpace* colorSpace) {
+ return colorSpace == nullptr
+ || colorSpace == SkColorSpace::MakeSRGB().get()
+ || colorSpace == SkColorSpace::MakeRGB(
+ SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kSRGB_Gamut,
+ SkColorSpace::kNonLinearBlending_ColorSpaceFlag).get();
+}
+
///////////////////////////////////////////////////////////////////////////////
bool HeapAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
mStorage = android::Bitmap::allocateHeapBitmap(bitmap, ctable);
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 8a1ef6e..7d7c881 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -111,6 +111,7 @@
static sk_sp<SkColorSpace> defaultColorSpace();
static sk_sp<SkColorSpace> linearColorSpace();
static sk_sp<SkColorSpace> colorSpaceForType(SkColorType type);
+ static bool isColorSpaceSRGB(SkColorSpace* colorSpace);
};
class HeapAllocator : public SkBRDAllocator {
diff --git a/core/jni/android/graphics/PathEffect.cpp b/core/jni/android/graphics/PathEffect.cpp
index e801da3..a4992de 100644
--- a/core/jni/android/graphics/PathEffect.cpp
+++ b/core/jni/android/graphics/PathEffect.cpp
@@ -20,7 +20,7 @@
jlong outerHandle, jlong innerHandle) {
SkPathEffect* outer = reinterpret_cast<SkPathEffect*>(outerHandle);
SkPathEffect* inner = reinterpret_cast<SkPathEffect*>(innerHandle);
- SkPathEffect* effect = SkComposePathEffect::Make(sk_ref_sp(outer),
+ SkPathEffect* effect = SkPathEffect::MakeCompose(sk_ref_sp(outer),
sk_ref_sp(inner)).release();
return reinterpret_cast<jlong>(effect);
}
@@ -29,7 +29,7 @@
jlong firstHandle, jlong secondHandle) {
SkPathEffect* first = reinterpret_cast<SkPathEffect*>(firstHandle);
SkPathEffect* second = reinterpret_cast<SkPathEffect*>(secondHandle);
- SkPathEffect* effect = SkSumPathEffect::Make(sk_ref_sp(first),
+ SkPathEffect* effect = SkPathEffect::MakeSum(sk_ref_sp(first),
sk_ref_sp(second)).release();
return reinterpret_cast<jlong>(effect);
}
diff --git a/core/jni/android_hardware_HardwareBuffer.cpp b/core/jni/android_hardware_HardwareBuffer.cpp
index b91bd5c..ed0ab60 100644
--- a/core/jni/android_hardware_HardwareBuffer.cpp
+++ b/core/jni/android_hardware_HardwareBuffer.cpp
@@ -31,8 +31,6 @@
#include <binder/Parcel.h>
#include <ui/GraphicBuffer.h>
-#include <gui/IGraphicBufferAlloc.h>
-#include <gui/ISurfaceComposer.h>
#include <private/gui/ComposerService.h>
#include <hardware/gralloc1.h>
@@ -73,15 +71,6 @@
static jlong android_hardware_HardwareBuffer_create(JNIEnv* env, jobject clazz,
jint width, jint height, jint format, jint layers, jlong usage) {
- sp<ISurfaceComposer> composer(ComposerService::getComposerService());
- sp<IGraphicBufferAlloc> alloc(composer->createGraphicBufferAlloc());
- if (alloc == NULL) {
- if (kDebugGraphicBuffer) {
- ALOGW("createGraphicBufferAlloc() failed in HardwareBuffer.create()");
- }
- return NULL;
- }
-
// TODO: update createGraphicBuffer to take two 64-bit values.
int pixelFormat = android_hardware_HardwareBuffer_convertToPixelFormat(format);
if (pixelFormat == 0) {
@@ -92,14 +81,14 @@
}
uint64_t producerUsage = 0;
uint64_t consumerUsage = 0;
- android_hardware_HardwareBuffer_convertToGrallocUsageBits(&producerUsage, &consumerUsage, usage,
- 0);
- status_t error;
- sp<GraphicBuffer> buffer(alloc->createGraphicBuffer(width, height, pixelFormat,
- layers, producerUsage, consumerUsage,
- std::string("HardwareBuffer pid [") + std::to_string(getpid()) +"]",
- &error));
- if (buffer == NULL) {
+ android_hardware_HardwareBuffer_convertToGrallocUsageBits(
+ &producerUsage, &consumerUsage, usage, 0);
+
+ sp<GraphicBuffer> buffer = new GraphicBuffer(width, height, pixelFormat, layers,
+ producerUsage, consumerUsage,
+ std::string("HardwareBuffer pid [") + std::to_string(getpid()) +"]");
+ status_t error = buffer->initCheck();
+ if (error < 0) {
if (kDebugGraphicBuffer) {
ALOGW("createGraphicBuffer() failed in HardwareBuffer.create()");
}
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 2439b82..15b2f35 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -49,12 +49,6 @@
namespace android {
-static jclass gArrayListClass;
-static struct {
- jmethodID size;
- jmethodID get;
-} gArrayListMethods;
-
static jclass gErrorClass;
static struct fields_t {
@@ -239,7 +233,6 @@
static void JHwBinder_native_registerService(
JNIEnv *env,
jobject thiz,
- jobject interfaceChainArrayList,
jstring serviceNameObj) {
if (serviceNameObj == NULL) {
jniThrowException(env, "java/lang/NullPointerException", NULL);
@@ -251,24 +244,6 @@
return; // XXX exception already pending?
}
- jint numInterfaces = env->CallIntMethod(interfaceChainArrayList,
- gArrayListMethods.size);
- hidl_string *strings = new hidl_string[numInterfaces];
-
- for (jint i = 0; i < numInterfaces; i++) {
- jstring strObj = static_cast<jstring>(
- env->CallObjectMethod(interfaceChainArrayList,
- gArrayListMethods.get,
- i)
- );
- const char * str = env->GetStringUTFChars(strObj, nullptr);
- strings[i] = hidl_string(str);
- env->ReleaseStringUTFChars(strObj, str);
- }
-
- hidl_vec<hidl_string> interfaceChain;
- interfaceChain.setToExternal(strings, numInterfaces, true /* shouldOwn */);
-
sp<hardware::IBinder> binder = JHwBinder::GetNativeContext(env, thiz);
/* TODO(b/33440494) this is not right */
@@ -282,7 +257,7 @@
return;
}
- Return<bool> ret = manager->add(interfaceChain, serviceName, base);
+ Return<bool> ret = manager->add(serviceName, base);
env->ReleaseStringUTFChars(serviceNameObj, serviceName);
serviceName = NULL;
@@ -385,7 +360,7 @@
"(IL" PACKAGE_PATH "/HwParcel;L" PACKAGE_PATH "/HwParcel;I)V",
(void *)JHwBinder_native_transact },
- { "registerService", "(Ljava/util/ArrayList;Ljava/lang/String;)V",
+ { "registerService", "(Ljava/lang/String;)V",
(void *)JHwBinder_native_registerService },
{ "getService", "(Ljava/lang/String;Ljava/lang/String;)L" PACKAGE_PATH "/IHwBinder;",
@@ -395,11 +370,6 @@
namespace android {
int register_android_os_HwBinder(JNIEnv *env) {
- jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
- gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
- gArrayListMethods.size = GetMethodIDOrDie(env, arrayListClass, "size", "()I");
- gArrayListMethods.get = GetMethodIDOrDie(env, arrayListClass, "get", "(I)Ljava/lang/Object;");
-
jclass errorClass = FindClassOrDie(env, "java/lang/Error");
gErrorClass = MakeGlobalRefOrDie(env, errorClass);
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index f8d5241..b3cb2c7 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2339,6 +2339,17 @@
<flag name="creditCardExpirationDay" value="0x1000" />
</attr>
+ <!-- Hints the Android System whether the view node associated with this View should be
+ included in a view structure used for autofill purposes. -->
+ <attr name="importantForAutofill">
+ <!-- Let the Android System use its heuristics to determine if the view is important for autofill. -->
+ <flag name="auto" value="0" />
+ <!-- Hint the Android System that this view is important for autofill. -->
+ <flag name="yes" value="0x1" />
+ <!-- Hint the Android System that this view is *not* important for autofill. -->
+ <flag name="no" value="0x2" />
+ </attr>
+
<!-- Boolean that controls whether a view can take focus while in touch mode.
If this is true for a view, that view can gain focus when clicked on, and can keep
focus if another view is clicked on that doesn't have this attribute set to true. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 0d90cd2..b664448 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2760,8 +2760,9 @@
=============================================================== -->
<eat-comment />
- <public-group type="attr" first-id="0x01010531">
- <public name="fontStyle" />
+ <public type="attr" name="visibleToInstantApps" id="0x01010531" />
+
+ <public-group type="attr" first-id="0x01010532">
<public name="font" />
<public name="fontWeight" />
<public name="tooltipText" />
@@ -2775,7 +2776,7 @@
<public name="layout_marginVertical" />
<public name="paddingHorizontal" />
<public name="paddingVertical" />
- <public name="visibleToInstantApps" />
+ <public name="fontStyle" />
<public name="keyboardNavigationCluster" />
<public name="targetProcess" />
<public name="nextClusterForward" />
@@ -2803,6 +2804,7 @@
<public name="requiredNotFeature" />
<public name="autoFillHint" />
<public name="fontProviderPackage" />
+ <public name="importantForAutofill" />
</public-group>
<public-group type="style" first-id="0x010302e0">
diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index 5c7da70..3a751af 100644
--- a/core/tests/coretests/src/android/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -16,6 +16,7 @@
package android.os;
+import static android.os.FileUtils.roundStorageSize;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
@@ -25,10 +26,10 @@
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
-import com.google.android.collect.Sets;
-
import libcore.io.IoUtils;
+import com.google.android.collect.Sets;
+
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
@@ -312,25 +313,31 @@
}
public void testRoundStorageSize() throws Exception {
- final long M128 = 134217728L;
- final long M256 = M128 * 2;
- final long M512 = M256 * 2;
- final long M1024 = M512 * 2;
- final long G16 = M1024 * 16;
- final long G32 = M1024 * 32;
- final long G64 = M1024 * 64;
+ final long M128 = 128000000L;
+ final long M256 = 256000000L;
+ final long M512 = 512000000L;
+ final long G1 = 1000000000L;
+ final long G2 = 2000000000L;
+ final long G16 = 16000000000L;
+ final long G32 = 32000000000L;
+ final long G64 = 64000000000L;
- assertEquals(M128, FileUtils.roundStorageSize(M128));
- assertEquals(M256, FileUtils.roundStorageSize(M128 + 1));
- assertEquals(M256, FileUtils.roundStorageSize(M256 - 1));
- assertEquals(M256, FileUtils.roundStorageSize(M256));
- assertEquals(M512, FileUtils.roundStorageSize(M256 + 1));
+ assertEquals(M128, roundStorageSize(M128));
+ assertEquals(M256, roundStorageSize(M128 + 1));
+ assertEquals(M256, roundStorageSize(M256 - 1));
+ assertEquals(M256, roundStorageSize(M256));
+ assertEquals(M512, roundStorageSize(M256 + 1));
+ assertEquals(M512, roundStorageSize(M512 - 1));
+ assertEquals(M512, roundStorageSize(M512));
+ assertEquals(G1, roundStorageSize(M512 + 1));
+ assertEquals(G1, roundStorageSize(G1));
+ assertEquals(G2, roundStorageSize(G1 + 1));
- assertEquals(G16, FileUtils.roundStorageSize(G16));
- assertEquals(G32, FileUtils.roundStorageSize(G16 + 1));
- assertEquals(G32, FileUtils.roundStorageSize(G32 - 1));
- assertEquals(G32, FileUtils.roundStorageSize(G32));
- assertEquals(G64, FileUtils.roundStorageSize(G32 + 1));
+ assertEquals(G16, roundStorageSize(G16));
+ assertEquals(G32, roundStorageSize(G16 + 1));
+ assertEquals(G32, roundStorageSize(G32 - 1));
+ assertEquals(G32, roundStorageSize(G32));
+ assertEquals(G64, roundStorageSize(G32 + 1));
}
private static void assertNameEquals(String expected, File actual) {
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 9a64507..696d498 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -158,6 +158,7 @@
Settings.Global.DEVICE_DEMO_MODE,
Settings.Global.DEVICE_IDLE_CONSTANTS,
Settings.Global.DEVICE_IDLE_CONSTANTS_WATCH,
+ Settings.Global.BATTERY_SAVER_CONSTANTS,
Settings.Global.DEVICE_NAME,
Settings.Global.DEVICE_PROVISIONED,
Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED,
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 6bb8a2c..3d5ba79 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -522,7 +522,7 @@
* <p>The content of the bitmap is copied into the buffer as-is. This means
* that if this bitmap stores its pixels pre-multiplied
* (see {@link #isPremultiplied()}, the values in the buffer will also be
- * pre-multiplied.</p>
+ * pre-multiplied. The pixels remain in the color space of the bitmap.</p>
* <p>After this method returns, the current position of the buffer is
* updated: the position is incremented by the number of elements written
* in the buffer.</p>
@@ -562,7 +562,8 @@
* <p>Copy the pixels from the buffer, beginning at the current position,
* overwriting the bitmap's pixels. The data in the buffer is not changed
* in any way (unlike setPixels(), which converts from unpremultipled 32bit
- * to whatever the bitmap's native format is.</p>
+ * to whatever the bitmap's native format is. The pixels in the source
+ * buffer are assumed to be in the bitmap's color space.</p>
* <p>After this method returns, the current position of the buffer is
* updated: the position is incremented by the number of elements read from
* the buffer. If you need to read the bitmap from the buffer again you must
@@ -1495,7 +1496,8 @@
/**
* Returns the {@link Color} at the specified location. Throws an exception
* if x or y are out of bounds (negative or >= to the width or height
- * respectively). The returned color is a non-premultiplied ARGB value.
+ * respectively). The returned color is a non-premultiplied ARGB value in
+ * the {@link ColorSpace.Named#SRGB sRGB} color space.
*
* @param x The x coordinate (0...width-1) of the pixel to return
* @param y The y coordinate (0...height-1) of the pixel to return
@@ -1517,7 +1519,8 @@
* a packed int representing a {@link Color}. The stride parameter allows
* the caller to allow for gaps in the returned pixels array between
* rows. For normal packed results, just pass width for the stride value.
- * The returned colors are non-premultiplied ARGB values.
+ * The returned colors are non-premultiplied ARGB values in the
+ * {@link ColorSpace.Named#SRGB sRGB} color space.
*
* @param pixels The array to receive the bitmap's colors
* @param offset The first index to write into pixels[]
@@ -1610,7 +1613,8 @@
/**
* <p>Write the specified {@link Color} into the bitmap (assuming it is
* mutable) at the x,y coordinate. The color must be a
- * non-premultiplied ARGB value.</p>
+ * non-premultiplied ARGB value in the {@link ColorSpace.Named#SRGB sRGB}
+ * color space.</p>
*
* @param x The x coordinate of the pixel to replace (0...width-1)
* @param y The y coordinate of the pixel to replace (0...height-1)
@@ -1632,7 +1636,7 @@
/**
* <p>Replace pixels in the bitmap with the colors in the array. Each element
* in the array is a packed int representing a non-premultiplied ARGB
- * {@link Color}.</p>
+ * {@link Color} in the {@link ColorSpace.Named#SRGB sRGB} color space.</p>
*
* @param pixels The colors to write to the bitmap
* @param offset The index of the first color to read from pixels[]
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 49b69eb..72a9f4e 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -30,8 +30,6 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include <gui/IGraphicBufferAlloc.h>
-#include <gui/ISurfaceComposer.h>
#include <private/gui/ComposerService.h>
#include <binder/IServiceManager.h>
#include <ui/PixelFormat.h>
@@ -219,13 +217,6 @@
renderThread.eglManager().initialize();
uirenderer::Caches& caches = uirenderer::Caches::getInstance();
- sp<ISurfaceComposer> composer(ComposerService::getComposerService());
- sp<IGraphicBufferAlloc> alloc(composer->createGraphicBufferAlloc());
- if (alloc == NULL) {
- ALOGW("createGraphicBufferAlloc() failed in GraphicBuffer.create()");
- return nullptr;
- }
-
const SkImageInfo& info = skBitmap.info();
if (info.colorType() == kUnknown_SkColorType || info.colorType() == kAlpha_8_SkColorType) {
ALOGW("unable to create hardware bitmap of colortype: %d", info.colorType());
@@ -240,12 +231,14 @@
needSRGB, &internalFormat, &format, &type);
PixelFormat pixelFormat = internalFormatToPixelFormat(internalFormat);
- status_t error;
- sp<GraphicBuffer> buffer = alloc->createGraphicBuffer(info.width(), info.height(), pixelFormat,
- 1, GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_WRITE_NEVER
- | GraphicBuffer::USAGE_SW_READ_NEVER , &error);
+ sp<GraphicBuffer> buffer = new GraphicBuffer(info.width(), info.height(), pixelFormat,
+ GraphicBuffer::USAGE_HW_TEXTURE |
+ GraphicBuffer::USAGE_SW_WRITE_NEVER |
+ GraphicBuffer::USAGE_SW_READ_NEVER,
+ std::string("Bitmap::allocateHardwareBitmap pid [") + std::to_string(getpid()) + "]");
- if (!buffer.get()) {
+ status_t error = buffer->initCheck();
+ if (error < 0) {
ALOGW("createGraphicBuffer() failed in GraphicBuffer.create()");
return nullptr;
}
diff --git a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
index 83b01e9..a461426 100644
--- a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
+++ b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
@@ -17,10 +17,6 @@
#include "TestSceneBase.h"
#include "utils/Color.h"
-#include <gui/IGraphicBufferAlloc.h>
-#include <gui/ISurfaceComposer.h>
-#include <private/gui/ComposerService.h>
-#include <binder/IServiceManager.h>
#include <ui/PixelFormat.h>
#include <SkGradientShader.h>
#include <SkImagePriv.h>
@@ -39,14 +35,11 @@
void createContent(int width, int height, Canvas& canvas) override {
canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
- status_t error;
- sp<ISurfaceComposer> composer(ComposerService::getComposerService());
- sp<IGraphicBufferAlloc> alloc(composer->createGraphicBufferAlloc());
uint32_t usage = GraphicBuffer::USAGE_HW_TEXTURE
| GraphicBuffer::USAGE_SW_READ_NEVER
| GRALLOC_USAGE_SW_WRITE_RARELY;
- sp<GraphicBuffer> buffer = alloc->createGraphicBuffer(400, 200, PIXEL_FORMAT_RGBA_8888, 1,
- usage, &error);
+
+ sp<GraphicBuffer> buffer = new GraphicBuffer(400, 200, PIXEL_FORMAT_RGBA_8888, usage);
unsigned char* pixels = nullptr;
buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, ((void**)&pixels));
@@ -88,4 +81,4 @@
return image->makeShader(SkShader::TileMode::kClamp_TileMode,
SkShader::TileMode::kClamp_TileMode);
}
-};
\ No newline at end of file
+};
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 3ac4c34..c157a47 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -1119,6 +1119,10 @@
sampleRates = new int[] { 8000 };
bitRates = Range.create(13000, 13000);
maxChannels = 1;
+ } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AC3)) {
+ maxChannels = 6;
+ } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_EAC3)) {
+ maxChannels = 16;
} else {
Log.w(TAG, "Unsupported mime " + mime);
mParent.mError |= ERROR_UNSUPPORTED;
diff --git a/media/java/android/media/VolumeShaper.java b/media/java/android/media/VolumeShaper.java
index cb27d10..796d6f3 100644
--- a/media/java/android/media/VolumeShaper.java
+++ b/media/java/android/media/VolumeShaper.java
@@ -25,6 +25,7 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.AutoCloseable;
import java.lang.ref.WeakReference;
+import java.util.Arrays;
import java.util.Objects;
/**
@@ -115,6 +116,7 @@
* @param configuration
* @param operation
* @return id a non-negative shaper id.
+ * @throws IllegalStateException if the player has been deallocated or is uninitialized.
*/
private int applyPlayer(
@NonNull VolumeShaper.Configuration configuration,
@@ -147,6 +149,7 @@
* Internal call to retrieve the current VolumeShaper state.
* @param id
* @return the current {@vode VolumeShaper.State}
+ * @throws IllegalStateException if the player has been deallocated or is uninitialized.
*/
private @NonNull VolumeShaper.State getStatePlayer(int id) {
final VolumeShaper.State state;
@@ -172,10 +175,10 @@
* <p>
* A {@code VolumeShaper.Configuration} is used by
* {@link VolumeAutomation#createVolumeShaper(Configuration)
- * VolumeAutomation#createVolumeShaper(Configuration)} to create
+ * VolumeAutomation.createVolumeShaper(Configuration)} to create
* a {@code VolumeShaper} and
* by {@link VolumeShaper#replace(Configuration, Operation, boolean)
- * VolumeShaper#replace(Configuration, Operation, boolean)}
+ * VolumeShaper.replace(Configuration, Operation, boolean)}
* to replace an existing {@code configuration}.
*/
public static final class Configuration implements Parcelable {
@@ -365,31 +368,34 @@
private final int mId;
// valid when mType is TYPE_SCALE
- private final int mInterpolatorType;
private final int mOptionFlags;
private final double mDurationMs;
+ private final int mInterpolatorType;
private final float[] mTimes;
private final float[] mVolumes;
@Override
public String toString() {
- return "VolumeShaper.Configuration["
- + "mType=" + mType
+ return "VolumeShaper.Configuration{"
+ + "mType = " + mType
+ + ", mId = " + mId
+ (mType == TYPE_ID
- ? ",mId" + mId
- : ",mInterpolatorType=" + mInterpolatorType
- + ",mOptionFlags=" + mOptionFlags
- + ",mDurationMs=" + mDurationMs
- + ",mTimes[]=" + mTimes
- + ",mVolumes[]=" + mVolumes
- + "]");
+ ? "}"
+ : ", mOptionFlags = 0x" + Integer.toHexString(mOptionFlags).toUpperCase()
+ + ", mDurationMs = " + mDurationMs
+ + ", mInterpolatorType = " + mInterpolatorType
+ + ", mTimes[] = " + Arrays.toString(mTimes)
+ + ", mVolumes[] = " + Arrays.toString(mVolumes)
+ + "}");
}
@Override
public int hashCode() {
return mType == TYPE_ID
? Objects.hash(mType, mId)
- : Objects.hash(mType, mInterpolatorType, mDurationMs, mTimes, mVolumes);
+ : Objects.hash(mType, mId,
+ mOptionFlags, mDurationMs, mInterpolatorType,
+ Arrays.hashCode(mTimes), Arrays.hashCode(mVolumes));
}
@Override
@@ -397,12 +403,17 @@
if (!(o instanceof Configuration)) return false;
if (o == this) return true;
final Configuration other = (Configuration) o;
- return mType == other.mType &&
- (mType == TYPE_ID ? mId == other.mId
- : mInterpolatorType == other.mInterpolatorType
- && mDurationMs == other.mDurationMs
- && mTimes == other.mTimes
- && mVolumes == other.mVolumes);
+ // Note that exact floating point equality may not be guaranteed
+ // for a theoretically idempotent operation; for example,
+ // there are many cases where a + b - b != a.
+ return mType == other.mType
+ && mId == other.mId
+ && (mType == TYPE_ID
+ || (mOptionFlags == other.mOptionFlags
+ && mDurationMs == other.mDurationMs
+ && mInterpolatorType == other.mInterpolatorType
+ && Arrays.equals(mTimes, other.mTimes)
+ && Arrays.equals(mVolumes, other.mVolumes)));
}
@Override
@@ -412,14 +423,22 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
+ // this needs to match the native VolumeShaper.Configuration parceling
dest.writeInt(mType);
dest.writeInt(mId);
if (mType != TYPE_ID) {
- dest.writeInt(mInterpolatorType);
dest.writeInt(mOptionFlags);
dest.writeDouble(mDurationMs);
- dest.writeFloatArray(mTimes);
- dest.writeFloatArray(mVolumes);
+ // this needs to match the native Interpolator parceling
+ dest.writeInt(mInterpolatorType);
+ dest.writeFloat(0.f); // first slope
+ dest.writeFloat(0.f); // last slope
+ // mTimes and mVolumes should have the same length.
+ dest.writeInt(mTimes.length);
+ for (int i = 0; i < mTimes.length; ++i) {
+ dest.writeFloat(mTimes[i]);
+ dest.writeFloat(mVolumes[i]);
+ }
}
}
@@ -427,19 +446,34 @@
= new Parcelable.Creator<VolumeShaper.Configuration>() {
@Override
public VolumeShaper.Configuration createFromParcel(Parcel p) {
+ // this needs to match the native VolumeShaper.Configuration parceling
final int type = p.readInt();
final int id = p.readInt();
if (type == TYPE_ID) {
return new VolumeShaper.Configuration(id);
} else {
+ final int optionFlags = p.readInt();
+ final double durationMs = p.readDouble();
+ // this needs to match the native Interpolator parceling
+ final int interpolatorType = p.readInt();
+ final float firstSlope = p.readFloat(); // ignored
+ final float lastSlope = p.readFloat(); // ignored
+ final int length = p.readInt();
+ final float[] times = new float[length];
+ final float[] volumes = new float[length];
+ for (int i = 0; i < length; ++i) {
+ times[i] = p.readFloat();
+ volumes[i] = p.readFloat();
+ }
+
return new VolumeShaper.Configuration(
type,
- id, // id
- p.readInt(), // interpolatorType
- p.readInt(), // optionFlags
- p.readDouble(), // durationMs
- p.createFloatArray(), // times
- p.createFloatArray()); // volumes
+ id,
+ optionFlags,
+ durationMs,
+ interpolatorType,
+ times,
+ volumes);
}
}
@@ -482,16 +516,16 @@
*/
private Configuration(@Type int type,
int id,
- @InterpolatorType int interpolatorType,
@OptionFlag int optionFlags,
double durationMs,
+ @InterpolatorType int interpolatorType,
@NonNull float[] times,
@NonNull float[] volumes) {
mType = type;
mId = id;
- mInterpolatorType = interpolatorType;
mOptionFlags = optionFlags;
mDurationMs = durationMs;
+ mInterpolatorType = interpolatorType;
// Builder should have cloned these arrays already.
mTimes = times;
mVolumes = volumes;
@@ -568,8 +602,12 @@
* @return null if no error, or the reason in a {@code String} for an error.
*/
private static @Nullable String checkCurveForErrors(
- @NonNull float[] times, @NonNull float[] volumes, boolean log) {
- if (times.length != volumes.length) {
+ @Nullable float[] times, @Nullable float[] volumes, boolean log) {
+ if (times == null) {
+ return "times array must be non-null";
+ } else if (volumes == null) {
+ return "volumes array must be non-null";
+ } else if (times.length != volumes.length) {
return "array length must match";
} else if (times.length < 2) {
return "array length must be at least 2";
@@ -605,7 +643,15 @@
return null; // no errors
}
- private static void checkValidVolume(float volume, boolean log) {
+ private static void checkCurveForErrorsAndThrowException(
+ @Nullable float[] times, @Nullable float[] volumes, boolean log) {
+ final String error = checkCurveForErrors(times, volumes, log);
+ if (error != null) {
+ throw new IllegalArgumentException(error);
+ }
+ }
+
+ private static void checkValidVolumeAndThrowException(float volume, boolean log) {
if (log) {
if (!(volume <= 0.f) /* handle nan */) {
throw new IllegalArgumentException("dbfs volume must be 0.f or less");
@@ -678,17 +724,22 @@
mOptionFlags = configuration.getAllOptionFlags();
mInterpolatorType = configuration.getInterpolatorType();
mDurationMs = configuration.getDurationMs();
- mTimes = configuration.getTimes();
- mVolumes = configuration.getVolumes();
+ mTimes = configuration.getTimes().clone();
+ mVolumes = configuration.getVolumes().clone();
}
/**
* @hide
- * Set the id for system defined shapers.
- * @param id
- * @return
+ * Set the {@code id} for system defined shapers.
+ * @param id the {@code id} to set. If non-negative, then it is used.
+ * If -1, then the system is expected to assign one.
+ * @return the same {@code Builder} instance.
+ * @throws IllegalArgumentException if {@code id} < -1.
*/
public @NonNull Builder setId(int id) {
+ if (id < -1) {
+ throw new IllegalArgumentException("invalid id: " + id);
+ }
mId = id;
return this;
}
@@ -789,11 +840,8 @@
*/
public @NonNull Builder setCurve(@NonNull float[] times, @NonNull float[] volumes) {
- String error = checkCurveForErrors(
+ checkCurveForErrorsAndThrowException(
times, volumes, (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0);
- if (error != null) {
- throw new IllegalArgumentException(error);
- }
mTimes = times.clone();
mVolumes = volumes.clone();
return this;
@@ -805,13 +853,19 @@
* to the start.
*
* @return the same {@code Builder} instance.
+ * @throws IllegalArgumentException if curve has not been set.
*/
public @NonNull Builder reflectTimes() {
+ checkCurveForErrorsAndThrowException(
+ mTimes, mVolumes, (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0);
int i;
for (i = 0; i < mTimes.length / 2; ++i) {
- float temp = mTimes[0];
+ float temp = mTimes[i];
mTimes[i] = 1.f - mTimes[mTimes.length - 1 - i];
mTimes[mTimes.length - 1 - i] = 1.f - temp;
+ temp = mVolumes[i];
+ mVolumes[i] = mVolumes[mVolumes.length - 1 - i];
+ mVolumes[mVolumes.length - 1 - i] = temp;
}
if ((mTimes.length & 1) != 0) {
mTimes[i] = 1.f - mTimes[i];
@@ -824,23 +878,24 @@
* becomes the min volume and vice versa.
*
* @return the same {@code Builder} instance.
+ * @throws IllegalArgumentException if curve has not been set.
*/
public @NonNull Builder invertVolumes() {
- if (mVolumes.length >= 2) {
- float min = mVolumes[0];
- float max = mVolumes[0];
- for (int i = 1; i < mVolumes.length; ++i) {
- if (mVolumes[i] < min) {
- min = mVolumes[i];
- } else if (mVolumes[i] > max) {
- max = mVolumes[i];
- }
+ checkCurveForErrorsAndThrowException(
+ mTimes, mVolumes, (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0);
+ float min = mVolumes[0];
+ float max = mVolumes[0];
+ for (int i = 1; i < mVolumes.length; ++i) {
+ if (mVolumes[i] < min) {
+ min = mVolumes[i];
+ } else if (mVolumes[i] > max) {
+ max = mVolumes[i];
}
+ }
- final float maxmin = max + min;
- for (int i = 0; i < mVolumes.length; ++i) {
- mVolumes[i] = maxmin - mVolumes[i];
- }
+ final float maxmin = max + min;
+ for (int i = 0; i < mVolumes.length; ++i) {
+ mVolumes[i] = maxmin - mVolumes[i];
}
return this;
}
@@ -853,11 +908,13 @@
*
* @param volume the target end volume to use.
* @return the same {@code Builder} instance.
- * @throws IllegalArgumentException if {@code volume} is not valid.
+ * @throws IllegalArgumentException if {@code volume}
+ * is not valid or if curve has not been set.
*/
public @NonNull Builder scaleToEndVolume(float volume) {
final boolean log = (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0;
- checkValidVolume(volume, log);
+ checkCurveForErrorsAndThrowException(mTimes, mVolumes, log);
+ checkValidVolumeAndThrowException(volume, log);
final float startVolume = mVolumes[0];
final float endVolume = mVolumes[mVolumes.length - 1];
if (endVolume == startVolume) {
@@ -885,11 +942,13 @@
*
* @param volume the target start volume to use.
* @return the same {@code Builder} instance.
- * @throws IllegalArgumentException if {@code volume} is not valid.
+ * @throws IllegalArgumentException if {@code volume}
+ * is not valid or if curve has not been set.
*/
public @NonNull Builder scaleToStartVolume(float volume) {
final boolean log = (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0;
- checkValidVolume(volume, log);
+ checkCurveForErrorsAndThrowException(mTimes, mVolumes, log);
+ checkValidVolumeAndThrowException(volume, log);
final float startVolume = mVolumes[0];
final float endVolume = mVolumes[mVolumes.length - 1];
if (endVolume == startVolume) {
@@ -911,16 +970,14 @@
/**
* Builds a new {@link VolumeShaper} object.
*
- * @return a new {@link VolumeShaper} object
+ * @return a new {@link VolumeShaper} object.
+ * @throws IllegalArgumentException if curve is not properly set.
*/
public @NonNull Configuration build() {
- String error = checkCurveForErrors(
+ checkCurveForErrorsAndThrowException(
mTimes, mVolumes, (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0);
- if (error != null) {
- throw new IllegalArgumentException(error);
- }
- return new Configuration(mType, mId, mInterpolatorType, mOptionFlags,
- mDurationMs, mTimes, mVolumes);
+ return new Configuration(mType, mId, mOptionFlags, mDurationMs,
+ mInterpolatorType, mTimes, mVolumes);
}
} // Configuration.Builder
} // Configuration
@@ -1011,10 +1068,10 @@
@Override
public String toString() {
- return "VolumeShaper.Operation["
- + "mFlags=" + mFlags
- + ",mReplaceId" + mReplaceId
- + "]";
+ return "VolumeShaper.Operation{"
+ + "mFlags = 0x" + Integer.toHexString(mFlags).toUpperCase()
+ + ", mReplaceId = " + mReplaceId
+ + "}";
}
@Override
@@ -1027,6 +1084,8 @@
if (!(o instanceof Operation)) return false;
if (o == this) return true;
final Operation other = (Operation) o;
+ // if xOffset (native field only) is brought into Java
+ // we need to do proper NaN comparison as that is allowed.
return mFlags == other.mFlags
&& mReplaceId == other.mReplaceId;
}
@@ -1038,17 +1097,24 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
+ // this needs to match the native VolumeShaper.Operation parceling
dest.writeInt(mFlags);
dest.writeInt(mReplaceId);
+ dest.writeFloat(Float.NaN); // xOffset (ignored at Java level)
}
public static final Parcelable.Creator<VolumeShaper.Operation> CREATOR
= new Parcelable.Creator<VolumeShaper.Operation>() {
@Override
public VolumeShaper.Operation createFromParcel(Parcel p) {
+ // this needs to match the native VolumeShaper.Operation parceling
+ final int flags = p.readInt();
+ final int replaceId = p.readInt();
+ final float xOffset = p.readFloat(); // ignored at Java level
+
return new VolumeShaper.Operation(
- p.readInt() // flags
- , p.readInt()); // replaceId
+ flags
+ , replaceId);
}
@Override
@@ -1154,6 +1220,7 @@
*
* @param flags new value for {@code flags}, consisting of ORed flags.
* @return the same {@code Builder} instance.
+ * @throws IllegalArgumentException if {@code flags} contains invalid set bits.
*/
private @NonNull Builder setFlags(@Flag int flags) {
if ((flags & ~FLAG_PUBLIC_ALL) != 0) {
@@ -1187,10 +1254,10 @@
@Override
public String toString() {
- return "VolumeShaper.State["
- + "mVolume=" + mVolume
- + ",mXOffset" + mXOffset
- + "]";
+ return "VolumeShaper.State{"
+ + "mVolume = " + mVolume
+ + ", mXOffset = " + mXOffset
+ + "}";
}
@Override
diff --git a/media/jni/android_media_VolumeShaper.h b/media/jni/android_media_VolumeShaper.h
index dbbc478..73498a2 100644
--- a/media/jni/android_media_VolumeShaper.h
+++ b/media/jni/android_media_VolumeShaper.h
@@ -29,9 +29,9 @@
jmethodID coConstructId;
jfieldID coTypeId;
jfieldID coIdId;
- jfieldID coInterpolatorTypeId;
jfieldID coOptionFlagsId;
jfieldID coDurationMsId;
+ jfieldID coInterpolatorTypeId;
jfieldID coTimesId;
jfieldID coVolumesId;
@@ -56,12 +56,12 @@
if (coClazz == nullptr) {
return;
}
- coConstructId = env->GetMethodID(coClazz, "<init>", "(IIIID[F[F)V");
+ coConstructId = env->GetMethodID(coClazz, "<init>", "(IIIDI[F[F)V");
coTypeId = env->GetFieldID(coClazz, "mType", "I");
coIdId = env->GetFieldID(coClazz, "mId", "I");
- coInterpolatorTypeId = env->GetFieldID(coClazz, "mInterpolatorType", "I");
coOptionFlagsId = env->GetFieldID(coClazz, "mOptionFlags", "I");
coDurationMsId = env->GetFieldID(coClazz, "mDurationMs", "D");
+ coInterpolatorTypeId = env->GetFieldID(coClazz, "mInterpolatorType", "I");
coTimesId = env->GetFieldID(coClazz, "mTimes", "[F");
coVolumesId = env->GetFieldID(coClazz, "mVolumes", "[F");
env->DeleteLocalRef(lclazz);
@@ -108,14 +108,14 @@
configuration->setId(
(int)env->GetIntField(jshaper, fields.coIdId));
if (configuration->getType() == VolumeShaper::Configuration::TYPE_SCALE) {
- configuration->setInterpolatorType(
- (VolumeShaper::Configuration::InterpolatorType)
- env->GetIntField(jshaper, fields.coInterpolatorTypeId));
configuration->setOptionFlags(
(VolumeShaper::Configuration::OptionFlag)
env->GetIntField(jshaper, fields.coOptionFlagsId));
configuration->setDurationMs(
(double)env->GetDoubleField(jshaper, fields.coDurationMsId));
+ configuration->setInterpolatorType(
+ (VolumeShaper::Configuration::InterpolatorType)
+ env->GetIntField(jshaper, fields.coInterpolatorTypeId));
// convert point arrays
jobject xobj = env->GetObjectField(jshaper, fields.coTimesId);
@@ -165,9 +165,9 @@
jvalue args[7];
args[0].i = (jint)configuration->getType();
args[1].i = (jint)configuration->getId();
- args[2].i = (jint)configuration->getInterpolatorType();
- args[3].i = (jint)configuration->getOptionFlags();
- args[4].d = (jdouble)configuration->getDurationMs();
+ args[2].i = (jint)configuration->getOptionFlags();
+ args[3].d = (jdouble)configuration->getDurationMs();
+ args[4].i = (jint)configuration->getInterpolatorType();
args[5].l = xarray;
args[6].l = yarray;
jobject jshaper = env->NewObjectA(fields.coClazz, fields.coConstructId, args);
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 23a8655..6394c64 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -77,8 +77,8 @@
mCm = ConnectivityManager.from(this);
mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
- mUserAgent = getIntent().getParcelableExtra(
- ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT);
+ mUserAgent =
+ getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT);
mUrl = getUrl();
if (mUrl == null) {
// getUrl() failed to parse the url provided in the intent: bail out in a way that
@@ -274,8 +274,17 @@
if (mUserAgent != null) {
urlConnection.setRequestProperty("User-Agent", mUserAgent);
}
+ // cannot read request header after connection
+ String requestHeader = urlConnection.getRequestProperties().toString();
+
urlConnection.getInputStream();
httpResponseCode = urlConnection.getResponseCode();
+ if (DBG) {
+ Log.d(TAG, "probe at " + mUrl +
+ " ret=" + httpResponseCode +
+ " request=" + requestHeader +
+ " headers=" + urlConnection.getHeaderFields());
+ }
} catch (IOException e) {
} finally {
if (urlConnection != null) urlConnection.disconnect();
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index fda3914..8f7efb5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -19,6 +19,8 @@
import android.app.ActivityManager;
import android.app.AppGlobals;
import android.app.Application;
+import android.app.usage.StorageStats;
+import android.app.usage.StorageStatsManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -92,6 +94,7 @@
final PackageManager mPm;
final IPackageManager mIpm;
final UserManager mUm;
+ final StorageStatsManager mStats;
final int mAdminRetrieveFlags;
final int mRetrieveFlags;
PackageIntentReceiver mPackageIntentReceiver;
@@ -111,6 +114,7 @@
final ArrayList<AppEntry> mAppEntries = new ArrayList<AppEntry>();
List<ApplicationInfo> mApplications = new ArrayList<ApplicationInfo>();
long mCurId = 1;
+ String mCurComputingSizeUuid;
String mCurComputingSizePkg;
int mCurComputingSizeUserId;
boolean mSessionsChanged;
@@ -126,7 +130,8 @@
mContext = app;
mPm = mContext.getPackageManager();
mIpm = AppGlobals.getPackageManager();
- mUm = (UserManager) app.getSystemService(Context.USER_SERVICE);
+ mUm = mContext.getSystemService(UserManager.class);
+ mStats = mContext.getSystemService(StorageStatsManager.class);
for (int userId : mUm.getProfileIdsWithDisabled(UserHandle.myUserId())) {
mEntriesMap.put(userId, new HashMap<String, AppEntry>());
}
@@ -328,7 +333,18 @@
synchronized (mEntriesMap) {
AppEntry entry = mEntriesMap.get(userId).get(packageName);
if (entry != null) {
- mPm.getPackageSizeInfoAsUser(packageName, userId, mBackgroundHandler.mStatsObserver);
+ mBackgroundHandler.post(() -> {
+ final StorageStats stats = mStats.queryStatsForPackage(entry.info.volumeUuid,
+ packageName, UserHandle.of(userId));
+ final PackageStats legacyStats = new PackageStats(packageName, userId);
+ legacyStats.codeSize = stats.getCodeBytes();
+ legacyStats.dataSize = stats.getDataBytes();
+ legacyStats.cacheSize = stats.getCacheBytes();
+ try {
+ mBackgroundHandler.mStatsObserver.onGetStatsCompleted(legacyStats, true);
+ } catch (RemoteException ignored) {
+ }
+ });
}
if (DEBUG_LOCKING) Log.v(TAG, "...requestSize releasing lock");
}
@@ -958,10 +974,24 @@
mMainHandler.sendMessage(m);
}
entry.sizeLoadStart = now;
+ mCurComputingSizeUuid = entry.info.volumeUuid;
mCurComputingSizePkg = entry.info.packageName;
mCurComputingSizeUserId = UserHandle.getUserId(entry.info.uid);
- mPm.getPackageSizeInfoAsUser(mCurComputingSizePkg,
- mCurComputingSizeUserId, mStatsObserver);
+
+ mBackgroundHandler.post(() -> {
+ final StorageStats stats = mStats.queryStatsForPackage(
+ mCurComputingSizeUuid, mCurComputingSizePkg,
+ UserHandle.of(mCurComputingSizeUserId));
+ final PackageStats legacyStats = new PackageStats(
+ mCurComputingSizePkg, mCurComputingSizeUserId);
+ legacyStats.codeSize = stats.getCodeBytes();
+ legacyStats.dataSize = stats.getDataBytes();
+ legacyStats.cacheSize = stats.getCacheBytes();
+ try {
+ mStatsObserver.onGetStatsCompleted(legacyStats, true);
+ } catch (RemoteException ignored) {
+ }
+ });
}
if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_SIZES releasing: now computing");
return;
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
index e520319..953dda2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
@@ -16,22 +16,14 @@
package com.android.settingslib.deviceinfo;
-import android.app.ActivityManager;
-import android.content.ComponentName;
+import android.app.usage.ExternalStorageStats;
+import android.app.usage.StorageStats;
+import android.app.usage.StorageStatsManager;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageStatsObserver;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageStats;
import android.content.pm.UserInfo;
+import android.os.AsyncTask;
import android.os.Environment;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageVolume;
@@ -40,93 +32,54 @@
import android.util.SparseArray;
import android.util.SparseLongArray;
-import com.android.internal.app.IMediaContainerService;
-import com.android.internal.util.ArrayUtils;
-import com.google.android.collect.Sets;
-
-import java.io.File;
import java.lang.ref.WeakReference;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
-import java.util.Objects;
-import java.util.Set;
/**
* Utility for measuring the disk usage of internal storage or a physical
- * {@link StorageVolume}. Connects with a remote {@link IMediaContainerService}
- * and delivers results to {@link MeasurementReceiver}.
+ * {@link StorageVolume}.
*/
public class StorageMeasurement {
private static final String TAG = "StorageMeasurement";
- private static final boolean LOCAL_LOGV = false;
- static final boolean LOGV = LOCAL_LOGV && Log.isLoggable(TAG, Log.VERBOSE);
-
- private static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
-
- public static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
- DEFAULT_CONTAINER_PACKAGE, "com.android.defcontainer.DefaultContainerService");
-
- /** Media types to measure on external storage. */
- private static final Set<String> sMeasureMediaTypes = Sets.newHashSet(
- Environment.DIRECTORY_DCIM, Environment.DIRECTORY_MOVIES,
- Environment.DIRECTORY_PICTURES, Environment.DIRECTORY_MUSIC,
- Environment.DIRECTORY_ALARMS, Environment.DIRECTORY_NOTIFICATIONS,
- Environment.DIRECTORY_RINGTONES, Environment.DIRECTORY_PODCASTS,
- Environment.DIRECTORY_DOWNLOADS, Environment.DIRECTORY_ANDROID);
-
public static class MeasurementDetails {
+ /** Size of storage device. */
public long totalSize;
+ /** Size of available space. */
public long availSize;
+ /** Size of all cached data. */
+ public long cacheSize;
/**
- * Total apps disk usage per profiles of the current user.
+ * Total disk space used by everything.
* <p>
- * When measuring internal storage, this value includes the code size of
- * all apps (regardless of install status for the given profile), and
- * internal disk used by the profile's apps. When the device
- * emulates external storage, this value also includes emulated storage
- * used by the profile's apps.
- * <p>
- * When measuring a physical {@link StorageVolume}, this value includes
- * usage by all apps on that volume and only for the primary profile.
+ * Key is {@link UserHandle}.
+ */
+ public SparseLongArray usersSize = new SparseLongArray();
+
+ /**
+ * Total disk space used by apps.
* <p>
* Key is {@link UserHandle}.
*/
public SparseLongArray appsSize = new SparseLongArray();
/**
- * Total cache disk usage by apps (over all users and profiles).
- */
- public long cacheSize;
-
- /**
- * Total media disk usage, categorized by types such as
- * {@link Environment#DIRECTORY_MUSIC} for every user profile of the current user.
+ * Total disk space used by media on shared storage.
* <p>
- * When measuring internal storage, this reflects media on emulated
- * storage for the respective profile.
- * <p>
- * When measuring a physical {@link StorageVolume}, this reflects media
- * on that volume.
- * <p>
- * Key of the {@link SparseArray} is {@link UserHandle}.
+ * First key is {@link UserHandle}. Second key is media type, such as
+ * {@link Environment#DIRECTORY_PICTURES}.
*/
public SparseArray<HashMap<String, Long>> mediaSize = new SparseArray<>();
/**
- * Misc external disk usage for the current user's profiles, unaccounted in
- * {@link #mediaSize}. Key is {@link UserHandle}.
+ * Total disk space used by non-media on shared storage.
+ * <p>
+ * Key is {@link UserHandle}.
*/
public SparseLongArray miscSize = new SparseLongArray();
- /**
- * Total disk usage for users, which is only meaningful for emulated
- * internal storage. Key is {@link UserHandle}.
- */
- public SparseLongArray usersSize = new SparseLongArray();
-
@Override
public String toString() {
return "MeasurementDetails: [totalSize: " + totalSize + " availSize: " + availSize
@@ -142,25 +95,19 @@
private WeakReference<MeasurementReceiver> mReceiver;
private final Context mContext;
+ private final UserManager mUser;
+ private final StorageStatsManager mStats;
private final VolumeInfo mVolume;
private final VolumeInfo mSharedVolume;
- private final MainHandler mMainHandler;
- private final MeasurementHandler mMeasurementHandler;
-
public StorageMeasurement(Context context, VolumeInfo volume, VolumeInfo sharedVolume) {
mContext = context.getApplicationContext();
+ mUser = mContext.getSystemService(UserManager.class);
+ mStats = mContext.getSystemService(StorageStatsManager.class);
mVolume = volume;
mSharedVolume = sharedVolume;
-
- // Start the thread that will measure the disk usage.
- final HandlerThread handlerThread = new HandlerThread("MemoryMeasurement");
- handlerThread.start();
-
- mMainHandler = new MainHandler();
- mMeasurementHandler = new MeasurementHandler(handlerThread.getLooper());
}
public void setReceiver(MeasurementReceiver receiver) {
@@ -170,315 +117,94 @@
}
public void forceMeasure() {
- invalidate();
measure();
}
public void measure() {
- if (!mMeasurementHandler.hasMessages(MeasurementHandler.MSG_MEASURE)) {
- mMeasurementHandler.sendEmptyMessage(MeasurementHandler.MSG_MEASURE);
- }
+ new MeasureTask().execute();
}
public void onDestroy() {
mReceiver = null;
- mMeasurementHandler.removeMessages(MeasurementHandler.MSG_MEASURE);
- mMeasurementHandler.sendEmptyMessage(MeasurementHandler.MSG_DISCONNECT);
}
- private void invalidate() {
- mMeasurementHandler.sendEmptyMessage(MeasurementHandler.MSG_INVALIDATE);
- }
-
- private static class StatsObserver extends IPackageStatsObserver.Stub {
- private final boolean mIsPrivate;
- private final MeasurementDetails mDetails;
- private final int mCurrentUser;
- private final Message mFinished;
-
- private int mRemaining;
-
- public StatsObserver(boolean isPrivate, MeasurementDetails details, int currentUser,
- List<UserInfo> profiles, Message finished, int remaining) {
- mIsPrivate = isPrivate;
- mDetails = details;
- mCurrentUser = currentUser;
- if (isPrivate) {
- // Add the profile ids as keys to detail's app sizes.
- for (UserInfo userInfo : profiles) {
- mDetails.appsSize.put(userInfo.id, 0);
- }
- }
- mFinished = finished;
- mRemaining = remaining;
+ private class MeasureTask extends AsyncTask<Void, Void, MeasurementDetails> {
+ @Override
+ protected MeasurementDetails doInBackground(Void... params) {
+ return measureExactStorage();
}
@Override
- public void onGetStatsCompleted(PackageStats stats, boolean succeeded) {
- synchronized (mDetails) {
- if (succeeded) {
- addStatsLocked(stats);
- }
- if (--mRemaining == 0) {
- mFinished.sendToTarget();
- }
- }
- }
-
- private void addStatsLocked(PackageStats stats) {
- if (mIsPrivate) {
- long codeSize = stats.codeSize;
- long dataSize = stats.dataSize;
- long cacheSize = stats.cacheSize;
- if (Environment.isExternalStorageEmulated()) {
- // Include emulated storage when measuring internal. OBB is
- // shared on emulated storage, so treat as code.
- codeSize += stats.externalCodeSize + stats.externalObbSize;
- dataSize += stats.externalDataSize + stats.externalMediaSize;
- cacheSize += stats.externalCacheSize;
- }
-
- // Count code and data for current user's profiles (keys prepared in constructor)
- addValueIfKeyExists(mDetails.appsSize, stats.userHandle, codeSize + dataSize);
-
- // User summary only includes data (code is only counted once
- // for the current user)
- addValue(mDetails.usersSize, stats.userHandle, dataSize);
-
- // Include cache for all users
- mDetails.cacheSize += cacheSize;
-
- } else {
- // Physical storage; only count external sizes
- addValue(mDetails.appsSize, mCurrentUser,
- stats.externalCodeSize + stats.externalDataSize
- + stats.externalMediaSize + stats.externalObbSize);
- mDetails.cacheSize += stats.externalCacheSize;
- }
- }
- }
-
- private class MainHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
- final MeasurementDetails details = (MeasurementDetails) msg.obj;
+ protected void onPostExecute(MeasurementDetails result) {
final MeasurementReceiver receiver = (mReceiver != null) ? mReceiver.get() : null;
if (receiver != null) {
- receiver.onDetailsChanged(details);
+ receiver.onDetailsChanged(result);
}
}
}
- private class MeasurementHandler extends Handler {
- public static final int MSG_MEASURE = 1;
- public static final int MSG_CONNECTED = 2;
- public static final int MSG_DISCONNECT = 3;
- public static final int MSG_COMPLETED = 4;
- public static final int MSG_INVALIDATE = 5;
+ private MeasurementDetails measureExactStorage() {
+ final List<UserInfo> users = mUser.getUsers();
- private Object mLock = new Object();
-
- private IMediaContainerService mDefaultContainer;
-
- private volatile boolean mBound = false;
-
- private MeasurementDetails mCached;
-
- private final ServiceConnection mDefContainerConn = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- final IMediaContainerService imcs = IMediaContainerService.Stub.asInterface(
- service);
- mDefaultContainer = imcs;
- mBound = true;
- sendMessage(obtainMessage(MSG_CONNECTED, imcs));
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- mBound = false;
- removeMessages(MSG_CONNECTED);
- }
- };
-
- public MeasurementHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_MEASURE: {
- if (mCached != null) {
- mMainHandler.obtainMessage(0, mCached).sendToTarget();
- break;
- }
-
- synchronized (mLock) {
- if (mBound) {
- removeMessages(MSG_DISCONNECT);
- sendMessage(obtainMessage(MSG_CONNECTED, mDefaultContainer));
- } else {
- Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
- mContext.bindServiceAsUser(service, mDefContainerConn,
- Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
- }
- }
- break;
- }
- case MSG_CONNECTED: {
- final IMediaContainerService imcs = (IMediaContainerService) msg.obj;
- measureExactStorage(imcs);
- break;
- }
- case MSG_DISCONNECT: {
- synchronized (mLock) {
- if (mBound) {
- mBound = false;
- mContext.unbindService(mDefContainerConn);
- }
- }
- break;
- }
- case MSG_COMPLETED: {
- mCached = (MeasurementDetails) msg.obj;
- mMainHandler.obtainMessage(0, mCached).sendToTarget();
- break;
- }
- case MSG_INVALIDATE: {
- mCached = null;
- break;
- }
- }
- }
- }
-
- private void measureExactStorage(IMediaContainerService imcs) {
- final UserManager userManager = mContext.getSystemService(UserManager.class);
- final PackageManager packageManager = mContext.getPackageManager();
-
- final List<UserInfo> users = userManager.getUsers();
- final List<UserInfo> currentProfiles = userManager.getEnabledProfiles(
- ActivityManager.getCurrentUser());
+ final long start = SystemClock.elapsedRealtime();
final MeasurementDetails details = new MeasurementDetails();
- final Message finished = mMeasurementHandler.obtainMessage(MeasurementHandler.MSG_COMPLETED,
- details);
+ if (mVolume == null) return details;
- if (mVolume == null || !mVolume.isMountedReadable()) {
- finished.sendToTarget();
- return;
- }
+ details.totalSize = mStats.getTotalBytes(mVolume.fsUuid);
+ details.availSize = mStats.getFreeBytes(mVolume.fsUuid);
+
+ final long finishTotal = SystemClock.elapsedRealtime();
+ Log.d(TAG, "Measured total storage in " + (finishTotal - start) + "ms");
if (mSharedVolume != null && mSharedVolume.isMountedReadable()) {
- for (UserInfo currentUserInfo : currentProfiles) {
- final int userId = currentUserInfo.id;
- final File basePath = mSharedVolume.getPathForUser(userId);
- HashMap<String, Long> mediaMap = new HashMap<>(sMeasureMediaTypes.size());
- details.mediaSize.put(userId, mediaMap);
-
- // Measure media types for emulated storage, or for primary physical
- // external volume
- for (String type : sMeasureMediaTypes) {
- final File path = new File(basePath, type);
- final long size = getDirectorySize(imcs, path);
- mediaMap.put(type, size);
- }
-
- // Measure misc files not counted under media
- addValue(details.miscSize, userId, measureMisc(imcs, basePath));
- }
-
- if (mSharedVolume.getType() == VolumeInfo.TYPE_EMULATED) {
- // Measure total emulated storage of all users; internal apps data
- // will be spliced in later
- for (UserInfo user : users) {
- final File userPath = mSharedVolume.getPathForUser(user.id);
- final long size = getDirectorySize(imcs, userPath);
- addValue(details.usersSize, user.id, size);
- }
- }
- }
-
- final File file = mVolume.getPath();
- if (file != null) {
- details.totalSize = file.getTotalSpace();
- details.availSize = file.getFreeSpace();
- }
-
- // Measure all apps hosted on this volume for all users
- if (mVolume.getType() == VolumeInfo.TYPE_PRIVATE) {
- final List<ApplicationInfo> apps = packageManager.getInstalledApplications(
- PackageManager.MATCH_ANY_USER
- | PackageManager.MATCH_DISABLED_COMPONENTS);
-
- final List<ApplicationInfo> volumeApps = new ArrayList<>();
- for (ApplicationInfo app : apps) {
- if (Objects.equals(app.volumeUuid, mVolume.getFsUuid())) {
- volumeApps.add(app);
- }
- }
-
- final int count = users.size() * volumeApps.size();
- if (count == 0) {
- finished.sendToTarget();
- return;
- }
-
- final StatsObserver observer = new StatsObserver(true, details,
- ActivityManager.getCurrentUser(), currentProfiles, finished, count);
for (UserInfo user : users) {
- for (ApplicationInfo app : volumeApps) {
- packageManager.getPackageSizeInfoAsUser(app.packageName, user.id, observer);
+ final HashMap<String, Long> mediaMap = new HashMap<>();
+ details.mediaSize.put(user.id, mediaMap);
+
+ final ExternalStorageStats stats = mStats
+ .queryExternalStatsForUser(mSharedVolume.fsUuid, UserHandle.of(user.id));
+
+ addValue(details.usersSize, user.id, stats.getTotalBytes());
+
+ // Track detailed data types
+ mediaMap.put(Environment.DIRECTORY_MUSIC, stats.getAudioBytes());
+ mediaMap.put(Environment.DIRECTORY_MOVIES, stats.getVideoBytes());
+ mediaMap.put(Environment.DIRECTORY_PICTURES, stats.getImageBytes());
+
+ final long miscBytes = stats.getTotalBytes() - stats.getAudioBytes()
+ - stats.getVideoBytes() - stats.getImageBytes();
+ addValue(details.miscSize, user.id, miscBytes);
+ }
+ }
+
+ final long finishShared = SystemClock.elapsedRealtime();
+ Log.d(TAG, "Measured shared storage in " + (finishShared - finishTotal) + "ms");
+
+ if ((mVolume.getType() == VolumeInfo.TYPE_PRIVATE) && mVolume.isMountedReadable()) {
+ for (UserInfo user : users) {
+ final StorageStats stats = mStats.queryStatsForUser(mVolume.fsUuid,
+ UserHandle.of(user.id));
+
+ // Only count code once against current user
+ if (user.id == UserHandle.myUserId()) {
+ addValue(details.usersSize, user.id, stats.getCodeBytes());
}
- }
- } else {
- finished.sendToTarget();
- return;
- }
- }
+ addValue(details.usersSize, user.id, stats.getDataBytes());
+ addValue(details.appsSize, user.id, stats.getCodeBytes() + stats.getDataBytes());
- private static long getDirectorySize(IMediaContainerService imcs, File path) {
- try {
- final long size = imcs.calculateDirectorySize(path.toString());
- if (LOGV) Log.v(TAG, "getDirectorySize(" + path + ") returned " + size);
- return size;
- } catch (Exception e) {
- Log.w(TAG, "Could not read memory from default container service for " + path, e);
- return 0;
- }
- }
-
- private long measureMisc(IMediaContainerService imcs, File dir) {
- final File[] files = dir.listFiles();
- if (ArrayUtils.isEmpty(files)) return 0;
-
- // Get sizes of all top level nodes except the ones already computed
- long miscSize = 0;
- for (File file : files) {
- final String name = file.getName();
- if (sMeasureMediaTypes.contains(name)) {
- continue;
- }
-
- if (file.isFile()) {
- miscSize += file.length();
- } else if (file.isDirectory()) {
- miscSize += getDirectorySize(imcs, file);
+ details.cacheSize += stats.getCacheBytes();
}
}
- return miscSize;
+
+ final long finishPrivate = SystemClock.elapsedRealtime();
+ Log.d(TAG, "Measured private storage in " + (finishPrivate - finishShared) + "ms");
+
+ return details;
}
private static void addValue(SparseLongArray array, int key, long value) {
array.put(key, array.get(key) + value);
}
-
- private static void addValueIfKeyExists(SparseLongArray array, int key, long value) {
- final int index = array.indexOfKey(key);
- if (index >= 0) {
- array.put(key, array.valueAt(index) + value);
- }
- }
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index de79d3f..5f4b239 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -553,23 +553,23 @@
}
private void doWriteState() {
+ boolean wroteState = false;
+ final int version;
+ final ArrayMap<String, Setting> settings;
+
+ synchronized (mLock) {
+ version = mVersion;
+ settings = new ArrayMap<>(mSettings);
+ mDirty = false;
+ mWriteScheduled = false;
+ }
+
synchronized (mWriteLock) {
if (DEBUG_PERSISTENCE) {
Slog.i(LOG_TAG, "[PERSIST START]");
}
AtomicFile destination = new AtomicFile(mStatePersistFile);
-
- final int version;
- final ArrayMap<String, Setting> settings;
-
- synchronized (mLock) {
- version = mVersion;
- settings = new ArrayMap<>(mSettings);
- mDirty = false;
- mWriteScheduled = false;
- }
-
FileOutputStream out = null;
try {
out = destination.startWrite();
@@ -600,9 +600,7 @@
serializer.endDocument();
destination.finishWrite(out);
- synchronized (mLock) {
- addHistoricalOperationLocked(HISTORICAL_OPERATION_PERSIST, null);
- }
+ wroteState = true;
if (DEBUG_PERSISTENCE) {
Slog.i(LOG_TAG, "[PERSIST END]");
@@ -614,6 +612,12 @@
IoUtils.closeQuietly(out);
}
}
+
+ if (wroteState) {
+ synchronized (mLock) {
+ addHistoricalOperationLocked(HISTORICAL_OPERATION_PERSIST, null);
+ }
+ }
}
static void writeSingleSetting(int version, XmlSerializer serializer, String id,
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 62e11f7..93ae763 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1164,6 +1164,8 @@
<string name="volume_stream_content_description_unmute">%1$s. Tap to unmute.</string>
<string name="volume_stream_content_description_vibrate">%1$s. Tap to set to vibrate. Accessibility services may be muted.</string>
<string name="volume_stream_content_description_mute">%1$s. Tap to mute. Accessibility services may be muted.</string>
+ <string name="volume_stream_content_description_vibrate_a11y">%1$s. Tap to set to vibrate.</string>
+ <string name="volume_stream_content_description_mute_a11y">%1$s. Tap to mute.</string>
<string name="volume_dialog_accessibility_shown_message">%s volume controls shown. Swipe up to dismiss.</string>
<string name="volume_dialog_accessibility_dismissed_message">Volume controls hidden</string>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 3559257..9da52d0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -263,7 +263,6 @@
public TilePage(Context context, AttributeSet attrs) {
super(context, attrs);
updateResources();
- setContentDescription(getContext().getString(R.string.accessibility_desc_quick_settings));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 3337090..a30b03b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -175,7 +175,8 @@
View view = mQs.getView();
if (count < mNumQuickTiles && mAllowFancy) {
// Quick tiles.
- com.android.systemui.plugins.qs.QSTileView quickTileView = mQuickQsPanel.getTileView(tile);
+ QSTileView quickTileView = mQuickQsPanel.getTileView(tile);
+ if (quickTileView == null) continue;
lastX = loc1[0];
getRelativePosition(loc1, quickTileView.getIcon().getIconView(), view);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 3a93d51..63563b2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -162,8 +162,7 @@
public void setHeaderClickable(boolean clickable) {
if (DEBUG) Log.d(TAG, "setHeaderClickable " + clickable);
- mHeader.setClickable(clickable);
- mFooter.setClickable(clickable);
+ mFooter.getExpandView().setClickable(clickable);
}
public void setExpanded(boolean expanded) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 8c1c89f..d0d6f61 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -125,9 +125,7 @@
}
public void updateEverything() {
- post(() -> {
- setClickable(false);
- });
+ post(() -> setClickable(false));
}
public void setQSPanel(final QSPanel qsPanel) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index fc3bb43..00968ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -1268,7 +1268,6 @@
if (mChildrenContainer != null) {
mChildrenContainer.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE
: INVISIBLE);
- mChildrenContainer.setHeaderVisible(!mShowingPublic && mIsSummaryWithChildren);
}
// The limits might have changed if the view suddenly became a group or vice versa
updateLimits();
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 b52c26f..4dc593b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -188,9 +188,6 @@
public void panelScrimMinFractionChanged(float minFraction) {
if (mMinFraction != minFraction) {
mMinFraction = minFraction;
- if (minFraction != 0.0f) {
- mScrimController.animateNextChange();
- }
updateScrimFraction();
}
}
@@ -203,7 +200,11 @@
}
private void updateScrimFraction() {
- float scrimFraction = Math.max(mPanelFraction, mMinFraction);
+ float scrimFraction = mPanelFraction;
+ if (mMinFraction < 1.0f) {
+ scrimFraction = Math.max((mPanelFraction - mMinFraction) / (1.0f - mMinFraction),
+ 0);
+ }
mScrimController.setPanelExpansion(scrimFraction);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index b30d3ab..dadb749 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -203,10 +203,6 @@
scheduleUpdate();
}
- public void animateNextChange() {
- mAnimateChange = true;
- }
-
public void setDozing(boolean dozing) {
if (mDozing != dozing) {
mDozing = dozing;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index 83cbd72..fe249a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -89,7 +89,6 @@
private ViewState mHeaderViewState;
private int mClipBottomAmount;
private boolean mIsLowPriority;
- private boolean mHeaderVisible = true;
private OnClickListener mHeaderClickListener;
private boolean mShowingNormalHeader;
@@ -324,6 +323,7 @@
}
mNotificationHeaderWrapperLowPriority.notifyContentUpdated(mContainingNotification);
} else {
+ removeView(mNotificationHeaderLowPriority);
mNotificationHeaderLowPriority = null;
mNotificationHeaderWrapperLowPriority = null;
}
@@ -794,11 +794,6 @@
return mNotificationHeaderLowPriority;
}
- public void setHeaderVisible(boolean visible) {
- mHeaderVisible = visible;
- updateHeaderVisibility(false /* animate */);
- }
-
private void updateHeaderVisibility(boolean animate) {
NotificationHeaderView visibleHeader = mNotificationHeader;
NotificationHeaderView hiddenHeader = mNotificationHeaderLowPriority;
@@ -809,7 +804,7 @@
normalHeaderVisible = false;
}
if (animate) {
- if (mHeaderVisible && visibleHeader != null && hiddenHeader != null
+ if (visibleHeader != null && hiddenHeader != null
&& mShowingNormalHeader != normalHeaderVisible) {
hiddenHeader.setVisibility(VISIBLE);
visibleHeader.setVisibility(VISIBLE);
@@ -825,7 +820,7 @@
if (!animate) {
if (visibleHeader != null) {
getWrapperForView(visibleHeader).setVisible(true);
- visibleHeader.setVisibility(mHeaderVisible ? VISIBLE : INVISIBLE);
+ visibleHeader.setVisibility(VISIBLE);
}
if (hiddenHeader != null) {
getWrapperForView(hiddenHeader).setVisible(false);
@@ -855,7 +850,7 @@
private void updateHeaderTransformation() {
- if (mUserLocked && mHeaderVisible && showingAsLowPriority()) {
+ if (mUserLocked && showingAsLowPriority()) {
float fraction = getGroupExpandFraction();
mNotificationHeaderWrapper.transformFrom(mNotificationHeaderWrapperLowPriority,
fraction);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index b320d60..1933349a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -426,34 +426,37 @@
});
row.icon = (ImageButton) row.view.findViewById(R.id.volume_row_icon);
row.icon.setImageResource(iconRes);
- row.icon.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- 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();
- if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
- if (hasVibrator) {
- mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
+ if (row.stream != AudioSystem.STREAM_ACCESSIBILITY) {
+ row.icon.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ 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();
+ if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
+ if (hasVibrator) {
+ mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
+ } else {
+ final boolean wasZero = row.ss.level == 0;
+ mController.setStreamVolume(stream,
+ wasZero ? row.lastAudibleLevel : 0);
+ }
} else {
- final boolean wasZero = row.ss.level == 0;
- mController.setStreamVolume(stream, wasZero ? row.lastAudibleLevel : 0);
+ mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
+ if (row.ss.level == 0) {
+ mController.setStreamVolume(stream, 1);
+ }
}
} else {
- mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
- if (row.ss.level == 0) {
- mController.setStreamVolume(stream, 1);
- }
+ final boolean vmute = row.ss.level == row.ss.levelMin;
+ mController.setStreamVolume(stream,
+ vmute ? row.lastAudibleLevel : row.ss.levelMin);
}
- } else {
- final boolean vmute = row.ss.level == row.ss.levelMin;
- mController.setStreamVolume(stream,
- vmute ? row.lastAudibleLevel : row.ss.levelMin);
+ row.userAttempt = 0; // reset the grace period, slider updates immediately
}
- row.userAttempt = 0; // reset the grace period, slider should update immediately
- }
- });
+ });
+ }
}
public void destroy() {
@@ -722,6 +725,7 @@
if (ss.level == row.requestedLevel) {
row.requestedLevel = -1;
}
+ final boolean isA11yStream = row.stream == AudioManager.STREAM_ACCESSIBILITY;
final boolean isRingStream = row.stream == AudioManager.STREAM_RING;
final boolean isSystemStream = row.stream == AudioManager.STREAM_SYSTEM;
final boolean isAlarmStream = row.stream == AudioManager.STREAM_ALARM;
@@ -781,14 +785,20 @@
} else {
if (mController.hasVibrator()) {
row.icon.setContentDescription(mContext.getString(
- R.string.volume_stream_content_description_vibrate,
+ mShowA11yStream
+ ? R.string.volume_stream_content_description_vibrate_a11y
+ : R.string.volume_stream_content_description_vibrate,
getStreamLabelH(ss)));
} else {
row.icon.setContentDescription(mContext.getString(
- R.string.volume_stream_content_description_mute,
+ mShowA11yStream
+ ? R.string.volume_stream_content_description_mute_a11y
+ : R.string.volume_stream_content_description_mute,
getStreamLabelH(ss)));
}
}
+ } else if (isA11yStream) {
+ row.icon.setContentDescription(getStreamLabelH(ss));
} else {
if (ss.muted || mAutomute && ss.level == 0) {
row.icon.setContentDescription(mContext.getString(
@@ -796,7 +806,9 @@
getStreamLabelH(ss)));
} else {
row.icon.setContentDescription(mContext.getString(
- R.string.volume_stream_content_description_mute,
+ mShowA11yStream
+ ? R.string.volume_stream_content_description_mute_a11y
+ : R.string.volume_stream_content_description_mute,
getStreamLabelH(ss)));
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysUIRunner.java b/packages/SystemUI/tests/src/com/android/systemui/SysUIRunner.java
index 1607b70..fd99d1d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysUIRunner.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysUIRunner.java
@@ -46,7 +46,7 @@
@Override
protected Statement methodInvoker(FrameworkMethod method, Object test) {
- return UiThreadStatement.shouldRunOnUiThread(method) ? new UiThreadStatement(
+ return shouldRunOnUiThread(method) ? new UiThreadStatement(
methodInvokerInt(method, test), true) : methodInvokerInt(method, test);
}
@@ -84,4 +84,12 @@
private long getTimeout(Test annotation) {
return annotation == null ? 0L : annotation.timeout();
}
+
+ public boolean shouldRunOnUiThread(FrameworkMethod method) {
+ if (mKlass.getAnnotation(UiThreadTest.class) != null) {
+ return true;
+ } else {
+ return UiThreadStatement.shouldRunOnUiThread(method);
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/UiThreadTest.java b/packages/SystemUI/tests/src/com/android/systemui/UiThreadTest.java
new file mode 100644
index 0000000..58369b1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/UiThreadTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * When applied to a class, all tests, befores, and afters will behave as if
+ * they have @UiThreadTest applied to them.
+ */
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface UiThreadTest {
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index 32afee9..0cccbe1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -37,11 +37,12 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.Display;
+import com.android.systemui.SysUIRunner;
+import com.android.systemui.UiThreadTest;
import com.android.systemui.statusbar.phone.DozeParameters;
import org.junit.Before;
@@ -49,7 +50,8 @@
import org.junit.runner.RunWith;
@SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(SysUIRunner.class)
+@UiThreadTest
public class DozeMachineTest {
DozeMachine mMachine;
@@ -72,7 +74,6 @@
}
@Test
- @UiThreadTest
public void testInitialize_initializesParts() {
mMachine.requestState(INITIALIZED);
@@ -80,7 +81,6 @@
}
@Test
- @UiThreadTest
public void testInitialize_goesToDoze() {
when(mParamsMock.getAlwaysOn()).thenReturn(false);
@@ -91,7 +91,6 @@
}
@Test
- @UiThreadTest
public void testInitialize_goesToAod() {
when(mParamsMock.getAlwaysOn()).thenReturn(true);
@@ -102,7 +101,6 @@
}
@Test
- @UiThreadTest
public void testPulseDone_goesToDoze() {
when(mParamsMock.getAlwaysOn()).thenReturn(false);
mMachine.requestState(INITIALIZED);
@@ -116,7 +114,6 @@
}
@Test
- @UiThreadTest
public void testPulseDone_goesToAoD() {
when(mParamsMock.getAlwaysOn()).thenReturn(true);
mMachine.requestState(INITIALIZED);
@@ -130,7 +127,6 @@
}
@Test
- @UiThreadTest
public void testFinished_staysFinished() {
mMachine.requestState(INITIALIZED);
mMachine.requestState(FINISH);
@@ -143,7 +139,6 @@
}
@Test
- @UiThreadTest
public void testFinish_finishesService() {
mMachine.requestState(INITIALIZED);
@@ -153,7 +148,6 @@
}
@Test
- @UiThreadTest
public void testWakeLock_heldInTransition() {
doAnswer((inv) -> {
assertTrue(mWakeLockFake.isHeld());
@@ -164,7 +158,6 @@
}
@Test
- @UiThreadTest
public void testWakeLock_heldInPulseStates() {
mMachine.requestState(INITIALIZED);
@@ -176,7 +169,6 @@
}
@Test
- @UiThreadTest
public void testWakeLock_notHeldInDozeStates() {
mMachine.requestState(INITIALIZED);
@@ -188,7 +180,6 @@
}
@Test
- @UiThreadTest
public void testWakeLock_releasedAfterPulse() {
mMachine.requestState(INITIALIZED);
@@ -201,7 +192,6 @@
}
@Test
- @UiThreadTest
public void testPulseDuringPulse_doesntCrash() {
mMachine.requestState(INITIALIZED);
@@ -213,7 +203,6 @@
}
@Test
- @UiThreadTest
public void testSuppressingPulse_doesntCrash() {
mMachine.requestState(INITIALIZED);
@@ -223,7 +212,6 @@
}
@Test
- @UiThreadTest
public void testScreen_offInDoze() {
mMachine.requestState(INITIALIZED);
@@ -233,7 +221,6 @@
}
@Test
- @UiThreadTest
public void testScreen_onInAod() {
mMachine.requestState(INITIALIZED);
@@ -243,7 +230,6 @@
}
@Test
- @UiThreadTest
public void testScreen_onInPulse() {
mMachine.requestState(INITIALIZED);
@@ -254,7 +240,6 @@
}
@Test
- @UiThreadTest
public void testScreen_offInRequestPulseWithoutAoD() {
mMachine.requestState(INITIALIZED);
@@ -265,7 +250,6 @@
}
@Test
- @UiThreadTest
public void testScreen_onInRequestPulseWithoutAoD() {
mMachine.requestState(INITIALIZED);
@@ -276,7 +260,6 @@
}
@Test
- @UiThreadTest
public void testTransitions_canRequestTransitions() {
mMachine.requestState(INITIALIZED);
mMachine.requestState(DOZE);
@@ -291,7 +274,6 @@
}
@Test
- @UiThreadTest
public void testWakeUp_wakesUp() {
mMachine.wakeUp();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notification/PropertyAnimatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/notification/PropertyAnimatorTest.java
index 193250f..53053fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notification/PropertyAnimatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/notification/PropertyAnimatorTest.java
@@ -16,7 +16,6 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
-import android.support.test.annotation.UiThreadTest;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
@@ -28,7 +27,9 @@
import android.view.View;
import android.view.animation.Interpolator;
+import com.android.systemui.SysUIRunner;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.UiThreadTest;
import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.stack.AnimationFilter;
import com.android.systemui.statusbar.stack.AnimationProperties;
@@ -49,7 +50,8 @@
import static org.mockito.Mockito.when;
@SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(SysUIRunner.class)
+@UiThreadTest
public class PropertyAnimatorTest extends SysuiTestCase {
private View mView;
@@ -106,13 +108,11 @@
@Before
- @UiThreadTest
public void setUp() {
mView = new View(getContext());
}
@Test
- @UiThreadTest
public void testAnimationStarted() {
mAnimationFilter.reset();
mAnimationFilter.animate(mProperty.getProperty());
@@ -121,7 +121,6 @@
}
@Test
- @UiThreadTest
public void testNoAnimationStarted() {
mAnimationFilter.reset();
PropertyAnimator.startAnimation(mView, mProperty, 200, mAnimationProperties);
@@ -129,7 +128,6 @@
}
@Test
- @UiThreadTest
public void testEndValueUpdated() {
mAnimationFilter.reset();
mAnimationFilter.animate(mProperty.getProperty());
@@ -139,7 +137,6 @@
}
@Test
- @UiThreadTest
public void testStartTagUpdated() {
mEffectiveProperty.set(mView, 100f);
mAnimationFilter.reset();
@@ -150,7 +147,6 @@
}
@Test
- @UiThreadTest
public void testValueIsSetUnAnimated() {
mAnimationFilter.reset();
PropertyAnimator.startAnimation(mView, mProperty, 200f, mAnimationProperties);
@@ -158,7 +154,6 @@
}
@Test
- @UiThreadTest
public void testAnimationToRightValueUpdated() {
mAnimationFilter.reset();
mAnimationFilter.animate(mProperty.getProperty());
@@ -171,7 +166,6 @@
}
@Test
- @UiThreadTest
public void testAnimationToRightValueUpdateAnimated() {
mAnimationFilter.reset();
mAnimationFilter.animate(mProperty.getProperty());
@@ -185,7 +179,6 @@
}
@Test
- @UiThreadTest
public void testStartTagShiftedWhenChanging() {
mEffectiveProperty.set(mView, 100f);
mAnimationFilter.reset();
@@ -198,7 +191,6 @@
}
@Test
- @UiThreadTest
public void testUsingDuration() {
mAnimationFilter.reset();
mAnimationFilter.animate(mProperty.getProperty());
@@ -210,7 +202,6 @@
}
@Test
- @UiThreadTest
public void testUsingDelay() {
mAnimationFilter.reset();
mAnimationFilter.animate(mProperty.getProperty());
@@ -222,7 +213,6 @@
}
@Test
- @UiThreadTest
public void testUsingInterpolator() {
mAnimationFilter.reset();
mAnimationFilter.animate(mProperty.getProperty());
@@ -234,7 +224,6 @@
}
@Test
- @UiThreadTest
public void testUsingListener() {
mAnimationFilter.reset();
mAnimationFilter.animate(mProperty.getProperty());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
index bf741ec..3db2440 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
@@ -17,28 +17,13 @@
package com.android.systemui.statusbar;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import android.app.ActivityManager;
-import android.app.Notification;
import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.UserHandle;
-import android.service.notification.StatusBarNotification;
import android.support.test.InstrumentationRegistry;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.view.LayoutInflater;
import android.view.View;
-import android.widget.RemoteViews;
-
-import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.InflationException;
-import com.android.systemui.statusbar.notification.NotificationCustomViewWrapper;
-import com.android.systemui.statusbar.notification.NotificationInflater;
-import com.android.systemui.statusbar.notification.NotificationViewWrapper;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import org.junit.Assert;
import org.junit.Before;
@@ -50,58 +35,32 @@
public class ExpandableNotificationRowTest {
private Context mContext;
- private ExpandableNotificationRow mRow;
- private NotificationGroupManager mGroupManager = new NotificationGroupManager();
- private int mId;
+ private ExpandableNotificationRow mGroup;
+ private NotificationTestHelper mNotificationTestHelper;
@Before
@UiThreadTest
public void setUp() {
mContext = InstrumentationRegistry.getTargetContext();
- mRow = createNotification();
- }
-
- private ExpandableNotificationRow createNotification() {
- LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- ExpandableNotificationRow row = (ExpandableNotificationRow) inflater.inflate(
- R.layout.status_bar_notification_row,
- null, false);
- row.setGroupManager(mGroupManager);
- Notification publicVersion = new Notification.Builder(mContext).setSmallIcon(
- R.drawable.ic_person)
- .setCustomContentView(new RemoteViews(mContext.getPackageName(),
- R.layout.custom_view_dark))
- .build();
- Notification notification = new Notification.Builder(mContext).setSmallIcon(
- R.drawable.ic_person)
- .setContentTitle("Title")
- .setContentText("Text")
- .setPublicVersion(publicVersion)
- .build();
- UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
- StatusBarNotification sbn = new StatusBarNotification("com.android.systemui",
- "com.android.systemui", mId++, null, 1000,
- 2000, notification, mUser, null, System.currentTimeMillis());
- NotificationData.Entry entry = new NotificationData.Entry(sbn);
- entry.row = row;
- try {
- entry.createIcons(mContext, sbn);
- row.updateNotification(entry);
- } catch (InflationException e) {
- throw new RuntimeException(e.getMessage());
- }
- return row;
+ mNotificationTestHelper = new NotificationTestHelper(mContext);
+ mGroup = mNotificationTestHelper.createGroup();
}
@Test
public void testGroupSummaryNotShowingIconWhenPublic() {
- mRow.setSensitive(true, true);
- mRow.addChildNotification(createNotification());
- mRow.addChildNotification(createNotification());
- mRow.setHideSensitive(true, false, 0, 0);
- Assert.assertTrue(mRow.isSummaryWithChildren());
- Assert.assertFalse(mRow.isShowingIcon());
+ mGroup.setSensitive(true, true);
+ mGroup.setHideSensitive(true, false, 0, 0);
+ Assert.assertTrue(mGroup.isSummaryWithChildren());
+ Assert.assertFalse(mGroup.isShowingIcon());
+ }
+
+ @Test
+ public void testNotificationHeaderVisibleWhenAnimating() {
+ mGroup.setSensitive(true, true);
+ mGroup.setHideSensitive(true, false, 0, 0);
+ mGroup.setHideSensitive(false, true, 0, 0);
+ Assert.assertTrue(mGroup.getChildrenContainer().getVisibleHeader().getVisibility()
+ == View.VISIBLE);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index 92f8c7c..8520bdb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -44,7 +44,6 @@
import android.graphics.drawable.Drawable;
import android.service.notification.StatusBarNotification;
import android.support.test.InstrumentationRegistry;
-import android.support.test.annotation.UiThreadTest;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
@@ -55,7 +54,10 @@
import android.widget.TextView;
import com.android.internal.util.CharSequences;
import com.android.systemui.R;
+import com.android.systemui.SysUIRunner;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.UiThreadTest;
+
import org.junit.Before;
import org.junit.runner.RunWith;
import org.junit.Test;
@@ -65,7 +67,8 @@
import java.util.concurrent.CountDownLatch;
@SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(SysUIRunner.class)
+@UiThreadTest
public class NotificationInfoTest extends SysuiTestCase {
private static final String TEST_PACKAGE_NAME = "test_package";
private static final String TEST_CHANNEL = "test_channel";
@@ -79,7 +82,6 @@
mock(StatusBarNotification.class);
@Before
- @UiThreadTest
public void setUp() throws Exception {
// Inflate the layout
final LayoutInflater layoutInflater =
@@ -116,7 +118,6 @@
}
@Test
- @UiThreadTest
public void testBindNotification_SetsTextApplicationName() throws Exception {
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -126,7 +127,6 @@
}
@Test
- @UiThreadTest
public void testBindNotification_SetsPackageIcon() throws Exception {
final Drawable iconDrawable = mock(Drawable.class);
when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
@@ -138,7 +138,6 @@
}
@Test
- @UiThreadTest
public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
mMockStatusBarNotification, mNotificationChannel, null, null, null);
@@ -150,7 +149,6 @@
}
@Test
- @UiThreadTest
public void testBindNotification_SetsGroupNameIfNonNull() throws Exception {
mNotificationChannel.setGroup("test_group_id");
final NotificationChannelGroup notificationChannelGroup =
@@ -169,7 +167,6 @@
}
@Test
- @UiThreadTest
public void testBindNotification_SetsGroupName_resId() throws Exception {
when(mMockPackageManager.getText(eq(TEST_PACKAGE_NAME),
eq(R.string.legacy_vpn_name), anyObject())).thenReturn(
@@ -191,7 +188,6 @@
}
@Test
- @UiThreadTest
public void testBindNotification_SetsTextChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
mMockStatusBarNotification, mNotificationChannel, null, null, null);
@@ -200,7 +196,6 @@
}
@Test
- @UiThreadTest
public void testBindNotification_SetsTextChannelName_resId() throws Exception {
when(mMockPackageManager.getText(eq(TEST_PACKAGE_NAME),
eq(R.string.notification_menu_accessibility), anyObject())).thenReturn(
@@ -216,7 +211,6 @@
}
@Test
- @UiThreadTest
public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -231,7 +225,6 @@
}
@Test
- @UiThreadTest
public void testBindNotification_SettingsTextWithOneChannel() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
mMockStatusBarNotification, mNotificationChannel, (View v, int appUid) -> {}, null,
@@ -242,7 +235,6 @@
}
@Test
- @UiThreadTest
public void testBindNotification_SettingsTextWithMultipleChannels() throws Exception {
when(mMockINotificationManager.getNumNotificationChannelsForPackage(
eq(TEST_PACKAGE_NAME), anyInt(), anyBoolean())).thenReturn(2);
@@ -255,7 +247,6 @@
}
@Test
- @UiThreadTest
public void testBindNotification_SetsOnClickListenerForDone() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -270,7 +261,6 @@
}
@Test
- @UiThreadTest
public void testBindNotification_NumChannelsTextHiddenWhenDefaultChannel() throws Exception {
final NotificationChannel defaultChannel = new NotificationChannel(
NotificationChannel.DEFAULT_CHANNEL_ID, TEST_CHANNEL_NAME,
@@ -283,7 +273,6 @@
}
@Test
- @UiThreadTest
public void testBindNotification_NumChannelsTextDisplaysWhenNotDefaultChannel()
throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -295,7 +284,6 @@
}
@Test
- @UiThreadTest
public void testBindNotification_NumChannelsTextScalesWithNumberOfChannels()
throws Exception {
when(mMockINotificationManager.getNumNotificationChannelsForPackage(
@@ -308,7 +296,6 @@
}
@Test
- @UiThreadTest
public void testbindNotification_ChannelDisabledTextGoneWhenNotDisabled() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
mMockStatusBarNotification, mNotificationChannel, null, null, null);
@@ -318,7 +305,6 @@
}
@Test
- @UiThreadTest
public void testbindNotification_ChannelDisabledTextVisibleWhenDisabled() throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_NONE);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -333,7 +319,6 @@
}
@Test
- @UiThreadTest
public void testHasImportanceChanged_DefaultsToFalse() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
mMockStatusBarNotification, mNotificationChannel, null, null, null);
@@ -341,7 +326,6 @@
}
@Test
- @UiThreadTest
public void testHasImportanceChanged_ReturnsTrueAfterChannelDisabled() throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -353,7 +337,6 @@
}
@Test
- @UiThreadTest
public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
mMockStatusBarNotification, mNotificationChannel, null, null, null);
@@ -362,7 +345,6 @@
}
@Test
- @UiThreadTest
public void testDoesNotUpdateNotificationChannelAfterImportanceChanged() throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -375,7 +357,6 @@
}
@Test
- @UiThreadTest
public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged()
throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -387,7 +368,6 @@
}
@Test
- @UiThreadTest
public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnspecified()
throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED);
@@ -400,7 +380,6 @@
}
@Test
- @UiThreadTest
public void testEnabledSwitchOnByDefault() throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -411,7 +390,6 @@
}
@Test
- @UiThreadTest
public void testEnabledButtonOffWhenAlreadyBanned() throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_NONE);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -422,7 +400,6 @@
}
@Test
- @UiThreadTest
public void testEnabledSwitchVisibleByDefault() throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -433,7 +410,6 @@
}
@Test
- @UiThreadTest
public void testEnabledSwitchInvisibleIfNonBlockable() throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -445,7 +421,6 @@
}
@Test
- @UiThreadTest
public void testEnabledSwitchChangedCallsUpdateNotificationChannel() throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -460,7 +435,6 @@
}
@Test
- @UiThreadTest
public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
new file mode 100644
index 0000000..96dbdb3
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.app.ActivityManager;
+import android.app.Notification;
+import android.content.Context;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.view.LayoutInflater;
+import android.widget.RemoteViews;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.InflationException;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+
+/**
+ * A helper class to create {@link ExpandableNotificationRow}
+ */
+public class NotificationTestHelper {
+
+ private final Context mContext;
+ private int mId;
+ private final NotificationGroupManager mGroupManager = new NotificationGroupManager();
+
+ public NotificationTestHelper(Context context) {
+ mContext = context;
+ }
+
+ public ExpandableNotificationRow createRow() {
+ LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+ mContext.LAYOUT_INFLATER_SERVICE);
+ ExpandableNotificationRow row = (ExpandableNotificationRow) inflater.inflate(
+ R.layout.status_bar_notification_row,
+ null, false);
+ row.setGroupManager(mGroupManager);
+ Notification publicVersion = new Notification.Builder(mContext).setSmallIcon(
+ R.drawable.ic_person)
+ .setCustomContentView(new RemoteViews(mContext.getPackageName(),
+ R.layout.custom_view_dark))
+ .build();
+ Notification notification = new Notification.Builder(mContext).setSmallIcon(
+ R.drawable.ic_person)
+ .setContentTitle("Title")
+ .setContentText("Text")
+ .setPublicVersion(publicVersion)
+ .build();
+ UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
+ StatusBarNotification sbn = new StatusBarNotification("com.android.systemui",
+ "com.android.systemui", mId++, null, 1000,
+ 2000, notification, mUser, null, System.currentTimeMillis());
+ NotificationData.Entry entry = new NotificationData.Entry(sbn);
+ entry.row = row;
+ try {
+ entry.createIcons(mContext, sbn);
+ row.updateNotification(entry);
+ } catch (InflationException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ return row;
+ }
+
+ public ExpandableNotificationRow createGroup() {
+ ExpandableNotificationRow row = createRow();
+ row.addChildNotification(createRow());
+ row.addChildNotification(createRow());
+ return row;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java
new file mode 100644
index 0000000..dbe0de4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.stack;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.NotificationHeaderView;
+import android.view.View;
+
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.NotificationTestHelper;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NotificationChildrenContainerTest {
+
+ private Context mContext;
+ private ExpandableNotificationRow mGroup;
+ private int mId;
+ private NotificationTestHelper mNotificationTestHelper;
+
+ @Before
+ @UiThreadTest
+ public void setUp() {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mNotificationTestHelper = new NotificationTestHelper(mContext);
+ mGroup = mNotificationTestHelper.createGroup();
+ }
+
+ @Test
+ public void testLowPriorityHeaderCleared() {
+ mGroup.setIsLowPriority(true);
+ NotificationChildrenContainer childrenContainer = mGroup.getChildrenContainer();
+ NotificationHeaderView lowPriorityHeaderView = childrenContainer.getLowPriorityHeaderView();
+ Assert.assertTrue(lowPriorityHeaderView.getVisibility() == View.VISIBLE);
+ Assert.assertTrue(lowPriorityHeaderView.getParent() == childrenContainer);
+ mGroup.setIsLowPriority(false);
+ Assert.assertTrue(lowPriorityHeaderView.getParent() == null);
+ Assert.assertTrue(childrenContainer.getLowPriorityHeaderView() == null);
+ }
+}
diff --git a/proto/src/ipconnectivity.proto b/proto/src/ipconnectivity.proto
index b5afc40..76c5418 100644
--- a/proto/src/ipconnectivity.proto
+++ b/proto/src/ipconnectivity.proto
@@ -9,6 +9,8 @@
// NetworkId represents the id given by the system to a physical network on the
// Android device. It is used to relates events to each other for devices with
// multiple networks (WiFi, 4G, ...).
+// Deprecated since version 3, replaced by top-level network_id field in
+// IpConnectivityEvent.
message NetworkId {
// Every network gets assigned a network_id on creation based on order of
// creation. Thus network_id N is assigned to the network created directly
@@ -91,7 +93,8 @@
// This message is associated to android.net.metrics.NetworkEvent.
message NetworkEvent {
// The id of the network on which this event happened.
- optional NetworkId network_id = 1;
+ // Deprecated since version 3.
+ optional NetworkId network_id = 1 [deprecated = true];
// The type of network event, represented by NETWORK_* constants defined in
// android.net.metrics.NetworkEvent.
@@ -107,7 +110,8 @@
// This message is associated to android.net.metrics.ValidationProbeEvent.
message ValidationProbeEvent {
// The id of the network for which the probe was sent.
- optional NetworkId network_id = 1;
+ // Deprecated since version 3.
+ optional NetworkId network_id = 1 [deprecated = true];
// The time it took for that probe to complete or time out.
optional int32 latency_ms = 2;
@@ -167,18 +171,28 @@
// Represents latency and errno statistics of the connect() system call.
// Since version 2.
+// Next tag: 7
message ConnectStatistics {
// The number of connect() operations recorded.
optional int32 connect_count = 1;
+ // The number of connect() operations done in blocking mode.
+ // Since version 3.
+ optional int32 connect_blocking_count = 5;
+
// The number of connect() operations with IPv6 socket address.
optional int32 ipv6_addr_count = 2;
- // The time it took for each successful connect() operation to complete.
- // The number of repeated values can be less than connect_count in case of
- // event rate-limiting.
+ // The time it took for successful blocking connect() operations to complete
+ // The number of repeated values can be less than connect_blocking_count in
+ // case of event rate-limiting.
repeated int32 latencies_ms = 3;
+ // The time it took for successful connect() operation to complete in
+ // non-blocking mode. The number of repeated values can be less than
+ // connect_count - connect_blocking_count in case of event rate-limiting.
+ repeated int32 non_blocking_latencies_ms = 6;
+
// Counts of all error values returned by failed connect() operations.
// The Pair key field is the errno code. The Pair value field is the count
// for that errno code.
@@ -212,10 +226,15 @@
// Represents the generation of an Android Packet Filter program.
// Since version 1.
+// Next tag: 8
message ApfProgramEvent {
- // Lifetime of the program in seconds.
+ // Maximum lifetime of the program in seconds.
optional int64 lifetime = 1;
+ // Effective lifetime of the program in seconds from the time the
+ // program was installed to the time it was replaced or removed.
+ optional int64 effective_lifetime = 7;
+
// Number of RAs filtered by the APF program.
optional int32 filtered_ras = 2;
@@ -236,6 +255,7 @@
// Represents Router Advertisement listening statistics for an interface with
// Android Packet Filter enabled.
// Since version 1.
+// Next tag: 12
message ApfStatistics {
// The time interval in milliseconds these stastistics cover.
optional int64 duration_ms = 1;
@@ -261,6 +281,14 @@
// The maximum APF program size in byte advertised by hardware.
optional int32 max_program_size = 9;
+
+ // The total number of successful APF program updates triggered by any state
+ // change in ApfFilter. Since version 3.
+ optional int32 program_updates_all = 10;
+
+ // The total number of APF program updates triggered when disabling the
+ // multicast filter. Since version 3.
+ optional int32 program_updates_allowing_multicast = 11;
}
// Represents the reception of a Router Advertisement packet for an interface
@@ -308,7 +336,7 @@
}
// Represents one of the IP connectivity event defined in this file.
-// Next tag: 16
+// Next tag: 19
message IpConnectivityEvent {
// Time in ms when the event was recorded.
optional int64 time_ms = 1;
@@ -318,7 +346,27 @@
// Since version 2.
optional LinkLayer link_layer = 15;
- // Event type.
+ // Represents the id given by the system to a physical network on the device.
+ // Every network gets assigned a unique id on creation from a monotonic
+ // counter. The value 0 is never assigned to a network and means no network.
+ // It is used to correlate different types of events to each other for devices
+ // with multiple networks (WiFi, 4G, ...).
+ // Since version 3.
+ optional int32 network_id = 16;
+
+ // The interface name (wlan, rmnet, lo, ...) on which the event happened.
+ // Present if the link_layer field was not inferred from the if_name on
+ // the device, so that post-processing of the serialized proto can backfill
+ // link_layer. Since version 3.
+ optional string if_name = 17;
+
+ // The transport types of the network on which the event happened, expressed
+ // as a bit field of TRANSPORT_* constants as defined in NetworkCapabilities.
+ // Present if the link_layer field was not inferred from the transport types,
+ // so that post-processing of the serialized proto can backfill link_layer
+ // Since version 3.
+ optional int64 transports = 18;
+
oneof event {
// An event about the system default network.
@@ -371,9 +419,10 @@
optional int32 dropped_events = 2;
// The version number of the metrics events being collected.
- // nyc-dev: not populated, implicitly 0.
+ // nyc: not populated, implicitly 0.
// nyc-dr1: not populated, implicitly 1 (sailfish and marlin only).
// nyc-mr1: not populated, implicitly 1.
// nyc-mr2: 2.
+ // oc: 3.
optional int32 version = 3;
};
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 20aeb11..c45de0d 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3525,6 +3525,21 @@
// OPEN: Settings > About device > Model > Hardware info dialog
DIALOG_SETTINGS_HARDWARE_INFO = 862;
+ // ACTION: Checks whether a contact's phone still exists
+ // Value 0: It doesn't exist anymore
+ // Value 1: It still exists
+ // Value 2: A SecurityException was thrown
+ // CATEGORY: SETTINGS
+ // OS: N
+ ACTION_PHONE_EXISTS = 863;
+
+ // ACTION: Retrieves a contact from CP2
+ // Value 0: Contact retrieved without issues
+ // Value 1: An IllegalArgumentException was thrown
+ // CATEGORY: SETTINGS
+ // OS: N
+ ACTION_GET_CONTACT = 864;
+
// ---- End O Constants, all O constants go above this line ----
// Add new aosp constants above this line.
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
index 40491e91..e943c4c 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
@@ -305,14 +305,23 @@
}
@Override
+ public void setHasCallback(IBinder activityToken, int userId, boolean hasIt) {
+ synchronized (mLock) {
+ final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
+ service.setHasCallback(activityToken, hasIt);
+ }
+ }
+
+ @Override
public void startSession(IBinder activityToken, IBinder windowToken, IBinder appCallback,
- AutoFillId autoFillId, Rect bounds, AutoFillValue value, int userId) {
+ AutoFillId autoFillId, Rect bounds, AutoFillValue value, int userId,
+ boolean hasCallback) {
// TODO(b/33197203): make sure it's called by resumed / focused activity
synchronized (mLock) {
final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
service.startSessionLocked(activityToken, windowToken, appCallback,
- autoFillId, bounds, value);
+ autoFillId, bounds, value, hasCallback);
}
}
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
index 5e852f1..aa0840c 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
@@ -274,15 +274,25 @@
}
}
+ void setHasCallback(IBinder activityToken, boolean hasIt) {
+ if (!hasService()) {
+ return;
+ }
+ final Session session = mSessions.get(activityToken);
+ if (session != null) {
+ session.setHasCallback(hasIt);
+ }
+ }
+
void startSessionLocked(IBinder activityToken, IBinder windowToken, IBinder appCallbackToken,
- AutoFillId autoFillId, Rect bounds, AutoFillValue value) {
+ AutoFillId autoFillId, Rect bounds, AutoFillValue value, boolean hasCallback) {
if (!hasService()) {
return;
}
final String historyItem = "s=" + mInfo.getServiceInfo().packageName
+ " u=" + mUserId + " a=" + activityToken
- + " i=" + autoFillId + " b=" + bounds;
+ + " i=" + autoFillId + " b=" + bounds + " hc=" + hasCallback;
mRequestsHistory.log(historyItem);
// TODO(b/33197203): Handle partitioning
@@ -293,7 +303,7 @@
}
final Session newSession = createSessionByTokenLocked(activityToken,
- windowToken, appCallbackToken);
+ windowToken, appCallbackToken, hasCallback);
newSession.updateLocked(autoFillId, bounds, value, FLAG_START_SESSION);
}
@@ -312,9 +322,9 @@
}
private Session createSessionByTokenLocked(IBinder activityToken, IBinder windowToken,
- IBinder appCallbackToken) {
+ IBinder appCallbackToken, boolean hasCallback) {
final Session newSession = new Session(mContext, activityToken,
- windowToken, appCallbackToken);
+ windowToken, appCallbackToken, hasCallback);
mSessions.put(activityToken, newSession);
/*
@@ -599,12 +609,18 @@
@GuardedBy("mLock")
private AssistStructure mStructure;
+ /**
+ * Whether the client has an {@link android.view.autofill.AutoFillManager.AutofillCallback}.
+ */
+ private boolean mHasCallback;
+
private Session(Context context, IBinder activityToken, IBinder windowToken,
- IBinder client) {
+ IBinder client, boolean hasCallback) {
mRemoteFillService = new RemoteFillService(context,
mInfo.getServiceInfo().getComponentName(), mUserId, this);
mActivityToken = activityToken;
mWindowToken = windowToken;
+ mHasCallback = hasCallback;
mClient = IAutoFillManagerClient.Stub.asInterface(client);
try {
@@ -712,6 +728,22 @@
.sendToTarget();
}
+ // AutoFillUiCallback
+ @Override
+ public void cancelSave() {
+ mHandlerCaller.getHandler().post(() -> {
+ removeSelf();
+ });
+ }
+
+ // AutoFillUiCallback
+ @Override
+ public void onEvent(AutoFillId id, int event) {
+ mHandlerCaller.getHandler().post(() -> {
+ notifyChangeToClient(id, event);
+ });
+ }
+
public void setAuthenticationResultLocked(Bundle data) {
if (mCurrentResponse == null || data == null) {
removeSelf();
@@ -731,6 +763,10 @@
}
}
+ public void setHasCallback(boolean hasIt) {
+ mHasCallback = hasIt;
+ }
+
/**
* Show the save UI, when session can be saved.
*/
@@ -814,6 +850,7 @@
node.updateAutoFillValue(value);
}
+ // Sanitize structure before it's sent to service.
mStructure.sanitizeForParceling(false);
if (VERBOSE) {
@@ -871,7 +908,7 @@
if ((flags & FLAG_FOCUS_GAINED) != 0) {
// Remove the UI if the ViewState has changed.
if (mCurrentViewState != viewState) {
- mUi.hideFillUi();
+ mUi.hideFillUi(mCurrentViewState != null ? mCurrentViewState.mId : null);
mCurrentViewState = viewState;
}
@@ -888,7 +925,7 @@
if ((flags & FLAG_FOCUS_LOST) != 0) {
if (mCurrentViewState == viewState) {
- mUi.hideFillUi();
+ mUi.hideFillUi(viewState.mId);
mCurrentViewState = null;
}
return;
@@ -912,6 +949,15 @@
getUiForShowing().showFillUi(filledId, response, bounds, filterText);
}
+ private void notifyChangeToClient(AutoFillId id, int event) {
+ if (!mHasCallback) return;
+ try {
+ mClient.onAutofillEvent(mWindowToken, id, event);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error notifying client on change: id=" + id + ", event=" + event, e);
+ }
+ }
+
private void processResponseLocked(FillResponse response) {
if (DEBUG) {
Slog.d(TAG, "processResponseLocked(auth=" + response.getAuthentication()
@@ -993,7 +1039,7 @@
pw.println("null");
}
}
-
+ pw.print(prefix); pw.print("mHasCallback: "); pw.println(mHasCallback);
mRemoteFillService.dump(prefix, pw);
}
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index 7058248..d9f9721 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -182,11 +182,8 @@
if (mDestroyed || mCompleted) {
return;
}
- if (pendingRequest.isFinal()) {
- mCompleted = true;
- }
if (!isBound()) {
- if (mPendingRequest != null) {
+ if (mPendingRequest != null && mPendingRequest != pendingRequest) {
mPendingRequest.cancel();
}
mPendingRequest = pendingRequest;
@@ -196,6 +193,9 @@
Slog.d(LOG_TAG, "[user: " + mUserId + "] handlePendingRequest()");
}
pendingRequest.run();
+ if (pendingRequest.isFinal()) {
+ mCompleted = true;
+ }
}
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index f00d6c5..599bbfe 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -15,6 +15,9 @@
*/
package com.android.server.autofill.ui;
+import static android.view.autofill.AutoFillManager.AutofillCallback.EVENT_INPUT_HIDDEN;
+import static android.view.autofill.AutoFillManager.AutofillCallback.EVENT_INPUT_SHOWN;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -26,8 +29,8 @@
import android.service.autofill.FillResponse;
import android.service.autofill.SaveInfo;
import android.text.TextUtils;
-import android.util.Slog;
import android.text.format.DateUtils;
+import android.util.Slog;
import android.view.autofill.AutoFillId;
import android.widget.Toast;
@@ -62,6 +65,8 @@
void authenticate(@NonNull IntentSender intent);
void fill(@NonNull Dataset dataset);
void save();
+ void cancelSave();
+ void onEvent(AutoFillId id, int event);
}
public AutoFillUI(@NonNull Context context) {
@@ -97,8 +102,13 @@
/**
* Hides the fill UI.
*/
- public void hideFillUi() {
- mHandler.post(this::hideFillUiUiThread);
+ public void hideFillUi(AutoFillId id) {
+ mHandler.post(() -> {
+ hideFillUiUiThread();
+ if (mCallback != null) {
+ mCallback.onEvent(id, EVENT_INPUT_HIDDEN);
+ }
+ });
}
/**
@@ -175,6 +185,7 @@
// TODO(b/33197203): add MetricsLogger call
}
});
+ mCallback.onEvent(focusedId, EVENT_INPUT_SHOWN);
});
}
@@ -210,6 +221,9 @@
+ listener, e);
}
}
+ if (mCallback != null) {
+ mCallback.cancelSave();
+ }
}
}, mSaveTimeoutMs);
});
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index c26032ce..8f2b428 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -80,6 +80,7 @@
import android.content.pm.Signature;
import android.database.ContentObserver;
import android.net.Uri;
+import android.os.PowerSaveState;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -122,6 +123,7 @@
import com.android.server.SystemService;
import com.android.server.backup.PackageManagerBackupAgent.Metadata;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
import libcore.io.IoUtils;
import java.io.BufferedInputStream;
@@ -5440,7 +5442,9 @@
// Don't run the backup if we're in battery saver mode, but reschedule
// to try again in the not-so-distant future.
- if (mPowerManager.isPowerSaveMode()) {
+ final PowerSaveState result =
+ mPowerManager.getPowerSaveState(ServiceType.FULL_BACKUP);
+ if (result.batterySaverEnabled) {
if (DEBUG) Slog.i(TAG, "Deferring scheduled full backups in battery saver mode");
FullBackupJob.schedule(mContext, KeyValueBackupJob.BATCH_INTERVAL);
return false;
@@ -9889,7 +9893,9 @@
public void backupNow() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "backupNow");
- if (mPowerManager.isPowerSaveMode()) {
+ final PowerSaveState result =
+ mPowerManager.getPowerSaveState(ServiceType.KEYVALUE_BACKUP);
+ if (result.batterySaverEnabled) {
if (DEBUG) Slog.v(TAG, "Not running backup while in battery save mode");
KeyValueBackupJob.schedule(mContext); // try again in several hours
} else {
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 81f137e..c9dd116 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -678,7 +678,7 @@
pw.println("Battery service (battery) commands:");
pw.println(" help");
pw.println(" Print this help text.");
- pw.println(" set [-f] [ac|usb|wireless|status|level|invalid] <value>");
+ pw.println(" set [-f] [ac|usb|wireless|status|level|present|invalid] <value>");
pw.println(" Force a battery property value, freezing battery state.");
pw.println(" -f: force a battery change broadcast be sent, prints new sequence.");
pw.println(" unplug [-f]");
@@ -748,6 +748,9 @@
}
boolean update = true;
switch (key) {
+ case "present":
+ mBatteryProps.batteryPresent = Integer.parseInt(value) != 0;
+ break;
case "ac":
mBatteryProps.chargerAcOnline = Integer.parseInt(value) != 0;
break;
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 8888325..5fe6952 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -25,6 +25,7 @@
import android.database.ContentObserver;
import android.hardware.input.InputManager;
import android.media.AudioManager;
+import android.os.PowerSaveState;
import android.os.BatteryStats;
import android.os.Handler;
import android.os.IVibratorService;
@@ -50,6 +51,7 @@
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -233,10 +235,15 @@
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mPowerManagerInternal.registerLowPowerModeObserver(
new PowerManagerInternal.LowPowerModeListener() {
- @Override
- public void onLowPowerModeChanged(boolean enabled) {
- updateInputDeviceVibrators();
- }
+ @Override
+ public int getServiceType() {
+ return ServiceType.VIBRATION;
+ }
+
+ @Override
+ public void onLowPowerModeChanged(PowerSaveState result) {
+ updateInputDeviceVibrators();
+ }
});
mContext.getContentResolver().registerContentObserver(
@@ -553,7 +560,8 @@
} catch (SettingNotFoundException snfe) {
}
- mLowPowerMode = mPowerManagerInternal.getLowPowerModeEnabled();
+ mLowPowerMode = mPowerManagerInternal
+ .getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled;
if (mVibrateInputDevicesSetting) {
if (!mInputDeviceListenerRegistered) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index dc73b63..ea9b651 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -503,10 +503,10 @@
UserHandle.getUserId(callingUid));
} catch (NameNotFoundException e) {
Log.d(TAG, "Package not found " + e.getMessage());
- return new HashMap<>();
+ return new LinkedHashMap<>();
}
- Map<Account, Integer> result = new HashMap<>();
+ Map<Account, Integer> result = new LinkedHashMap<>();
for (String accountType : accountTypes) {
synchronized (accounts.cacheLock) {
final Account[] accountsOfType = accounts.accountCache.get(accountType);
@@ -1040,7 +1040,7 @@
private static HashMap<String, Integer> getAuthenticatorTypeAndUIDForUser(
IAccountAuthenticatorCache authCache,
int userId) {
- HashMap<String, Integer> knownAuth = new HashMap<>();
+ HashMap<String, Integer> knownAuth = new LinkedHashMap<>();
for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> service : authCache
.getAllServices(userId)) {
knownAuth.put(service.type.type, service.uid);
@@ -3927,7 +3927,7 @@
List<String> visibleAccountTypes = getTypesVisibleToCaller(callingUid, userId,
opPackageName);
if (visibleAccountTypes.isEmpty()) {
- return new Account[0];
+ return EMPTY_ACCOUNT_ARRAY;
}
long identityToken = clearCallingIdentity();
try {
@@ -4047,7 +4047,7 @@
opPackageName);
if (visibleAccountTypes.isEmpty()
|| (type != null && !visibleAccountTypes.contains(type))) {
- return new Account[]{};
+ return EMPTY_ACCOUNT_ARRAY;
} else if (visibleAccountTypes.contains(type)) {
// Prune the list down to just the requested type.
visibleAccountTypes = new ArrayList<>();
@@ -4194,11 +4194,11 @@
packageUid = mPackageManager.getPackageUidAsUser(packageName, userId);
} catch (NameNotFoundException re) {
Slog.e(TAG, "Couldn't determine the packageUid for " + packageName + re);
- return new Account[0];
+ return EMPTY_ACCOUNT_ARRAY;
}
if (!UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
&& !isAccountManagedByCaller(type, callingUid, userId)) {
- return new Account[0];
+ return EMPTY_ACCOUNT_ARRAY;
}
return getAccountsAsUser(type, userId,
@@ -4229,7 +4229,7 @@
if (!visibleAccountTypes.contains(type)) {
Bundle result = new Bundle();
// Need to return just the accounts that are from matching signatures.
- result.putParcelableArray(AccountManager.KEY_ACCOUNTS, new Account[0]);
+ result.putParcelableArray(AccountManager.KEY_ACCOUNTS, EMPTY_ACCOUNT_ARRAY);
try {
response.onResult(result);
} catch (RemoteException e) {
@@ -5368,10 +5368,11 @@
return newAccountsForType[oldLength];
}
+ @NonNull
private Account[] filterAccounts(UserAccounts accounts, Account[] unfiltered, int callingUid,
String callingPackage, boolean includeManagedNotVisible) {
// filter based on visibility.
- Map<Account, Integer> firstPass = new HashMap<>();
+ Map<Account, Integer> firstPass = new LinkedHashMap<>();
for (Account account : unfiltered) {
int visibility = resolveAccountVisibility(account, callingPackage, accounts);
if ((visibility == AccountManager.VISIBILITY_VISIBLE
@@ -5390,8 +5391,10 @@
return filtered;
}
+ @NonNull
private Map<Account, Integer> filterSharedAccounts(UserAccounts userAccounts,
- Map<Account, Integer> unfiltered, int callingUid, String callingPackage) {
+ @NonNull Map<Account, Integer> unfiltered, int callingUid,
+ String callingPackage) {
// first part is to filter shared accounts.
// unfiltered type check is not necessary.
if (getUserManager() == null || userAccounts == null || userAccounts.userId < 0
@@ -5441,7 +5444,7 @@
} catch (NameNotFoundException e) {
Log.d(TAG, "Package not found " + e.getMessage());
}
- Map<Account, Integer> filtered = new HashMap<>();
+ Map<Account, Integer> filtered = new LinkedHashMap<>();
for (Map.Entry<Account, Integer> entry : unfiltered.entrySet()) {
Account account = entry.getKey();
if (account.type.equals(requiredAccountType)) {
@@ -5469,6 +5472,7 @@
* packageName can be null. If not null, it should be used to filter out restricted accounts
* that the package is not allowed to access.
*/
+ @NonNull
protected Account[] getAccountsFromCacheLocked(UserAccounts userAccounts, String accountType,
int callingUid, String callingPackage, boolean includeManagedNotVisible) {
if (callingPackage == null) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 54ee5dc..10b1f2b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -10088,8 +10088,18 @@
}
/**
- * Moves an activity, and all of the other activities within the same task, to the bottom
- * of the history stack. The activity's order within the task is unchanged.
+ * Attempts to move a task backwards in z-order (the order of activities within the task is
+ * unchanged).
+ *
+ * There are several possible results of this call:
+ * - if the task is locked, then we will show the lock toast
+ * - if there is a task behind the provided task, then that task is made visible and resumed as
+ * this task is moved to the back
+ * - otherwise, if there are no other tasks in the stack:
+ * - if this task is in the pinned stack, then we remove the stack completely, which will
+ * have the effect of moving the task to the top or bottom of the fullscreen stack
+ * (depending on whether it is visible)
+ * - otherwise, we simply return home and hide this task
*
* @param token A reference to the activity we wish to move
* @param nonRoot If false then this only works if the activity is the root
@@ -10105,10 +10115,6 @@
int taskId = ActivityRecord.getTaskForActivityLocked(token, !nonRoot);
final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
if (task != null) {
- if (mStackSupervisor.isLockedTask(task)) {
- mStackSupervisor.showLockTaskToast();
- return false;
- }
return ActivityRecord.getStackLocked(token).moveTaskToBackLocked(taskId);
}
} finally {
@@ -10367,7 +10373,7 @@
synchronized (this) {
if (!mSupportsPictureInPicture) {
throw new IllegalStateException("moveTopActivityToPinnedStack:"
- + "Device doesn't support picture-in-pciture mode");
+ + "Device doesn't support picture-in-picture mode");
}
long ident = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 5d4bff9..a679a31 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -4351,9 +4351,13 @@
Slog.i(TAG, "moveTaskToBack: bad taskId=" + taskId);
return false;
}
-
Slog.i(TAG, "moveTaskToBack: " + tr);
- mStackSupervisor.removeLockedTaskLocked(tr);
+
+ // If the task is locked, then show the lock task toast
+ if (mStackSupervisor.isLockedTask(tr)) {
+ mStackSupervisor.showLockTaskToast();
+ return false;
+ }
// If we have a watcher, preflight the move before committing to it. First check
// for *other* available tasks, but if none are available, then try again allowing the
@@ -4416,12 +4420,24 @@
prevIsHome = true;
}
}
- mTaskHistory.remove(tr);
- mTaskHistory.add(0, tr);
- updateTaskMovement(tr, false);
- // There is an assumption that moving a task to the back moves it behind the home activity.
- // We make sure here that some activity in the stack will launch home.
+ boolean requiresMove = mTaskHistory.indexOf(tr) != 0;
+ if (requiresMove) {
+ mTaskHistory.remove(tr);
+ mTaskHistory.add(0, tr);
+ updateTaskMovement(tr, false);
+
+ mWindowManager.prepareAppTransition(TRANSIT_TASK_TO_BACK, false);
+ mWindowContainerController.positionChildAtBottom(tr.getWindowContainerController());
+ }
+
+ if (mStackId == PINNED_STACK_ID) {
+ mStackSupervisor.removeStackLocked(PINNED_STACK_ID);
+ return true;
+ }
+
+ // Otherwise, there is an assumption that moving a task to the back moves it behind the
+ // home activity. We make sure here that some activity in the stack will launch home.
int numTasks = mTaskHistory.size();
for (int taskNdx = numTasks - 1; taskNdx >= 1; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
@@ -4434,9 +4450,6 @@
}
}
- mWindowManager.prepareAppTransition(TRANSIT_TASK_TO_BACK, false);
- mWindowContainerController.positionChildAtBottom(tr.getWindowContainerController());
-
final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null;
if (prevIsHome || (task == tr && canGoHome) || (numTasks <= 1 && isOnHomeDisplay())) {
if (!mService.mBooting && !mService.mBooted) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 3571302..1712d48 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -24,6 +24,7 @@
import android.content.pm.PackageManager;
import android.net.wifi.IWifiManager;
import android.net.wifi.WifiActivityEnergyInfo;
+import android.os.PowerSaveState;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Handler;
@@ -60,6 +61,7 @@
import com.android.internal.os.PowerProfile;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
import java.io.File;
import java.io.FileDescriptor;
@@ -232,7 +234,9 @@
public void initPowerManagement() {
final PowerManagerInternal powerMgr = LocalServices.getService(PowerManagerInternal.class);
powerMgr.registerLowPowerModeObserver(this);
- mStats.notePowerSaveMode(powerMgr.getLowPowerModeEnabled());
+ mStats.notePowerSaveMode(
+ powerMgr.getLowPowerState(ServiceType.BATTERY_STATS)
+ .batterySaverEnabled);
(new WakeupReasonThread()).start();
}
@@ -258,9 +262,14 @@
}
@Override
- public void onLowPowerModeChanged(boolean enabled) {
+ public int getServiceType() {
+ return ServiceType.BATTERY_STATS;
+ }
+
+ @Override
+ public void onLowPowerModeChanged(PowerSaveState result) {
synchronized (mStats) {
- mStats.notePowerSaveMode(enabled);
+ mStats.notePowerSaveMode(result.batterySaverEnabled);
}
}
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index abdcfe7..b3f1548 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -46,9 +46,9 @@
/**
* set to true so the framework enforces ducking itself, without communicating to apps
- * that they lost focus.
+ * that they lost focus for most use cases.
*/
- static final boolean ENFORCE_DUCKING = false;
+ static final boolean ENFORCE_DUCKING = true;
/**
* set to true so the framework enforces muting media/game itself when the device is ringing
* or in a call.
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 6932427..82a0ff6 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -309,7 +309,7 @@
return false;
} else {
try {
- if (DEBUG) { Log.v(TAG, "ducking player " + piid); }
+ Log.v(TAG, "ducking player " + piid);
apc.getPlayerProxy().applyVolumeShaper(
DUCK_VSHAPE,
PLAY_CREATE_IF_NEEDED);
@@ -339,7 +339,7 @@
if (apc != null
&& winner.hasSameUid(apc.getClientUid())) {
try {
- if (DEBUG) { Log.v(TAG, "unducking player" + piid); }
+ Log.v(TAG, "unducking player" + piid);
mDuckedPlayers.remove(new Integer(piid));
apc.getPlayerProxy().applyVolumeShaper(
DUCK_ID,
@@ -381,11 +381,11 @@
}
if (mute) {
try {
- if (DEBUG) { Log.v(TAG, "muting player" + piid); }
+ Log.v(TAG, "call: muting player" + piid);
apc.getPlayerProxy().setVolume(0.0f);
mMutedPlayers.add(piid);
} catch (Exception e) {
- Log.e(TAG, "Error muting player " + piid, e);
+ Log.e(TAG, "call: error muting player " + piid, e);
}
}
}
@@ -405,10 +405,10 @@
final AudioPlaybackConfiguration apc = mPlayers.get(piid);
if (apc != null) {
try {
- if (DEBUG) { Log.v(TAG, "unmuting player" + piid); }
+ Log.v(TAG, "call: unmuting player" + piid);
apc.getPlayerProxy().setVolume(1.0f);
} catch (Exception e) {
- Log.e(TAG, "Error unmuting player " + piid, e);
+ Log.e(TAG, "call: error unmuting player " + piid, e);
}
}
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index fbda901..cf33313 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -790,6 +790,8 @@
if (userAgent != null) {
urlConnection.setRequestProperty("User-Agent", userAgent);
}
+ // cannot read request header after connection
+ String requestHeader = urlConnection.getRequestProperties().toString();
// Time how long it takes to get a response to our request
long requestTimestamp = SystemClock.elapsedRealtime();
@@ -803,6 +805,7 @@
validationLog(ValidationProbeEvent.getProbeName(probeType) + " " + url +
" time=" + (responseTimestamp - requestTimestamp) + "ms" +
" ret=" + httpResponseCode +
+ " request=" + requestHeader +
" headers=" + urlConnection.getHeaderFields());
// NOTE: We may want to consider an "HTTP/1.0 204" response to be a captive
// portal. The only example of this seen so far was a captive portal. For
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index bed269c..0ef0561 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -705,11 +705,14 @@
mAppliedDimming = false;
}
- // If low power mode is enabled, cut the brightness level by half
+ // If low power mode is enabled, scale brightness by screenLowPowerBrightnessFactor
// as long as it is above the minimum threshold.
if (mPowerRequest.lowPowerMode) {
if (brightness > mScreenBrightnessRangeMinimum) {
- brightness = Math.max(brightness / 2, mScreenBrightnessRangeMinimum);
+ final float brightnessFactor =
+ Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
+ final int lowPowerBrightness = (int) (brightness * brightnessFactor);
+ brightness = Math.max(lowPowerBrightness, mScreenBrightnessRangeMinimum);
}
if (!mAppliedLowPower) {
slowChange = false;
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 4c6b832..fc86d68 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1659,6 +1659,17 @@
}
@Override
+ public void setStandbyMode(final boolean isStandbyModeOn) {
+ enforceAccessPermission();
+ runOnServiceThread(new Runnable() {
+ @Override
+ public void run() {
+ HdmiControlService.this.setStandbyMode(isStandbyModeOn);
+ }
+ });
+ }
+
+ @Override
protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
@@ -2203,6 +2214,29 @@
}
}
+ void setStandbyMode(boolean isStandbyModeOn) {
+ assertRunOnServiceThread();
+ if (isPowerOnOrTransient() && isStandbyModeOn) {
+ mPowerManager.goToSleep(SystemClock.uptimeMillis(),
+ PowerManager.GO_TO_SLEEP_REASON_HDMI, 0);
+ if (playback() != null) {
+ playback().sendStandby(0 /* unused */);
+ }
+ } else if (isPowerStandbyOrTransient() && !isStandbyModeOn) {
+ mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.server.hdmi:WAKE");
+ if (playback() != null) {
+ oneTouchPlay(new IHdmiControlCallback.Stub() {
+ @Override
+ public void onComplete(int result) {
+ if (result != HdmiControlManager.RESULT_SUCCESS) {
+ Slog.w(TAG, "Failed to complete 'one touch play'. result=" + result);
+ }
+ }
+ });
+ }
+ }
+ }
+
boolean isProhibitMode() {
synchronized (mLock) {
return mProhibitMode;
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index fdaba0b..3a1ddd7 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -16,13 +16,6 @@
package com.android.server.location;
-import com.android.internal.app.IAppOpsService;
-import com.android.internal.app.IBatteryStats;
-import com.android.internal.location.GpsNetInitiatedHandler;
-import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
-import com.android.internal.location.ProviderProperties;
-import com.android.internal.location.ProviderRequest;
-
import android.app.AlarmManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
@@ -55,6 +48,7 @@
import android.net.NetworkRequest;
import android.net.Uri;
import android.os.AsyncTask;
+import android.os.PowerSaveState;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Bundle;
@@ -81,6 +75,17 @@
import android.util.Log;
import android.util.NtpTrustedTime;
+import com.android.internal.app.IAppOpsService;
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.location.GpsNetInitiatedHandler;
+import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
+import com.android.internal.location.ProviderProperties;
+import com.android.internal.location.ProviderRequest;
+import com.android.server.power.BatterySaverPolicy;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
+
+import libcore.io.IoUtils;
+
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -96,7 +101,6 @@
import java.util.Properties;
import java.util.Map;
import java.util.HashMap;
-import libcore.io.IoUtils;
/**
* A GNSS implementation of LocationProvider used by LocationManager.
@@ -243,14 +247,6 @@
private static final int TCP_MIN_PORT = 0;
private static final int TCP_MAX_PORT = 0xffff;
- // Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode.
- private static final int BATTERY_SAVER_MODE_NO_CHANGE = 0;
- // Value of batterySaverGpsMode such that GPS is disabled when battery saver mode
- // is enabled and the screen is off.
- private static final int BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF = 1;
- // Secure setting for GPS behavior when battery saver mode is on.
- private static final String BATTERY_SAVER_GPS_MODE = "batterySaverGpsMode";
-
/** simpler wrapper for ProviderRequest + Worksource */
private static class GpsRequest {
public ProviderRequest request;
@@ -548,11 +544,12 @@
private void updateLowPowerMode() {
// Disable GPS if we are in device idle mode.
boolean disableGps = mPowerManager.isDeviceIdleMode();
- switch (Settings.Secure.getInt(mContext.getContentResolver(), BATTERY_SAVER_GPS_MODE,
- BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF)) {
- case BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF:
+ final PowerSaveState result =
+ mPowerManager.getPowerSaveState(ServiceType.GPS);
+ switch (result.gpsMode) {
+ case BatterySaverPolicy.GPS_MODE_DISABLED_WHEN_SCREEN_OFF:
// If we are in battery saver mode and the screen is off, disable GPS.
- disableGps |= mPowerManager.isPowerSaveMode() && !mPowerManager.isInteractive();
+ disableGps |= result.batterySaverEnabled && !mPowerManager.isInteractive();
break;
}
if (disableGps != mDisableGps) {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 5078998..4e9d838 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -131,6 +131,7 @@
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
+import android.os.PowerSaveState;
import android.os.Binder;
import android.os.Environment;
import android.os.Handler;
@@ -180,6 +181,7 @@
import com.android.server.LocalServices;
import com.android.server.SystemConfig;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
import libcore.io.IoUtils;
import com.google.android.collect.Lists;
@@ -590,18 +592,26 @@
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mPowerManagerInternal.registerLowPowerModeObserver(
new PowerManagerInternal.LowPowerModeListener() {
- @Override
- public void onLowPowerModeChanged(boolean enabled) {
- if (LOGD) Slog.d(TAG, "onLowPowerModeChanged(" + enabled + ")");
- synchronized (mUidRulesFirstLock) {
- if (mRestrictPower != enabled) {
- mRestrictPower = enabled;
- updateRulesForRestrictPowerUL();
+ @Override
+ public int getServiceType() {
+ return ServiceType.NETWORK_FIREWALL;
}
- }
- }
+
+ @Override
+ public void onLowPowerModeChanged(PowerSaveState result) {
+ final boolean enabled = result.batterySaverEnabled;
+ if (LOGD) Slog.d(TAG,
+ "onLowPowerModeChanged(" + enabled + ")");
+ synchronized (mUidRulesFirstLock) {
+ if (mRestrictPower != enabled) {
+ mRestrictPower = enabled;
+ updateRulesForRestrictPowerUL();
+ }
+ }
+ }
});
- mRestrictPower = mPowerManagerInternal.getLowPowerModeEnabled();
+ mRestrictPower = mPowerManagerInternal.getLowPowerState(
+ ServiceType.NETWORK_FIREWALL).batterySaverEnabled;
mSystemReady = true;
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 1af541d..2026c1b 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -504,6 +504,25 @@
}
@Override
+ public boolean setEnabledExclusive(@Nullable final String packageName, final boolean enable,
+ int userId) throws RemoteException {
+ enforceChangeOverlayPackagesPermission("setEnabled");
+ userId = handleIncomingUser(userId, "setEnabled");
+ if (packageName == null) {
+ return false;
+ }
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ return mImpl.setEnabledExclusive(packageName, enable, userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
public boolean setPriority(@Nullable final String packageName,
@Nullable final String parentPackageName, int userId) throws RemoteException {
enforceChangeOverlayPackagesPermission("setPriority");
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index ed49383..b085179 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -301,6 +301,38 @@
}
}
+ boolean setEnabledExclusive(@NonNull final String packageName, final boolean enable,
+ final int userId) {
+ if (DEBUG) {
+ Slog.d(TAG, String.format("setEnabled packageName=%s enable=%s userId=%d",
+ packageName, enable, userId));
+ }
+
+ final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
+ if (overlayPackage == null) {
+ return false;
+ }
+
+ try {
+ final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
+ List<OverlayInfo> allOverlays = getOverlayInfosForTarget(oi.targetPackageName, userId);
+
+ // Disable all other overlays.
+ allOverlays.remove(oi);
+ for (int i = 0; i < allOverlays.size(); i++) {
+ mSettings.setEnabled(allOverlays.get(i).packageName, userId, false);
+ }
+
+ final PackageInfo targetPackage =
+ mPackageManager.getPackageInfo(oi.targetPackageName, userId);
+ mSettings.setEnabled(packageName, userId, enable);
+ updateState(targetPackage, overlayPackage, userId);
+ return true;
+ } catch (OverlayManagerSettings.BadKeyException e) {
+ return false;
+ }
+ }
+
boolean setPriority(@NonNull final String packageName,
@NonNull final String newParentPackageName, final int userId) {
return mSettings.setPriority(packageName, newParentPackageName, userId);
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index fb8429d..36eba8e 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -414,13 +414,6 @@
final long id = Binder.clearCallingIdentity();
try {
switch (key) {
- case UserManager.DISALLOW_CONFIG_WIFI:
- if (newValue) {
- android.provider.Settings.Secure.putIntForUser(cr,
- android.provider.Settings.Global
- .WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0, userId);
- }
- break;
case UserManager.DISALLOW_DATA_ROAMING:
if (newValue) {
// DISALLOW_DATA_ROAMING user restriction is set.
diff --git a/services/core/java/com/android/server/power/BatterySaverPolicy.java b/services/core/java/com/android/server/power/BatterySaverPolicy.java
new file mode 100644
index 0000000..8d20531
--- /dev/null
+++ b/services/core/java/com/android/server/power/BatterySaverPolicy.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.power;
+
+import android.annotation.IntDef;
+import android.content.ContentResolver;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.provider.Settings;
+import android.util.KeyValueListParser;
+import android.util.Slog;
+import android.os.PowerSaveState;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Class to decide whether to turn on battery saver mode for specific service
+ */
+public class BatterySaverPolicy extends ContentObserver {
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({ServiceType.GPS,
+ ServiceType.VIBRATION,
+ ServiceType.ANIMATION,
+ ServiceType.FULL_BACKUP,
+ ServiceType.KEYVALUE_BACKUP,
+ ServiceType.NETWORK_FIREWALL,
+ ServiceType.SCREEN_BRIGHTNESS,
+ ServiceType.SOUND,
+ ServiceType.BATTERY_STATS})
+ public @interface ServiceType {
+ int NULL = 0;
+ int GPS = 1;
+ int VIBRATION = 2;
+ int ANIMATION = 3;
+ int FULL_BACKUP = 4;
+ int KEYVALUE_BACKUP = 5;
+ int NETWORK_FIREWALL = 6;
+ int SCREEN_BRIGHTNESS = 7;
+ int SOUND = 8;
+ int BATTERY_STATS = 9;
+ }
+
+ private static final String TAG = "BatterySaverPolicy";
+
+ // Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode.
+ public static final int GPS_MODE_NO_CHANGE = 0;
+ // Value of batterySaverGpsMode such that GPS is disabled when battery saver mode
+ // is enabled and the screen is off.
+ public static final int GPS_MODE_DISABLED_WHEN_SCREEN_OFF = 1;
+ // Secure setting for GPS behavior when battery saver mode is on.
+ public static final String SECURE_KEY_GPS_MODE = "batterySaverGpsMode";
+
+ private static final String KEY_GPS_MODE = "gps_mode";
+ private static final String KEY_VIBRATION_DISABLED = "vibration_disabled";
+ private static final String KEY_ANIMATION_DISABLED = "animation_disabled";
+ private static final String KEY_SOUNDTRIGGER_DISABLED = "soundtrigger_disabled";
+ private static final String KEY_FIREWALL_DISABLED = "firewall_disabled";
+ private static final String KEY_ADJUST_BRIGHTNESS_DISABLED = "adjust_brightness_disabled";
+ private static final String KEY_ADJUST_BRIGHTNESS_FACTOR = "adjust_brightness_factor";
+ private static final String KEY_FULLBACKUP_DEFERRED = "fullbackup_deferred";
+ private static final String KEY_KEYVALUE_DEFERRED = "keyvaluebackup_deferred";
+
+ private final KeyValueListParser mParser = new KeyValueListParser(',');
+
+ /**
+ * {@code true} if vibration is disabled in battery saver mode.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_VIBRATION_DISABLED
+ */
+ private boolean mVibrationDisabled;
+
+ /**
+ * {@code true} if animation is disabled in battery saver mode.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_ANIMATION_DISABLED
+ */
+ private boolean mAnimationDisabled;
+
+ /**
+ * {@code true} if sound trigger is disabled in battery saver mode
+ * in battery saver mode.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_SOUNDTRIGGER_DISABLED
+ */
+ private boolean mSoundTriggerDisabled;
+
+ /**
+ * {@code true} if full backup is deferred in battery saver mode.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_FULLBACKUP_DEFERRED
+ */
+ private boolean mFullBackupDeferred;
+
+ /**
+ * {@code true} if key value backup is deferred in battery saver mode.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_KEYVALUE_DEFERRED
+ */
+ private boolean mKeyValueBackupDeferred;
+
+ /**
+ * {@code true} if network policy firewall is disabled in battery saver mode.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_FIREWALL_DISABLED
+ */
+ private boolean mFireWallDisabled;
+
+ /**
+ * {@code true} if adjust brightness is disabled in battery saver mode.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_ADJUST_BRIGHTNESS_DISABLED
+ */
+ private boolean mAdjustBrightnessDisabled;
+
+ /**
+ * This is the flag to decide the gps mode in battery saver mode.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_GPS_MODE
+ */
+ private int mGpsMode;
+
+ /**
+ * This is the flag to decide the how much to adjust the screen brightness. This is
+ * the float value from 0 to 1 where 1 means don't change brightness.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_ADJUST_BRIGHTNESS_FACTOR
+ */
+ private float mAdjustBrightnessFactor;
+
+ private ContentResolver mContentResolver;
+
+ public BatterySaverPolicy(Handler handler) {
+ super(handler);
+ }
+
+ public void start(ContentResolver contentResolver) {
+ mContentResolver = contentResolver;
+
+ mContentResolver.registerContentObserver(Settings.Global.getUriFor(
+ Settings.Global.BATTERY_SAVER_CONSTANTS), false, this);
+ onChange(true, null);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ final String value = Settings.Global.getString(mContentResolver,
+ Settings.Global.BATTERY_SAVER_CONSTANTS);
+ updateConstants(value);
+ }
+
+ @VisibleForTesting
+ void updateConstants(final String value) {
+ synchronized (BatterySaverPolicy.this) {
+ try {
+ mParser.setString(value);
+ } catch (IllegalArgumentException e) {
+ Slog.e(TAG, "Bad battery saver constants");
+ }
+
+ mVibrationDisabled = mParser.getBoolean(KEY_VIBRATION_DISABLED, true);
+ mAnimationDisabled = mParser.getBoolean(KEY_ANIMATION_DISABLED, true);
+ mSoundTriggerDisabled = mParser.getBoolean(KEY_SOUNDTRIGGER_DISABLED, true);
+ mFullBackupDeferred = mParser.getBoolean(KEY_FULLBACKUP_DEFERRED, true);
+ mKeyValueBackupDeferred = mParser.getBoolean(KEY_KEYVALUE_DEFERRED, true);
+ mFireWallDisabled = mParser.getBoolean(KEY_FIREWALL_DISABLED, false);
+ mAdjustBrightnessDisabled = mParser.getBoolean(KEY_ADJUST_BRIGHTNESS_DISABLED, false);
+ mAdjustBrightnessFactor = mParser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR, 0.5f);
+
+ // Get default value from Settings.Secure
+ final int defaultGpsMode = Settings.Secure.getInt(mContentResolver, SECURE_KEY_GPS_MODE,
+ GPS_MODE_DISABLED_WHEN_SCREEN_OFF);
+ mGpsMode = mParser.getInt(KEY_GPS_MODE, defaultGpsMode);
+ }
+ }
+
+ /**
+ * Get the {@link PowerSaveState} based on {@paramref type} and {@paramref realMode}.
+ * The result will have {@link PowerSaveState#batterySaverEnabled} and some other
+ * parameters when necessary.
+ *
+ * @param type type of the service, one of {@link ServiceType}
+ * @param realMode whether the battery saver is on by default
+ * @return State data that contains battery saver data
+ */
+ public PowerSaveState getBatterySaverPolicy(@ServiceType int type, boolean realMode) {
+ synchronized (BatterySaverPolicy.this) {
+ final PowerSaveState.Builder builder = new PowerSaveState.Builder();
+ if (!realMode) {
+ return builder.setBatterySaverEnabled(realMode)
+ .build();
+ }
+ switch (type) {
+ case ServiceType.GPS:
+ return builder.setBatterySaverEnabled(realMode)
+ .setGpsMode(mGpsMode)
+ .build();
+ case ServiceType.ANIMATION:
+ return builder.setBatterySaverEnabled(mAnimationDisabled)
+ .build();
+ case ServiceType.FULL_BACKUP:
+ return builder.setBatterySaverEnabled(mFullBackupDeferred)
+ .build();
+ case ServiceType.KEYVALUE_BACKUP:
+ return builder.setBatterySaverEnabled(mKeyValueBackupDeferred)
+ .build();
+ case ServiceType.NETWORK_FIREWALL:
+ return builder.setBatterySaverEnabled(!mFireWallDisabled)
+ .build();
+ case ServiceType.SCREEN_BRIGHTNESS:
+ return builder.setBatterySaverEnabled(!mAdjustBrightnessDisabled)
+ .setBrightnessFactor(mAdjustBrightnessFactor)
+ .build();
+ case ServiceType.SOUND:
+ return builder.setBatterySaverEnabled(mSoundTriggerDisabled)
+ .build();
+ case ServiceType.VIBRATION:
+ return builder.setBatterySaverEnabled(mVibrationDisabled)
+ .build();
+ default:
+ return builder.setBatterySaverEnabled(realMode)
+ .build();
+ }
+ }
+ }
+
+ public void dump(PrintWriter pw) {
+ pw.println();
+ pw.println("Battery saver policy");
+ pw.println(" Settings " + Settings.Global.BATTERY_SAVER_CONSTANTS);
+ pw.println(" value: " + Settings.Global.getString(mContentResolver,
+ Settings.Global.BATTERY_SAVER_CONSTANTS));
+
+ pw.println();
+ pw.println(" " + KEY_VIBRATION_DISABLED + "=" + mVibrationDisabled);
+ pw.println(" " + KEY_ANIMATION_DISABLED + "=" + mAnimationDisabled);
+ pw.println(" " + KEY_FULLBACKUP_DEFERRED + "=" + mFullBackupDeferred);
+ pw.println(" " + KEY_KEYVALUE_DEFERRED + "=" + mKeyValueBackupDeferred);
+ pw.println(" " + KEY_FIREWALL_DISABLED + "=" + mFireWallDisabled);
+ pw.println(" " + KEY_ADJUST_BRIGHTNESS_DISABLED + "=" + mAdjustBrightnessDisabled);
+ pw.println(" " + KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + mAdjustBrightnessFactor);
+ pw.println(" " + KEY_GPS_MODE + "=" + mGpsMode);
+
+ }
+}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index d3931fb..c58b527 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -43,6 +43,7 @@
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
+import android.os.PowerSaveState;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -68,6 +69,7 @@
import android.util.proto.ProtoOutputStream;
import android.view.Display;
import android.view.WindowManagerPolicy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.BackgroundThread;
@@ -80,7 +82,7 @@
import com.android.server.am.BatteryStatsService;
import com.android.server.lights.Light;
import com.android.server.lights.LightsManager;
-
+import com.android.server.power.BatterySaverPolicy.ServiceType;
import libcore.util.Objects;
import java.io.FileDescriptor;
@@ -192,6 +194,7 @@
private final Context mContext;
private final ServiceThread mHandlerThread;
private final PowerManagerHandler mHandler;
+ private final BatterySaverPolicy mBatterySaverPolicy;
private LightsManager mLightsManager;
private BatteryManagerInternal mBatteryManagerInternal;
@@ -605,6 +608,7 @@
mHandlerThread.start();
mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
mConstants = new Constants(mHandler);
+ mBatterySaverPolicy = new BatterySaverPolicy(mHandler);
synchronized (mLock) {
mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
@@ -625,6 +629,21 @@
}
}
+ @VisibleForTesting
+ PowerManagerService(Context context, BatterySaverPolicy batterySaverPolicy) {
+ super(context);
+
+ mBatterySaverPolicy = batterySaverPolicy;
+ mContext = context;
+ mHandlerThread = new ServiceThread(TAG,
+ Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
+ mHandlerThread.start();
+ mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
+ mConstants = new Constants(mHandler);
+ mDisplaySuspendBlocker = null;
+ mWakeLockSuspendBlocker = null;
+ }
+
@Override
public void onStart() {
publishBinderService(Context.POWER_SERVICE, new BinderService());
@@ -704,6 +723,7 @@
final ContentResolver resolver = mContext.getContentResolver();
mConstants.start(resolver);
+ mBatterySaverPolicy.start(resolver);
// Register for settings changes.
resolver.registerContentObserver(Settings.Secure.getUriFor(
@@ -939,8 +959,12 @@
listeners = new ArrayList<PowerManagerInternal.LowPowerModeListener>(
mLowPowerModeListeners);
}
- for (int i=0; i<listeners.size(); i++) {
- listeners.get(i).onLowPowerModeChanged(lowPowerModeEnabled);
+ for (int i = 0; i < listeners.size(); i++) {
+ final PowerManagerInternal.LowPowerModeListener listener = listeners.get(i);
+ final PowerSaveState result =
+ mBatterySaverPolicy.getBatterySaverPolicy(
+ listener.getServiceType(), lowPowerModeEnabled);
+ listener.onLowPowerModeChanged(result);
}
intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -2252,9 +2276,10 @@
mDisplayPowerRequest.brightnessSetByUser = brightnessSetByUser;
mDisplayPowerRequest.useAutoBrightness = autoBrightness;
mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
- mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled;
mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();
+ updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);
+
if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND
@@ -2671,6 +2696,14 @@
}
}
+ @VisibleForTesting
+ void updatePowerRequestFromBatterySaverPolicy(DisplayPowerRequest displayPowerRequest) {
+ PowerSaveState state = mBatterySaverPolicy.
+ getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS, mLowPowerModeEnabled);
+ displayPowerRequest.lowPowerMode = state.batterySaverEnabled;
+ displayPowerRequest.screenLowPowerBrightnessFactor = state.brightnessFactor;
+ }
+
void setStayOnSettingInternal(int val) {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.STAY_ON_WHILE_PLUGGED_IN, val);
@@ -3245,6 +3278,8 @@
pw.println();
pw.println("Display Power: " + mDisplayPowerCallbacks);
+ mBatterySaverPolicy.dump(pw);
+
wcd = mWirelessChargerDetector;
}
@@ -4201,6 +4236,19 @@
}
}
+ // Binder call
+ public PowerSaveState getPowerSaveState(@ServiceType int serviceType) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ return mBatterySaverPolicy.getBatterySaverPolicy(
+ serviceType, isLowPowerModeInternal());
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
@Override // Binder call
public boolean setPowerSaveMode(boolean mode) {
mContext.enforceCallingOrSelfPermission(
@@ -4519,9 +4567,9 @@
}
@Override
- public boolean getLowPowerModeEnabled() {
+ public PowerSaveState getLowPowerState(@ServiceType int serviceType) {
synchronized (mLock) {
- return mLowPowerModeEnabled;
+ return mBatterySaverPolicy.getBatterySaverPolicy(serviceType, mLowPowerModeEnabled);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8b62236..8b859d1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -129,6 +129,7 @@
import android.hardware.display.DisplayManagerInternal;
import android.hardware.input.InputManager;
import android.net.Uri;
+import android.os.PowerSaveState;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -219,6 +220,7 @@
import com.android.server.UiThread;
import com.android.server.Watchdog;
import com.android.server.input.InputManagerService;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
import com.android.server.power.ShutdownThread;
import java.io.BufferedWriter;
@@ -1009,15 +1011,26 @@
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
if (mPowerManagerInternal != null) {
- mPowerManagerInternal.registerLowPowerModeObserver((enabled) -> {
- synchronized (mWindowMap) {
- if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
- mAnimationsDisabled = enabled;
- dispatchNewAnimatorScaleLocked(null);
+ mPowerManagerInternal.registerLowPowerModeObserver(
+ new PowerManagerInternal.LowPowerModeListener() {
+ @Override
+ public int getServiceType() {
+ return ServiceType.ANIMATION;
+ }
+
+ @Override
+ public void onLowPowerModeChanged(PowerSaveState result) {
+ synchronized (mWindowMap) {
+ final boolean enabled = result.batterySaverEnabled;
+ if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
+ mAnimationsDisabled = enabled;
+ dispatchNewAnimatorScaleLocked(null);
+ }
}
}
});
- mAnimationsDisabled = mPowerManagerInternal.getLowPowerModeEnabled();
+ mAnimationsDisabled = mPowerManagerInternal
+ .getLowPowerState(ServiceType.ANIMATION).batterySaverEnabled;
}
mScreenFrozenLock = mPowerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 36ae94b..78d8b53 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -1175,7 +1175,7 @@
}
sp<IGnssNiCallback> gnssNiCbIface = new GnssNiCallback();
- if (gnssNiCbIface != nullptr) {
+ if (gnssNiIface != nullptr) {
gnssNiIface->setCallback(gnssNiCbIface);
} else {
ALOGE("Unable to initialize GNSS NI interface\n");
diff --git a/services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java b/services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java
new file mode 100644
index 0000000..7282b3e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.power;
+
+import android.os.PowerSaveState;
+import android.os.Handler;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import static com.google.common.truth.Truth.assertThat;
+
+/**
+ * Tests for {@link com.android.server.power.BatterySaverPolicy}
+ */
+public class BatterySaverPolicyTest extends AndroidTestCase {
+ private static final boolean BATTERY_SAVER_ON = true;
+ private static final boolean BATTERY_SAVER_OFF = false;
+ private static final float BRIGHTNESS_FACTOR = 0.7f;
+ private static final float DEFAULT_BRIGHTNESS_FACTOR = 0.5f;
+ private static final float PRECISION = 0.001f;
+ private static final int GPS_MODE = 0;
+ private static final int DEFAULT_GPS_MODE = 1;
+ private static final String BATTERY_SAVER_CONSTANTS = "vibration_disabled=true,"
+ + "animation_disabled=false,"
+ + "soundtrigger_disabled=true,"
+ + "firewall_disabled=false,"
+ + "adjust_brightness_disabled=true,"
+ + "adjust_brightness_factor=0.7,"
+ + "fullbackup_deferred=true,"
+ + "keyvaluebackup_deferred=false,"
+ + "gps_mode=0";
+ private static final String BATTERY_SAVER_INCORRECT_CONSTANTS = "vi*,!=,,true";
+
+ @Mock
+ Handler mHandler;
+ private BatterySaverPolicy mBatterySaverPolicy;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ MockitoAnnotations.initMocks(this);
+ mBatterySaverPolicy = new BatterySaverPolicy(mHandler);
+ mBatterySaverPolicy.start(getContext().getContentResolver());
+ }
+
+ @SmallTest
+ public void testGetBatterySaverPolicy_PolicyNull_DefaultValueCorrect() {
+ testServiceDefaultValue(ServiceType.NULL);
+ }
+
+ @SmallTest
+ public void testGetBatterySaverPolicy_PolicyVibration_DefaultValueCorrect() {
+ testServiceDefaultValue(ServiceType.VIBRATION);
+ }
+
+ @SmallTest
+ public void testGetBatterySaverPolicy_PolicySound_DefaultValueCorrect() {
+ testServiceDefaultValue(ServiceType.SOUND);
+ }
+
+ @SmallTest
+ public void testGetBatterySaverPolicy_PolicyFullBackup_DefaultValueCorrect() {
+ testServiceDefaultValue(ServiceType.FULL_BACKUP);
+ }
+
+ @SmallTest
+ public void testGetBatterySaverPolicy_PolicyKeyValueBackup_DefaultValueCorrect() {
+ testServiceDefaultValue(ServiceType.KEYVALUE_BACKUP);
+ }
+
+ @SmallTest
+ public void testGetBatterySaverPolicy_PolicyAnimation_DefaultValueCorrect() {
+ testServiceDefaultValue(ServiceType.ANIMATION);
+ }
+
+ @SmallTest
+ public void testGetBatterySaverPolicy_PolicyBatteryStats_DefaultValueCorrect() {
+ testServiceDefaultValue(ServiceType.BATTERY_STATS);
+ }
+
+ @SmallTest
+ public void testGetBatterySaverPolicy_PolicyNetworkFirewall_DefaultValueCorrect() {
+ testServiceDefaultValue(ServiceType.NETWORK_FIREWALL);
+ }
+
+ @SmallTest
+ public void testGetBatterySaverPolicy_PolicyScreenBrightness_DefaultValueCorrect() {
+ testServiceDefaultValue(ServiceType.SCREEN_BRIGHTNESS);
+
+ PowerSaveState stateOn =
+ mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS, true);
+ assertThat(stateOn.brightnessFactor).isWithin(PRECISION).of(DEFAULT_BRIGHTNESS_FACTOR);
+ }
+
+ @SmallTest
+ public void testGetBatterySaverPolicy_PolicyGps_DefaultValueCorrect() {
+ testServiceDefaultValue(ServiceType.GPS);
+
+ PowerSaveState stateOn =
+ mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.GPS, true);
+ assertThat(stateOn.gpsMode).isEqualTo(DEFAULT_GPS_MODE);
+ }
+
+ @SmallTest
+ public void testUpdateConstants_getCorrectData() {
+ mBatterySaverPolicy.updateConstants(BATTERY_SAVER_CONSTANTS);
+
+ final PowerSaveState vibrationState =
+ mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.VIBRATION, BATTERY_SAVER_ON);
+ assertThat(vibrationState.batterySaverEnabled).isTrue();
+
+ final PowerSaveState animationState =
+ mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.ANIMATION, BATTERY_SAVER_ON);
+ assertThat(animationState.batterySaverEnabled).isFalse();
+
+ final PowerSaveState soundState =
+ mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SOUND, BATTERY_SAVER_ON);
+ assertThat(soundState.batterySaverEnabled).isTrue();
+
+ final PowerSaveState networkState = mBatterySaverPolicy.getBatterySaverPolicy(
+ ServiceType.NETWORK_FIREWALL, BATTERY_SAVER_ON);
+ assertThat(networkState.batterySaverEnabled).isTrue();
+
+ final PowerSaveState screenState =
+ mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS, BATTERY_SAVER_ON);
+ assertThat(screenState.batterySaverEnabled).isFalse();
+ assertThat(screenState.brightnessFactor).isWithin(PRECISION).of(BRIGHTNESS_FACTOR);
+
+ final PowerSaveState fullBackupState = mBatterySaverPolicy.getBatterySaverPolicy(
+ ServiceType.FULL_BACKUP, BATTERY_SAVER_ON);
+ assertThat(fullBackupState.batterySaverEnabled).isTrue();
+
+ final PowerSaveState keyValueBackupState = mBatterySaverPolicy.getBatterySaverPolicy(
+ ServiceType.KEYVALUE_BACKUP, BATTERY_SAVER_ON);
+ assertThat(keyValueBackupState.batterySaverEnabled).isFalse();
+
+ final PowerSaveState gpsState =
+ mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.GPS, BATTERY_SAVER_ON);
+ assertThat(gpsState.batterySaverEnabled).isTrue();
+ assertThat(gpsState.gpsMode).isEqualTo(GPS_MODE);
+ }
+
+ @SmallTest
+ public void testUpdateConstants_IncorrectData_NotCrash() {
+ //Should not crash
+ mBatterySaverPolicy.updateConstants(BATTERY_SAVER_INCORRECT_CONSTANTS);
+ mBatterySaverPolicy.updateConstants(null);
+ }
+
+ private void testServiceDefaultValue(@ServiceType int type) {
+ mBatterySaverPolicy.updateConstants("");
+ final PowerSaveState batterySaverStateOn =
+ mBatterySaverPolicy.getBatterySaverPolicy(type, BATTERY_SAVER_ON);
+ assertThat(batterySaverStateOn.batterySaverEnabled).isTrue();
+
+ final PowerSaveState batterySaverStateOff =
+ mBatterySaverPolicy.getBatterySaverPolicy(type, BATTERY_SAVER_OFF);
+ assertThat(batterySaverStateOff.batterySaverEnabled).isFalse();
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
new file mode 100644
index 0000000..967b0a4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power;
+
+import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
+import android.os.PowerSaveState;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for {@link com.android.server.power.PowerManagerService}
+ */
+public class PowerManagerServiceTest extends AndroidTestCase {
+ private static final float PRECISION = 0.001f;
+ private static final float BRIGHTNESS_FACTOR = 0.7f;
+ private static final boolean BATTERY_SAVER_ENABLED = true;
+
+ private @Mock BatterySaverPolicy mBatterySaverPolicy;
+ private PowerManagerService mService;
+ private PowerSaveState mPowerSaveState;
+ private DisplayPowerRequest mDisplayPowerRequest;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ MockitoAnnotations.initMocks(this);
+
+ mPowerSaveState = new PowerSaveState.Builder()
+ .setBatterySaverEnabled(BATTERY_SAVER_ENABLED)
+ .setBrightnessFactor(BRIGHTNESS_FACTOR)
+ .build();
+ when(mBatterySaverPolicy.getBatterySaverPolicy(
+ eq(BatterySaverPolicy.ServiceType.SCREEN_BRIGHTNESS), anyBoolean()))
+ .thenReturn(mPowerSaveState);
+ mDisplayPowerRequest = new DisplayPowerRequest();
+ mService = new PowerManagerService(getContext(), mBatterySaverPolicy);
+ }
+
+ @SmallTest
+ public void testUpdatePowerScreenPolicy_UpdateDisplayPowerRequest() {
+ mService.updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);
+ assertThat(mDisplayPowerRequest.lowPowerMode).isEqualTo(BATTERY_SAVER_ENABLED);
+ assertThat(mDisplayPowerRequest.screenLowPowerBrightnessFactor)
+ .isWithin(PRECISION).of(BRIGHTNESS_FACTOR);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index dd45d9b..c8b73f1 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -17,9 +17,13 @@
package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer;
+
+import android.os.PowerSaveState;
import org.mockito.invocation.InvocationOnMock;
import android.annotation.Nullable;
@@ -67,6 +71,10 @@
if (LocalServices.getService(PowerManagerInternal.class) == null) {
LocalServices.addService(PowerManagerInternal.class,
mock(PowerManagerInternal.class));
+ final PowerManagerInternal pm =
+ LocalServices.getService(PowerManagerInternal.class);
+ PowerSaveState state = new PowerSaveState.Builder().build();
+ doReturn(state).when(pm).getLowPowerState(anyInt());
}
if (LocalServices.getService(ActivityManagerInternal.class) == null) {
LocalServices.addService(ActivityManagerInternal.class,
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 058de05..40bdaa5 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -497,6 +497,7 @@
//
// Devices List
//
+/*
public ArrayList<UsbAudioDevice> getConnectedDevices() {
ArrayList<UsbAudioDevice> devices = new ArrayList<UsbAudioDevice>(mAudioDevices.size());
for (HashMap.Entry<UsbDevice,UsbAudioDevice> entry : mAudioDevices.entrySet()) {
@@ -504,6 +505,7 @@
}
return devices;
}
+*/
//
// Logging
@@ -519,6 +521,7 @@
}
}
+/*
public void logDevicesList(String title) {
if (DEBUG) {
for (HashMap.Entry<UsbDevice,UsbAudioDevice> entry : mAudioDevices.entrySet()) {
@@ -528,15 +531,19 @@
Slog.i(TAG, "" + entry.getValue());
}
}
- }
+ }
+*/
- // This logs a more terse (and more readable) version of the devices list
- public void logDevices(String title) {
+ // This logs a more terse (and more readable) version of the devices list
+/*
+ public void logDevices(String title) {
if (DEBUG) {
Slog.i(TAG, title);
for (HashMap.Entry<UsbDevice,UsbAudioDevice> entry : mAudioDevices.entrySet()) {
Slog.i(TAG, entry.getValue().toShortString());
}
}
- }
+ }
+*/
+
}
diff --git a/services/usb/java/com/android/server/usb/UsbAudioDevice.java b/services/usb/java/com/android/server/usb/UsbAudioDevice.java
index bdd28e4..70d1fc6 100644
--- a/services/usb/java/com/android/server/usb/UsbAudioDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbAudioDevice.java
@@ -20,10 +20,10 @@
private static final String TAG = "UsbAudioDevice";
protected static final boolean DEBUG = false;
- public int mCard;
- public int mDevice;
- public boolean mHasPlayback;
- public boolean mHasCapture;
+ public final int mCard;
+ public final int mDevice;
+ public final boolean mHasPlayback;
+ public final boolean mHasCapture;
// Device "class" flags
public static final int kAudioDeviceClassMask = 0x00FFFFFF;
@@ -34,7 +34,7 @@
public static final int kAudioDeviceMetaMask = 0xFF000000;
public static final int kAudioDeviceMeta_Alsa = 0x80000000;
// This member is a combination of the above bit-flags
- public int mDeviceClass;
+ public final int mDeviceClass;
public String mDeviceName = "";
public String mDeviceDescription = "";
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index b1df0af..a17676a 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -749,7 +749,7 @@
mMidiCard = scanner.nextInt();
mMidiDevice = scanner.nextInt();
} catch (FileNotFoundException e) {
- Slog.e(TAG, "could not open MIDI PCM file", e);
+ Slog.e(TAG, "could not open MIDI file", e);
enabled = false;
} finally {
if (scanner != null) {
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index e89585c..ca37631 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -16,8 +16,6 @@
package com.android.server.soundtrigger;
-import static android.hardware.soundtrigger.SoundTrigger.STATUS_ERROR;
-
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -42,6 +40,7 @@
import android.telephony.TelephonyManager;
import android.util.Slog;
import com.android.internal.logging.MetricsLogger;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -841,7 +840,8 @@
if (!PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(intent.getAction())) {
return;
}
- boolean active = mPowerManager.isPowerSaveMode();
+ boolean active = mPowerManager.getPowerSaveState(ServiceType.SOUND)
+ .batterySaverEnabled;
if (DBG) Slog.d(TAG, "onPowerSaveModeChanged: " + active);
synchronized (mLock) {
onPowerSaveModeChangedLocked(active);
@@ -874,7 +874,8 @@
mContext.registerReceiver(mPowerSaveModeListener,
new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
}
- mIsPowerSaveMode = mPowerManager.isPowerSaveMode();
+ mIsPowerSaveMode = mPowerManager.getPowerSaveState(ServiceType.SOUND)
+ .batterySaverEnabled;
}
// Sends an error callback to all models with a valid registered callback.
diff --git a/telephony/java/android/telephony/ims/ImsServiceBase.java b/telephony/java/android/telephony/ims/ImsServiceBase.java
index 0878db8..bb36862 100644
--- a/telephony/java/android/telephony/ims/ImsServiceBase.java
+++ b/telephony/java/android/telephony/ims/ImsServiceBase.java
@@ -19,6 +19,7 @@
import android.annotation.SystemApi;
import android.app.Service;
import android.content.Intent;
+import android.os.Binder;
import android.os.IBinder;
/**
@@ -30,8 +31,15 @@
@SystemApi
public class ImsServiceBase extends Service {
+ /**
+ * Binder connection that does nothing but keep the connection between this Service and the
+ * framework active. If this service crashes, the framework will be notified.
+ */
+ private IBinder mConnection = new Binder();
+
@Override
public IBinder onBind(Intent intent) {
- return null;
+ return mConnection;
}
+
}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PathDestructionActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PathDestructionActivity.java
index 4177725..5cede65 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/PathDestructionActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PathDestructionActivity.java
@@ -25,6 +25,8 @@
import android.util.MathUtils;
import android.view.View;
+import java.util.Random;
+
/**
* The point of this test is to ensure that we can cause many paths to be created, drawn,
* and destroyed without causing hangs or crashes. This tests the native reference counting
@@ -57,10 +59,11 @@
private Path getRandomPath() {
float left, top, right, bottom;
- left = MathUtils.random(getWidth() - MIN_SIZE);
- top = MathUtils.random(getHeight() - MIN_SIZE);
- right = left + MathUtils.random(getWidth() - left);
- bottom = top + MathUtils.random(getHeight() - top);
+ Random r = new Random();
+ left = r.nextFloat() * (getWidth() - MIN_SIZE);
+ top = r.nextFloat() * (getHeight() - MIN_SIZE);
+ right = left + r.nextFloat() * (getWidth() - left);
+ bottom = top + r.nextFloat() * (getHeight() - top);
Path path = new Path();
path.moveTo(left, top);
path.lineTo(right, top);
@@ -71,9 +74,10 @@
}
private int getRandomColor() {
- int red = MathUtils.random(255);
- int green = MathUtils.random(255);
- int blue = MathUtils.random(255);
+ Random r = new Random();
+ int red = r.nextInt(255);
+ int green = r.nextInt(255);
+ int blue = r.nextInt(255);
return 0xff000000 | red << 16 | green << 8 | blue;
}
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
index 415911e..11105d6 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
@@ -43,6 +43,7 @@
import java.util.Arrays;
import junit.framework.TestCase;
+// TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
public class IpConnectivityEventBuilderTest extends TestCase {
@SmallTest
@@ -58,8 +59,11 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " if_name: \"\"",
" link_layer: 0",
+ " network_id: 0",
" time_ms: 1",
+ " transports: 0",
" default_network_event <",
" network_id <",
" network_id: 102",
@@ -89,8 +93,11 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " if_name: \"\"",
" link_layer: 0",
+ " network_id: 0",
" time_ms: 1",
+ " transports: 0",
" dhcp_event <",
" duration_ms: 192",
" if_name: \"wlan0\"",
@@ -112,8 +119,11 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " if_name: \"\"",
" link_layer: 0",
+ " network_id: 0",
" time_ms: 1",
+ " transports: 0",
" dhcp_event <",
" duration_ms: 0",
" if_name: \"wlan0\"",
@@ -137,8 +147,11 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " if_name: \"\"",
" link_layer: 0",
+ " network_id: 0",
" time_ms: 1",
+ " transports: 0",
" dns_lookup_batch <",
" event_types: 1",
" event_types: 1",
@@ -185,8 +198,11 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " if_name: \"\"",
" link_layer: 0",
+ " network_id: 0",
" time_ms: 1",
+ " transports: 0",
" ip_provisioning_event <",
" event_type: 1",
" if_name: \"wlan0\"",
@@ -208,8 +224,11 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " if_name: \"\"",
" link_layer: 0",
+ " network_id: 0",
" time_ms: 1",
+ " transports: 0",
" ip_reachability_event <",
" event_type: 512",
" if_name: \"wlan0\"",
@@ -231,8 +250,11 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " if_name: \"\"",
" link_layer: 0",
+ " network_id: 0",
" time_ms: 1",
+ " transports: 0",
" network_event <",
" event_type: 5",
" latency_ms: 20410",
@@ -258,8 +280,11 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " if_name: \"\"",
" link_layer: 0",
+ " network_id: 0",
" time_ms: 1",
+ " transports: 0",
" validation_probe_event <",
" latency_ms: 40730",
" network_id <",
@@ -287,11 +312,15 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " if_name: \"\"",
" link_layer: 0",
+ " network_id: 0",
" time_ms: 1",
+ " transports: 0",
" apf_program_event <",
" current_ras: 9",
" drop_multicast: true",
+ " effective_lifetime: 0",
" filtered_ras: 7",
" has_ipv4_addr: true",
" lifetime: 200",
@@ -319,8 +348,11 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " if_name: \"\"",
" link_layer: 0",
+ " network_id: 0",
" time_ms: 1",
+ " transports: 0",
" apf_statistics <",
" dropped_ras: 2",
" duration_ms: 45000",
@@ -328,6 +360,8 @@
" max_program_size: 2048",
" parse_errors: 2",
" program_updates: 4",
+ " program_updates_all: 0",
+ " program_updates_allowing_multicast: 0",
" received_ras: 10",
" zero_lifetime_ras: 1",
" >",
@@ -351,8 +385,11 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " if_name: \"\"",
" link_layer: 0",
+ " network_id: 0",
" time_ms: 1",
+ " transports: 0",
" ra_event <",
" dnssl_lifetime: -1",
" prefix_preferred_lifetime: 300",
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index f56f3f8..1f7c5f4 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -139,6 +139,7 @@
@SmallTest
public void testEndToEndLogging() {
+ // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
Parcelable[] events = {
@@ -158,16 +159,22 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " if_name: \"\"",
" link_layer: 0",
+ " network_id: 0",
" time_ms: 100",
+ " transports: 0",
" ip_reachability_event <",
" event_type: 512",
" if_name: \"wlan0\"",
" >",
">",
"events <",
+ " if_name: \"\"",
" link_layer: 0",
+ " network_id: 0",
" time_ms: 200",
+ " transports: 0",
" dhcp_event <",
" duration_ms: 192",
" if_name: \"wlan0\"",
@@ -175,8 +182,11 @@
" >",
">",
"events <",
+ " if_name: \"\"",
" link_layer: 0",
+ " network_id: 0",
" time_ms: 300",
+ " transports: 0",
" default_network_event <",
" network_id <",
" network_id: 102",
@@ -191,8 +201,11 @@
" >",
">",
"events <",
+ " if_name: \"\"",
" link_layer: 0",
+ " network_id: 0",
" time_ms: 400",
+ " transports: 0",
" ip_provisioning_event <",
" event_type: 1",
" if_name: \"wlan0\"",
@@ -200,8 +213,11 @@
" >",
">",
"events <",
+ " if_name: \"\"",
" link_layer: 0",
+ " network_id: 0",
" time_ms: 500",
+ " transports: 0",
" validation_probe_event <",
" latency_ms: 40730",
" network_id <",
@@ -212,8 +228,11 @@
" >",
">",
"events <",
+ " if_name: \"\"",
" link_layer: 0",
+ " network_id: 0",
" time_ms: 600",
+ " transports: 0",
" apf_statistics <",
" dropped_ras: 2",
" duration_ms: 45000",
@@ -221,13 +240,18 @@
" max_program_size: 2048",
" parse_errors: 2",
" program_updates: 4",
+ " program_updates_all: 0",
+ " program_updates_allowing_multicast: 0",
" received_ras: 10",
" zero_lifetime_ras: 1",
" >",
">",
"events <",
+ " if_name: \"\"",
" link_layer: 0",
+ " network_id: 0",
" time_ms: 700",
+ " transports: 0",
" ra_event <",
" dnssl_lifetime: -1",
" prefix_preferred_lifetime: 300",
diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
index cfd5598..637eaa3 100644
--- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -213,9 +213,13 @@
IpConnectivityEvent got = events.get(0);
String want = String.join("\n",
+ "if_name: \"\"",
"link_layer: 0",
+ "network_id: 0",
"time_ms: 0",
+ "transports: 0",
"connect_statistics <",
+ " connect_blocking_count: 0",
" connect_count: 12",
" errnos_counters <",
" key: 1",
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index ff306ce..60f0d56 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -4764,6 +4764,7 @@
const sp<XMLNode>& root) {
const String16 vector16("vector");
const String16 animatedVector16("animated-vector");
+ const String16 pathInterpolator16("pathInterpolator");
const int minSdk = getMinSdkVersion(bundle);
if (minSdk >= SDK_LOLLIPOP_MR1) {
@@ -4789,7 +4790,8 @@
nodesToVisit.pop();
if (bundle->getNoVersionVectors() && (node->getElementName() == vector16 ||
- node->getElementName() == animatedVector16)) {
+ node->getElementName() == animatedVector16 ||
+ node->getElementName() == pathInterpolator16)) {
// We were told not to version vector tags, so skip the children here.
continue;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index 9f73d79..339019d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -18,6 +18,7 @@
import android.os.IBinder;
import android.os.IPowerManager;
+import android.os.PowerSaveState;
import android.os.RemoteException;
import android.os.WorkSource;
@@ -42,6 +43,10 @@
return false;
}
+ public PowerSaveState getPowerSaveState(int serviceType) {
+ return null;
+ }
+
@Override
public IBinder asBinder() {
// pass for now.