Merge "Allow the support library to add its own droiddoc options"
diff --git a/api/current.txt b/api/current.txt
index 2644372..2276012 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5415,6 +5415,7 @@
ctor public Notification.MessagingStyle.Message(java.lang.CharSequence, long, java.lang.CharSequence);
method public java.lang.String getDataMimeType();
method public android.net.Uri getDataUri();
+ method public android.os.Bundle getExtras();
method public java.lang.CharSequence getSender();
method public java.lang.CharSequence getText();
method public long getTimestamp();
@@ -5548,12 +5549,14 @@
method public void createNotificationChannelGroups(java.util.List<android.app.NotificationChannelGroup>);
method public void createNotificationChannels(java.util.List<android.app.NotificationChannel>);
method public void deleteNotificationChannel(java.lang.String);
+ method public void deleteNotificationChannelGroup(java.lang.String);
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
method public java.util.Map<java.lang.String, android.app.AutomaticZenRule> getAutomaticZenRules();
method public final int getCurrentInterruptionFilter();
method public int getImportance();
method public android.app.NotificationChannel getNotificationChannel(java.lang.String);
+ method public java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups();
method public java.util.List<android.app.NotificationChannel> getNotificationChannels();
method public android.app.NotificationManager.Policy getNotificationPolicy();
method public boolean isNotificationPolicyAccessGranted();
@@ -5715,6 +5718,8 @@
method public java.lang.CharSequence getContentDescription();
method public android.graphics.drawable.Icon getIcon();
method public java.lang.CharSequence getTitle();
+ method public boolean isEnabled();
+ method public void setEnabled(boolean);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.RemoteAction> CREATOR;
}
@@ -7120,6 +7125,7 @@
method public android.bluetooth.le.BluetoothLeScanner getBluetoothLeScanner();
method public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
+ method public int getLeMaximumAdvertisingDataLength();
method public java.lang.String getName();
method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
method public int getProfileConnectionState(int);
@@ -10670,6 +10676,7 @@
field public static final java.lang.String FEATURE_USB_ACCESSORY = "android.hardware.usb.accessory";
field public static final java.lang.String FEATURE_USB_HOST = "android.hardware.usb.host";
field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
+ field public static final java.lang.String FEATURE_VR_HEADTRACKING = "android.hardware.vr.headtracking";
field public static final java.lang.String FEATURE_VR_MODE = "android.software.vr.mode";
field public static final java.lang.String FEATURE_VR_MODE_HIGH_PERFORMANCE = "android.hardware.vr.high_performance";
field public static final java.lang.String FEATURE_VULKAN_HARDWARE_COMPUTE = "android.hardware.vulkan.compute";
@@ -12755,7 +12762,7 @@
}
public class ColorFilter {
- ctor public ColorFilter();
+ ctor public deprecated ColorFilter();
}
public class ColorMatrix {
@@ -12779,6 +12786,9 @@
public class ColorMatrixColorFilter extends android.graphics.ColorFilter {
ctor public ColorMatrixColorFilter(android.graphics.ColorMatrix);
ctor public ColorMatrixColorFilter(float[]);
+ method public void getColorMatrix(android.graphics.ColorMatrix);
+ method public void setColorMatrix(android.graphics.ColorMatrix);
+ method public void setColorMatrixArray(float[]);
}
public abstract class ColorSpace {
@@ -13002,6 +13012,10 @@
public class LightingColorFilter extends android.graphics.ColorFilter {
ctor public LightingColorFilter(int, int);
+ method public int getColorAdd();
+ method public int getColorMultiply();
+ method public void setColorAdd(int);
+ method public void setColorMultiply(int);
}
public class LinearGradient extends android.graphics.Shader {
@@ -13518,6 +13532,10 @@
public class PorterDuffColorFilter extends android.graphics.ColorFilter {
ctor public PorterDuffColorFilter(int, android.graphics.PorterDuff.Mode);
+ method public int getColor();
+ method public android.graphics.PorterDuff.Mode getMode();
+ method public void setColor(int);
+ method public void setMode(android.graphics.PorterDuff.Mode);
}
public class PorterDuffXfermode extends android.graphics.Xfermode {
@@ -37155,11 +37173,11 @@
field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
field public static final int REASON_APP_CANCEL = 8; // 0x8
field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
+ field public static final int REASON_CANCEL = 2; // 0x2
+ field public static final int REASON_CANCEL_ALL = 3; // 0x3
field public static final int REASON_CHANNEL_BANNED = 17; // 0x11
- field public static final int REASON_DELEGATE_CANCEL = 2; // 0x2
- field public static final int REASON_DELEGATE_CANCEL_ALL = 3; // 0x3
- field public static final int REASON_DELEGATE_CLICK = 1; // 0x1
- field public static final int REASON_DELEGATE_ERROR = 4; // 0x4
+ field public static final int REASON_CLICK = 1; // 0x1
+ field public static final int REASON_ERROR = 4; // 0x4
field public static final int REASON_GROUP_OPTIMIZATION = 13; // 0xd
field public static final int REASON_GROUP_SUMMARY_CANCELED = 12; // 0xc
field public static final int REASON_LISTENER_CANCEL = 10; // 0xa
@@ -45073,8 +45091,8 @@
method public void addTouchables(java.util.ArrayList<android.view.View>);
method public android.view.ViewPropertyAnimator animate();
method public void announceForAccessibility(java.lang.CharSequence);
- method public void autofill(android.view.autofill.AutofillValue);
- method public void autofillVirtual(int, android.view.autofill.AutofillValue);
+ method public boolean autofill(android.view.autofill.AutofillValue);
+ method public boolean autofill(int, android.view.autofill.AutofillValue);
method protected boolean awakenScrollBars();
method protected boolean awakenScrollBars(int);
method protected boolean awakenScrollBars(int, boolean);
@@ -46289,7 +46307,7 @@
method public abstract int addChildCount(int);
method public abstract void asyncCommit();
method public abstract android.view.ViewStructure asyncNewChild(int);
- method public abstract android.view.ViewStructure asyncNewChildForAutofill(int, int, int);
+ method public abstract android.view.ViewStructure asyncNewChild(int, int, int);
method public abstract int getChildCount();
method public abstract android.os.Bundle getExtras();
method public abstract java.lang.CharSequence getHint();
@@ -46298,7 +46316,7 @@
method public abstract int getTextSelectionStart();
method public abstract boolean hasExtras();
method public abstract android.view.ViewStructure newChild(int);
- method public abstract android.view.ViewStructure newChildForAutofill(int, int, int);
+ method public abstract android.view.ViewStructure newChild(int, int, int);
method public abstract void setAccessibilityFocused(boolean);
method public abstract void setActivated(boolean);
method public abstract void setAlpha(float);
@@ -47570,11 +47588,11 @@
method public void commit();
method public boolean isEnabled();
method public void notifyValueChanged(android.view.View);
+ method public void notifyValueChanged(android.view.View, int, android.view.autofill.AutofillValue);
method public void notifyViewEntered(android.view.View);
+ method public void notifyViewEntered(android.view.View, int, android.graphics.Rect);
method public void notifyViewExited(android.view.View);
- method public void notifyVirtualValueChanged(android.view.View, int, android.view.autofill.AutofillValue);
- method public void notifyVirtualViewEntered(android.view.View, int, android.graphics.Rect);
- method public void notifyVirtualViewExited(android.view.View, int);
+ method public void notifyViewExited(android.view.View, int);
method public void registerCallback(android.view.autofill.AutofillManager.AutofillCallback);
method public void requestAutofill(android.view.View);
method public void requestAutofill(android.view.View, int, android.graphics.Rect);
@@ -47587,9 +47605,10 @@
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);
+ method public void onAutofillEvent(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
+ field public static final int EVENT_INPUT_UNAVAILABLE = 3; // 0x3
}
public final class AutofillValue implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index eb5ebd7..ae510c9 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5589,6 +5589,7 @@
ctor public Notification.MessagingStyle.Message(java.lang.CharSequence, long, java.lang.CharSequence);
method public java.lang.String getDataMimeType();
method public android.net.Uri getDataUri();
+ method public android.os.Bundle getExtras();
method public java.lang.CharSequence getSender();
method public java.lang.CharSequence getText();
method public long getTimestamp();
@@ -5751,12 +5752,14 @@
method public void createNotificationChannelGroups(java.util.List<android.app.NotificationChannelGroup>);
method public void createNotificationChannels(java.util.List<android.app.NotificationChannel>);
method public void deleteNotificationChannel(java.lang.String);
+ method public void deleteNotificationChannelGroup(java.lang.String);
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
method public java.util.Map<java.lang.String, android.app.AutomaticZenRule> getAutomaticZenRules();
method public final int getCurrentInterruptionFilter();
method public int getImportance();
method public android.app.NotificationChannel getNotificationChannel(java.lang.String);
+ method public java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups();
method public java.util.List<android.app.NotificationChannel> getNotificationChannels();
method public android.app.NotificationManager.Policy getNotificationPolicy();
method public boolean isNotificationPolicyAccessGranted();
@@ -5918,6 +5921,8 @@
method public java.lang.CharSequence getContentDescription();
method public android.graphics.drawable.Icon getIcon();
method public java.lang.CharSequence getTitle();
+ method public boolean isEnabled();
+ method public void setEnabled(boolean);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.RemoteAction> CREATOR;
}
@@ -7589,6 +7594,7 @@
method public android.bluetooth.le.BluetoothLeScanner getBluetoothLeScanner();
method public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
+ method public int getLeMaximumAdvertisingDataLength();
method public java.lang.String getName();
method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
method public int getProfileConnectionState(int);
@@ -11328,6 +11334,7 @@
field public static final java.lang.String FEATURE_USB_ACCESSORY = "android.hardware.usb.accessory";
field public static final java.lang.String FEATURE_USB_HOST = "android.hardware.usb.host";
field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
+ field public static final java.lang.String FEATURE_VR_HEADTRACKING = "android.hardware.vr.headtracking";
field public static final java.lang.String FEATURE_VR_MODE = "android.software.vr.mode";
field public static final java.lang.String FEATURE_VR_MODE_HIGH_PERFORMANCE = "android.hardware.vr.high_performance";
field public static final java.lang.String FEATURE_VULKAN_HARDWARE_COMPUTE = "android.hardware.vulkan.compute";
@@ -13489,7 +13496,7 @@
}
public class ColorFilter {
- ctor public ColorFilter();
+ ctor public deprecated ColorFilter();
}
public class ColorMatrix {
@@ -13513,6 +13520,9 @@
public class ColorMatrixColorFilter extends android.graphics.ColorFilter {
ctor public ColorMatrixColorFilter(android.graphics.ColorMatrix);
ctor public ColorMatrixColorFilter(float[]);
+ method public void getColorMatrix(android.graphics.ColorMatrix);
+ method public void setColorMatrix(android.graphics.ColorMatrix);
+ method public void setColorMatrixArray(float[]);
}
public abstract class ColorSpace {
@@ -13736,6 +13746,10 @@
public class LightingColorFilter extends android.graphics.ColorFilter {
ctor public LightingColorFilter(int, int);
+ method public int getColorAdd();
+ method public int getColorMultiply();
+ method public void setColorAdd(int);
+ method public void setColorMultiply(int);
}
public class LinearGradient extends android.graphics.Shader {
@@ -14252,6 +14266,10 @@
public class PorterDuffColorFilter extends android.graphics.ColorFilter {
ctor public PorterDuffColorFilter(int, android.graphics.PorterDuff.Mode);
+ method public int getColor();
+ method public android.graphics.PorterDuff.Mode getMode();
+ method public void setColor(int);
+ method public void setMode(android.graphics.PorterDuff.Mode);
}
public class PorterDuffXfermode extends android.graphics.Xfermode {
@@ -34415,6 +34433,7 @@
method public deprecated void setUserRestrictions(android.os.Bundle);
method public deprecated void setUserRestrictions(android.os.Bundle, android.os.UserHandle);
method public static boolean supportsMultipleUsers();
+ field public static final java.lang.String ACTION_USER_RESTRICTIONS_CHANGED = "android.os.action.USER_RESTRICTIONS_CHANGED";
field public static final java.lang.String ALLOW_PARENT_PROFILE_APP_LINKING = "allow_parent_profile_app_linking";
field public static final java.lang.String DISALLOW_ADD_MANAGED_PROFILE = "no_add_managed_profile";
field public static final java.lang.String DISALLOW_ADD_USER = "no_add_user";
@@ -40226,11 +40245,11 @@
field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
field public static final int REASON_APP_CANCEL = 8; // 0x8
field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
+ field public static final int REASON_CANCEL = 2; // 0x2
+ field public static final int REASON_CANCEL_ALL = 3; // 0x3
field public static final int REASON_CHANNEL_BANNED = 17; // 0x11
- field public static final int REASON_DELEGATE_CANCEL = 2; // 0x2
- field public static final int REASON_DELEGATE_CANCEL_ALL = 3; // 0x3
- field public static final int REASON_DELEGATE_CLICK = 1; // 0x1
- field public static final int REASON_DELEGATE_ERROR = 4; // 0x4
+ field public static final int REASON_CLICK = 1; // 0x1
+ field public static final int REASON_ERROR = 4; // 0x4
field public static final int REASON_GROUP_OPTIMIZATION = 13; // 0xd
field public static final int REASON_GROUP_SUMMARY_CANCELED = 12; // 0xc
field public static final int REASON_LISTENER_CANCEL = 10; // 0xa
@@ -48536,8 +48555,8 @@
method public void addTouchables(java.util.ArrayList<android.view.View>);
method public android.view.ViewPropertyAnimator animate();
method public void announceForAccessibility(java.lang.CharSequence);
- method public void autofill(android.view.autofill.AutofillValue);
- method public void autofillVirtual(int, android.view.autofill.AutofillValue);
+ method public boolean autofill(android.view.autofill.AutofillValue);
+ method public boolean autofill(int, android.view.autofill.AutofillValue);
method protected boolean awakenScrollBars();
method protected boolean awakenScrollBars(int);
method protected boolean awakenScrollBars(int, boolean);
@@ -49752,7 +49771,7 @@
method public abstract int addChildCount(int);
method public abstract void asyncCommit();
method public abstract android.view.ViewStructure asyncNewChild(int);
- method public abstract android.view.ViewStructure asyncNewChildForAutofill(int, int, int);
+ method public abstract android.view.ViewStructure asyncNewChild(int, int, int);
method public abstract int getChildCount();
method public abstract android.os.Bundle getExtras();
method public abstract java.lang.CharSequence getHint();
@@ -49761,7 +49780,7 @@
method public abstract int getTextSelectionStart();
method public abstract boolean hasExtras();
method public abstract android.view.ViewStructure newChild(int);
- method public abstract android.view.ViewStructure newChildForAutofill(int, int, int);
+ method public abstract android.view.ViewStructure newChild(int, int, int);
method public abstract void setAccessibilityFocused(boolean);
method public abstract void setActivated(boolean);
method public abstract void setAlpha(float);
@@ -51036,11 +51055,11 @@
method public void commit();
method public boolean isEnabled();
method public void notifyValueChanged(android.view.View);
+ method public void notifyValueChanged(android.view.View, int, android.view.autofill.AutofillValue);
method public void notifyViewEntered(android.view.View);
+ method public void notifyViewEntered(android.view.View, int, android.graphics.Rect);
method public void notifyViewExited(android.view.View);
- method public void notifyVirtualValueChanged(android.view.View, int, android.view.autofill.AutofillValue);
- method public void notifyVirtualViewEntered(android.view.View, int, android.graphics.Rect);
- method public void notifyVirtualViewExited(android.view.View, int);
+ method public void notifyViewExited(android.view.View, int);
method public void registerCallback(android.view.autofill.AutofillManager.AutofillCallback);
method public void requestAutofill(android.view.View);
method public void requestAutofill(android.view.View, int, android.graphics.Rect);
@@ -51053,9 +51072,10 @@
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);
+ method public void onAutofillEvent(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
+ field public static final int EVENT_INPUT_UNAVAILABLE = 3; // 0x3
}
public final class AutofillValue implements android.os.Parcelable {
diff --git a/api/test-current.txt b/api/test-current.txt
index 3b02916..ea3e6e2 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5425,6 +5425,7 @@
ctor public Notification.MessagingStyle.Message(java.lang.CharSequence, long, java.lang.CharSequence);
method public java.lang.String getDataMimeType();
method public android.net.Uri getDataUri();
+ method public android.os.Bundle getExtras();
method public java.lang.CharSequence getSender();
method public java.lang.CharSequence getText();
method public long getTimestamp();
@@ -5558,6 +5559,7 @@
method public void createNotificationChannelGroups(java.util.List<android.app.NotificationChannelGroup>);
method public void createNotificationChannels(java.util.List<android.app.NotificationChannel>);
method public void deleteNotificationChannel(java.lang.String);
+ method public void deleteNotificationChannelGroup(java.lang.String);
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
method public java.util.Map<java.lang.String, android.app.AutomaticZenRule> getAutomaticZenRules();
@@ -5565,6 +5567,7 @@
method public android.content.ComponentName getEffectsSuppressor();
method public int getImportance();
method public android.app.NotificationChannel getNotificationChannel(java.lang.String);
+ method public java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups();
method public java.util.List<android.app.NotificationChannel> getNotificationChannels();
method public android.app.NotificationManager.Policy getNotificationPolicy();
method public boolean isNotificationPolicyAccessGranted();
@@ -5726,6 +5729,8 @@
method public java.lang.CharSequence getContentDescription();
method public android.graphics.drawable.Icon getIcon();
method public java.lang.CharSequence getTitle();
+ method public boolean isEnabled();
+ method public void setEnabled(boolean);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.RemoteAction> CREATOR;
}
@@ -7147,6 +7152,7 @@
method public android.bluetooth.le.BluetoothLeScanner getBluetoothLeScanner();
method public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
+ method public int getLeMaximumAdvertisingDataLength();
method public java.lang.String getName();
method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
method public int getProfileConnectionState(int);
@@ -10706,6 +10712,7 @@
field public static final java.lang.String FEATURE_USB_ACCESSORY = "android.hardware.usb.accessory";
field public static final java.lang.String FEATURE_USB_HOST = "android.hardware.usb.host";
field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
+ field public static final java.lang.String FEATURE_VR_HEADTRACKING = "android.hardware.vr.headtracking";
field public static final java.lang.String FEATURE_VR_MODE = "android.software.vr.mode";
field public static final java.lang.String FEATURE_VR_MODE_HIGH_PERFORMANCE = "android.hardware.vr.high_performance";
field public static final java.lang.String FEATURE_VULKAN_HARDWARE_COMPUTE = "android.hardware.vulkan.compute";
@@ -12793,7 +12800,7 @@
}
public class ColorFilter {
- ctor public ColorFilter();
+ ctor public deprecated ColorFilter();
}
public class ColorMatrix {
@@ -12817,6 +12824,9 @@
public class ColorMatrixColorFilter extends android.graphics.ColorFilter {
ctor public ColorMatrixColorFilter(android.graphics.ColorMatrix);
ctor public ColorMatrixColorFilter(float[]);
+ method public void getColorMatrix(android.graphics.ColorMatrix);
+ method public void setColorMatrix(android.graphics.ColorMatrix);
+ method public void setColorMatrixArray(float[]);
}
public abstract class ColorSpace {
@@ -13040,6 +13050,10 @@
public class LightingColorFilter extends android.graphics.ColorFilter {
ctor public LightingColorFilter(int, int);
+ method public int getColorAdd();
+ method public int getColorMultiply();
+ method public void setColorAdd(int);
+ method public void setColorMultiply(int);
}
public class LinearGradient extends android.graphics.Shader {
@@ -13556,6 +13570,10 @@
public class PorterDuffColorFilter extends android.graphics.ColorFilter {
ctor public PorterDuffColorFilter(int, android.graphics.PorterDuff.Mode);
+ method public int getColor();
+ method public android.graphics.PorterDuff.Mode getMode();
+ method public void setColor(int);
+ method public void setMode(android.graphics.PorterDuff.Mode);
}
public class PorterDuffXfermode extends android.graphics.Xfermode {
@@ -31717,6 +31735,7 @@
method public deprecated void setUserRestrictions(android.os.Bundle);
method public deprecated void setUserRestrictions(android.os.Bundle, android.os.UserHandle);
method public static boolean supportsMultipleUsers();
+ field public static final java.lang.String ACTION_USER_RESTRICTIONS_CHANGED = "android.os.action.USER_RESTRICTIONS_CHANGED";
field public static final java.lang.String ALLOW_PARENT_PROFILE_APP_LINKING = "allow_parent_profile_app_linking";
field public static final java.lang.String DISALLOW_ADD_MANAGED_PROFILE = "no_add_managed_profile";
field public static final java.lang.String DISALLOW_ADD_USER = "no_add_user";
@@ -37331,11 +37350,11 @@
field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
field public static final int REASON_APP_CANCEL = 8; // 0x8
field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
+ field public static final int REASON_CANCEL = 2; // 0x2
+ field public static final int REASON_CANCEL_ALL = 3; // 0x3
field public static final int REASON_CHANNEL_BANNED = 17; // 0x11
- field public static final int REASON_DELEGATE_CANCEL = 2; // 0x2
- field public static final int REASON_DELEGATE_CANCEL_ALL = 3; // 0x3
- field public static final int REASON_DELEGATE_CLICK = 1; // 0x1
- field public static final int REASON_DELEGATE_ERROR = 4; // 0x4
+ field public static final int REASON_CLICK = 1; // 0x1
+ field public static final int REASON_ERROR = 4; // 0x4
field public static final int REASON_GROUP_OPTIMIZATION = 13; // 0xd
field public static final int REASON_GROUP_SUMMARY_CANCELED = 12; // 0xc
field public static final int REASON_LISTENER_CANCEL = 10; // 0xa
@@ -45433,8 +45452,8 @@
method public void addTouchables(java.util.ArrayList<android.view.View>);
method public android.view.ViewPropertyAnimator animate();
method public void announceForAccessibility(java.lang.CharSequence);
- method public void autofill(android.view.autofill.AutofillValue);
- method public void autofillVirtual(int, android.view.autofill.AutofillValue);
+ method public boolean autofill(android.view.autofill.AutofillValue);
+ method public boolean autofill(int, android.view.autofill.AutofillValue);
method protected boolean awakenScrollBars();
method protected boolean awakenScrollBars(int);
method protected boolean awakenScrollBars(int, boolean);
@@ -46656,7 +46675,7 @@
method public abstract int addChildCount(int);
method public abstract void asyncCommit();
method public abstract android.view.ViewStructure asyncNewChild(int);
- method public abstract android.view.ViewStructure asyncNewChildForAutofill(int, int, int);
+ method public abstract android.view.ViewStructure asyncNewChild(int, int, int);
method public abstract int getChildCount();
method public abstract android.os.Bundle getExtras();
method public abstract java.lang.CharSequence getHint();
@@ -46665,7 +46684,7 @@
method public abstract int getTextSelectionStart();
method public abstract boolean hasExtras();
method public abstract android.view.ViewStructure newChild(int);
- method public abstract android.view.ViewStructure newChildForAutofill(int, int, int);
+ method public abstract android.view.ViewStructure newChild(int, int, int);
method public abstract void setAccessibilityFocused(boolean);
method public abstract void setActivated(boolean);
method public abstract void setAlpha(float);
@@ -47939,11 +47958,11 @@
method public void commit();
method public boolean isEnabled();
method public void notifyValueChanged(android.view.View);
+ method public void notifyValueChanged(android.view.View, int, android.view.autofill.AutofillValue);
method public void notifyViewEntered(android.view.View);
+ method public void notifyViewEntered(android.view.View, int, android.graphics.Rect);
method public void notifyViewExited(android.view.View);
- method public void notifyVirtualValueChanged(android.view.View, int, android.view.autofill.AutofillValue);
- method public void notifyVirtualViewEntered(android.view.View, int, android.graphics.Rect);
- method public void notifyVirtualViewExited(android.view.View, int);
+ method public void notifyViewExited(android.view.View, int);
method public void registerCallback(android.view.autofill.AutofillManager.AutofillCallback);
method public void requestAutofill(android.view.View);
method public void requestAutofill(android.view.View, int, android.graphics.Rect);
@@ -47956,9 +47975,10 @@
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);
+ method public void onAutofillEvent(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
+ field public static final int EVENT_INPUT_UNAVAILABLE = 3; // 0x3
}
public final class AutofillValue implements android.os.Parcelable {
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index e5df278..75d4f32 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -21,8 +21,11 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
+import android.annotation.SdkConstant;
import android.annotation.Size;
import android.annotation.SystemApi;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.BroadcastBehavior;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -335,6 +338,8 @@
*
* @deprecated use #addOnAccountsUpdatedListener to get account updates in runtime.
*/
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(includeBackground = true)
public static final String LOGIN_ACCOUNTS_CHANGED_ACTION =
"android.accounts.LOGIN_ACCOUNTS_CHANGED";
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 86adbb0..5c7a12c 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -431,31 +431,28 @@
// Force all the animations to end when the duration scale is 0.
private void forceToEnd() {
- if (mEndCanBeCalled) {
- end();
+ // TODO: Below is commented out to temp work around b/36241584, uncomment this when it's
+ // fixed.
+// if (mEndCanBeCalled) {
+// end();
+// return;
+// }
+
+ // Note: we don't want to combine this case with the end() method below because in
+ // the case of developer calling end(), we still need to make sure end() is explicitly
+ // called on the child animators to maintain the old behavior.
+ if (mReversing) {
+ handleAnimationEvents(mLastEventId, 0, getTotalDuration());
} else {
- // Note: we don't want to combine this case with the end() method below because in
- // the case of developer calling end(), we still need to make sure end() is explicitly
- // called on the child animators to maintain the old behavior.
- if (mReversing) {
- mLastEventId = mLastEventId == -1 ? mEvents.size() : mLastEventId;
- for (int j = mLastEventId - 1; j >= 0; j--) {
- AnimationEvent event = mEvents.get(j);
- if (event.mEvent == AnimationEvent.ANIMATION_END) {
- event.mNode.mAnimation.reverse();
- }
- }
- } else {
- for (int j = mLastEventId + 1; j < mEvents.size(); j++) {
- AnimationEvent event = mEvents.get(j);
- if (event.mEvent == AnimationEvent.ANIMATION_START) {
- event.mNode.mAnimation.start();
- }
- }
+ long zeroScalePlayTime = getTotalDuration();
+ if (zeroScalePlayTime == DURATION_INFINITE) {
+ // Use a large number for the play time.
+ zeroScalePlayTime = Integer.MAX_VALUE;
}
- mPlayingSet.clear();
- endAnimation();
+ handleAnimationEvents(mLastEventId, mEvents.size() - 1, zeroScalePlayTime);
}
+ mPlayingSet.clear();
+ endAnimation();
}
/**
@@ -730,7 +727,7 @@
if (isEmptySet) {
// In the case of empty AnimatorSet, or 0 duration scale, we will trigger the
// onAnimationEnd() right away.
- forceToEnd();
+ end();
}
}
@@ -1130,8 +1127,10 @@
*/
private void pulseFrame(Node node, long animPlayTime) {
if (!node.mEnded) {
+ float durationScale = ValueAnimator.getDurationScale();
+ durationScale = durationScale == 0 ? 1 : durationScale;
node.mEnded = node.mAnimation.pulseAnimationFrame(
- (long) (animPlayTime * ValueAnimator.getDurationScale()));
+ (long) (animPlayTime * durationScale));
}
}
diff --git a/core/java/android/annotation/BroadcastBehavior.java b/core/java/android/annotation/BroadcastBehavior.java
new file mode 100644
index 0000000..9b2ca31
--- /dev/null
+++ b/core/java/android/annotation/BroadcastBehavior.java
@@ -0,0 +1,56 @@
+/*
+ * 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 android.annotation;
+
+import android.content.Intent;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Description of how the annotated broadcast action behaves.
+ *
+ * @hide
+ */
+@Target({ ElementType.FIELD })
+@Retention(RetentionPolicy.SOURCE)
+public @interface BroadcastBehavior {
+ /**
+ * This broadcast will only be delivered to an explicit target.
+ *
+ * @see Intent#setPackage(String)
+ * @see Intent#setComponent(android.content.ComponentName)
+ */
+ boolean explicitOnly() default false;
+
+ /**
+ * This broadcast will only be delivered to registered receivers.
+ *
+ * @see Intent#FLAG_RECEIVER_REGISTERED_ONLY
+ */
+ boolean registeredOnly() default false;
+
+ /**
+ * This broadcast will include all {@code AndroidManifest.xml} receivers
+ * regardless of process state.
+ *
+ * @see Intent#FLAG_RECEIVER_INCLUDE_BACKGROUND
+ */
+ boolean includeBackground() default false;
+}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 78c29e8..37a11ec 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -16,6 +16,7 @@
package android.app;
+import android.metrics.LogMaker;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
@@ -23,6 +24,8 @@
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.app.ToolbarActionBar;
import com.android.internal.app.WindowDecorActionBar;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.policy.PhoneWindow;
import android.annotation.CallSuper;
@@ -765,6 +768,7 @@
/*package*/ Configuration mCurrentConfig;
private SearchManager mSearchManager;
private MenuInflater mMenuInflater;
+ private final MetricsLogger mMetricsLogger = new MetricsLogger();
static final class NonConfigurationInstances {
Object activity;
@@ -7188,6 +7192,8 @@
public void autofill(List<AutofillId> ids, List<AutofillValue> values) {
final View root = getWindow().getDecorView();
final int itemCount = ids.size();
+ int numApplied = 0;
+
for (int i = 0; i < itemCount; i++) {
final AutofillId id = ids.get(i);
final AutofillValue value = values.get(i);
@@ -7197,12 +7203,22 @@
Log.w(TAG, "autofill(): no View with id " + viewId);
continue;
}
+ final boolean wasApplied;
if (id.isVirtual()) {
- view.autofillVirtual(id.getVirtualChildId(), value);
+ wasApplied = view.autofill(id.getVirtualChildId(), value);
} else {
- view.autofill(value);
+ wasApplied = view.autofill(value);
+ }
+
+ if (wasApplied) {
+ numApplied++;
}
}
+
+ LogMaker log = new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_DATASET_APPLIED);
+ log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, itemCount);
+ log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VIEWS_FILLED, numApplied);
+ mMetricsLogger.write(log);
}
/** @hide */
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 5cdfb8e..6b53cd8 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -149,6 +149,7 @@
import libcore.io.EventLogger;
import libcore.io.IoUtils;
import libcore.net.event.NetworkEventDispatcher;
+import dalvik.system.BaseDexClassLoader;
import dalvik.system.CloseGuard;
import dalvik.system.VMDebug;
import dalvik.system.VMRuntime;
@@ -336,6 +337,8 @@
Configuration overrideConfig;
// Used for consolidating configs before sending on to Activity.
private Configuration tmpConfig = new Configuration();
+ // Callback used for updating activity override config.
+ ViewRootImpl.ActivityConfigCallback configCallback;
ActivityClientRecord nextIdle;
ProfilerInfo profilerInfo;
@@ -371,6 +374,14 @@
stopped = false;
hideForNow = false;
nextIdle = null;
+ configCallback = (Configuration overrideConfig, int newDisplayId) -> {
+ if (activity == null) {
+ throw new IllegalStateException(
+ "Received config update for non-existing activity");
+ }
+ activity.mMainThread.handleActivityConfigurationChanged(
+ new ActivityConfigChangeData(token, overrideConfig), newDisplayId);
+ };
}
public boolean isPreHoneycomb() {
@@ -3680,6 +3691,12 @@
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
+ final ViewRootImpl viewRoot = r.activity.mDecor.getViewRootImpl();
+ if (viewRoot != null) {
+ // TODO: Figure out the best place to set the callback.
+ // This looks like a place where decor view is already initialized.
+ viewRoot.setActivityConfigCallback(r.configCallback);
+ }
}
if (!r.onlyLocalRequest) {
@@ -5028,7 +5045,7 @@
* @param displayId Id of the display where activity was moved to, -1 if there was no move and
* value didn't change.
*/
- private void handleActivityConfigurationChanged(ActivityConfigChangeData data, int displayId) {
+ void handleActivityConfigurationChanged(ActivityConfigChangeData data, int displayId) {
ActivityClientRecord r = mActivities.get(data.activityToken);
// Check input params.
if (r == null || r.activity == null) {
@@ -5045,6 +5062,7 @@
// Perform updates.
r.overrideConfig = data.overrideConfig;
+ final ViewRootImpl viewRoot = r.activity.mDecor.getViewRootImpl();
if (movedToDifferentDisplay) {
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity moved to display, activity:"
+ r.activityInfo.name + ", displayId=" + displayId
@@ -5052,13 +5070,15 @@
performConfigurationChangedForActivity(r, mCompatConfiguration, displayId,
true /* movedToDifferentDisplay */);
- final ViewRootImpl viewRoot = r.activity.mDecor.getViewRootImpl();
viewRoot.onMovedToDisplay(displayId);
} else {
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
+ r.activityInfo.name + ", config=" + data.overrideConfig);
performConfigurationChangedForActivity(r, mCompatConfiguration);
}
+ // Notify the ViewRootImpl instance about configuration changes. It may have initiated this
+ // update to make sure that resources are updated before updating itself.
+ viewRoot.updateConfiguration();
mSomeActivitiesChanged = true;
}
@@ -5571,6 +5591,16 @@
}
}
+ // If we use profiles, setup the dex reporter to notify package manager
+ // of any relevant dex loads. The idle maintenance job will use the information
+ // reported to optimize the loaded dex files.
+ // Note that we only need one global reporter per app.
+ // Make sure we do this before calling onCreate so that we can capture the
+ // complete application startup.
+ if (SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) {
+ BaseDexClassLoader.setReporter(DexLoadReporter.getInstance());
+ }
+
// Install the Network Security Config Provider. This must happen before the application
// code is loaded to prevent issues with instances of TLS objects being created before
// the provider is installed.
@@ -6284,35 +6314,26 @@
// add dropbox logging to libcore
DropBox.setReporter(new DropBoxReporter());
- ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- synchronized (mResourcesManager) {
- // We need to apply this change to the resources
- // immediately, because upon returning the view
- // hierarchy will be informed about it.
- if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {
- updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
- mResourcesManager.getConfiguration().getLocales());
+ ViewRootImpl.ConfigChangedCallback configChangedCallback
+ = (Configuration globalConfig) -> {
+ synchronized (mResourcesManager) {
+ // We need to apply this change to the resources immediately, because upon returning
+ // the view hierarchy will be informed about it.
+ if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
+ null /* compat */)) {
+ updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
+ mResourcesManager.getConfiguration().getLocales());
- // This actually changed the resources! Tell
- // everyone about it.
- if (mPendingConfiguration == null ||
- mPendingConfiguration.isOtherSeqNewer(newConfig)) {
- mPendingConfiguration = newConfig;
-
- sendMessage(H.CONFIGURATION_CHANGED, newConfig);
- }
+ // This actually changed the resources! Tell everyone about it.
+ if (mPendingConfiguration == null
+ || mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
+ mPendingConfiguration = globalConfig;
+ sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
}
}
}
- @Override
- public void onLowMemory() {
- }
- @Override
- public void onTrimMemory(int level) {
- }
- });
+ };
+ ViewRootImpl.addConfigCallback(configChangedCallback);
}
public static ActivityThread systemMain() {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 0f2ce3c..09e7595 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -362,6 +362,8 @@
public static final String OPSTR_ANSWER_PHONE_CALLS
= "android:answer_phone_calls";
+ // Warning: If an permission is added here it also has to be added to
+ // com.android.packageinstaller.permission.utils.EventLogger
private static final int[] RUNTIME_AND_APPOP_PERMISSIONS_OPS = {
// RUNTIME PERMISSIONS
// Contacts
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index 9f1a539..e645261 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -22,6 +22,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.os.Binder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemProperties;
@@ -430,7 +431,7 @@
dest.writeInt(throwLineNumber);
dest.writeString(stackTrace);
int total = dest.dataPosition()-start;
- if (total > 20*1024) {
+ if (Binder.CHECK_PARCEL_SIZE && total > 20*1024) {
Slog.d("Error", "ERR: exClass=" + exceptionClassName);
Slog.d("Error", "ERR: exMsg=" + exceptionMessage);
Slog.d("Error", "ERR: file=" + throwFileName);
diff --git a/core/java/android/app/DexLoadReporter.java b/core/java/android/app/DexLoadReporter.java
new file mode 100644
index 0000000..13f288a
--- /dev/null
+++ b/core/java/android/app/DexLoadReporter.java
@@ -0,0 +1,168 @@
+/*
+ * 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 android.app;
+
+import android.os.FileUtils;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+import dalvik.system.BaseDexClassLoader;
+import dalvik.system.VMRuntime;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A dex load reporter which will notify package manager of any dex file loaded
+ * with {@code BaseDexClassLoader}.
+ * The goals are:
+ * 1) discover secondary dex files so that they can be optimized during the
+ * idle maintenance job.
+ * 2) determine whether or not a dex file is used by an app which does not
+ * own it (in order to select the optimal compilation method).
+ * @hide
+ */
+/*package*/ class DexLoadReporter implements BaseDexClassLoader.Reporter {
+ private static final String TAG = "DexLoadReporter";
+
+ private static final DexLoadReporter INSTANCE = new DexLoadReporter();
+
+ private static final boolean DEBUG = false;
+
+ // We must guard the access to the list of data directories because
+ // we might have concurrent accesses. Apps might load dex files while
+ // new data dirs are registered (due to creation of LoadedApks via
+ // create createApplicationContext).
+ @GuardedBy("mDataDirs")
+ private final Set<String> mDataDirs;
+
+ private DexLoadReporter() {
+ mDataDirs = new HashSet<>();
+ }
+
+ /*package*/ static DexLoadReporter getInstance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Register an application data directory with the reporter.
+ * The data directories are used to determine if a dex file is secondary dex or not.
+ * Note that this method may be called multiple times for the same app, registering
+ * different data directories. This may happen when apps share the same user id
+ * ({@code android:sharedUserId}). For example, if app1 and app2 share the same user
+ * id, and app1 loads app2 apk, then both data directories will be registered.
+ */
+ /*package*/ void registerAppDataDir(String packageName, String dataDir) {
+ if (DEBUG) {
+ Slog.i(TAG, "Package " + packageName + " registering data dir: " + dataDir);
+ }
+ // TODO(calin): A few code paths imply that the data dir
+ // might be null. Investigate when that can happen.
+ if (dataDir != null) {
+ synchronized (mDataDirs) {
+ mDataDirs.add(dataDir);
+ }
+ }
+ }
+
+ @Override
+ public void report(List<String> dexPaths) {
+ if (dexPaths.isEmpty()) {
+ return;
+ }
+ // Notify the package manager about the dex loads unconditionally.
+ // The load might be for either a primary or secondary dex file.
+ notifyPackageManager(dexPaths);
+ // Check for secondary dex files and register them for profiling if
+ // possible.
+ registerSecondaryDexForProfiling(dexPaths);
+ }
+
+ private void notifyPackageManager(List<String> dexPaths) {
+ String packageName = ActivityThread.currentPackageName();
+ try {
+ ActivityThread.getPackageManager().notifyDexLoad(
+ packageName, dexPaths, VMRuntime.getRuntime().vmInstructionSet());
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Failed to notify PM about dex load for package " + packageName, re);
+ }
+ }
+
+ private void registerSecondaryDexForProfiling(List<String> dexPaths) {
+ if (!SystemProperties.getBoolean("dalvik.vm.dexopt.secondary", false)) {
+ return;
+ }
+ // Make a copy of the current data directories so that we don't keep the lock
+ // while registering for profiling. The registration will perform I/O to
+ // check for or create the profile.
+ String[] dataDirs;
+ synchronized (mDataDirs) {
+ dataDirs = mDataDirs.toArray(new String[0]);
+ }
+ for (String dexPath : dexPaths) {
+ registerSecondaryDexForProfiling(dexPath, dataDirs);
+ }
+ }
+
+ private void registerSecondaryDexForProfiling(String dexPath, String[] dataDirs) {
+ if (!isSecondaryDexFile(dexPath, dataDirs)) {
+ // The dex path is not a secondary dex file. Nothing to do.
+ return;
+ }
+ File secondaryProfile = getSecondaryProfileFile(dexPath);
+ try {
+ // Create the profile if not already there.
+ // Returns true if the file was created, false if the file already exists.
+ // or throws exceptions in case of errors.
+ boolean created = secondaryProfile.createNewFile();
+ if (DEBUG && created) {
+ Slog.i(TAG, "Created profile for secondary dex: " + secondaryProfile);
+ }
+ } catch (IOException ex) {
+ Slog.e(TAG, "Failed to create profile for secondary dex " + secondaryProfile +
+ ":" + ex.getMessage());
+ // Don't move forward with the registration if we failed to create the profile.
+ return;
+ }
+
+ VMRuntime.registerAppInfo(secondaryProfile.getPath(), new String[] { dexPath });
+ }
+
+ // A dex file is a secondary dex file if it is in any of the registered app
+ // data directories.
+ private boolean isSecondaryDexFile(String dexPath, String[] dataDirs) {
+ for (String dataDir : dataDirs) {
+ if (FileUtils.contains(dataDir, dexPath)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Secondary dex profiles are stored next to the dex file and have the same
+ // name with '.prof' appended.
+ // NOTE: Keep in sync with installd.
+ private File getSecondaryProfileFile(String dexPath) {
+ return new File(dexPath + ".prof");
+ }
+}
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 896f56c..5ea2480 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -67,6 +67,8 @@
ParceledListSlice getNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted);
int getNumNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted);
int getDeletedChannelCount(String pkg, int uid);
+ void deleteNotificationChannelGroup(String pkg, String channelGroupId);
+ ParceledListSlice getNotificationChannelGroups(String pkg);
// TODO: Remove this when callers have been migrated to the equivalent
// INotificationListener method.
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 77c4c7e..cf41e4e 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -55,7 +55,6 @@
import com.android.internal.util.ArrayUtils;
-import dalvik.system.BaseDexClassLoader;
import dalvik.system.VMRuntime;
import java.io.File;
@@ -752,39 +751,10 @@
VMRuntime.registerAppInfo(profileFile.getPath(),
codePaths.toArray(new String[codePaths.size()]));
- // Setup the reporter to notify package manager of any relevant dex loads.
- // At this point the primary apk is loaded and will not be reported.
- // Anything loaded from now on will be tracked as a potential secondary
- // or foreign dex file. The goal is to enable:
- // 1) monitoring and compilation of secondary dex file
- // 2) track whether or not a dex file is used by other apps (used to
- // determined the compilation filter of apks).
- if (BaseDexClassLoader.getReporter() != DexLoadReporter.INSTANCE) {
- // Set the dex load reporter if not already set.
- // Note that during the app's life cycle different LoadedApks may be
- // created and loaded (e.g. if two different apps share the same runtime).
- BaseDexClassLoader.setReporter(DexLoadReporter.INSTANCE);
- }
- }
-
- private static class DexLoadReporter implements BaseDexClassLoader.Reporter {
- private static final DexLoadReporter INSTANCE = new DexLoadReporter();
-
- private DexLoadReporter() {}
-
- @Override
- public void report(List<String> dexPaths) {
- if (dexPaths.isEmpty()) {
- return;
- }
- String packageName = ActivityThread.currentPackageName();
- try {
- ActivityThread.getPackageManager().notifyDexLoad(
- packageName, dexPaths, VMRuntime.getRuntime().vmInstructionSet());
- } catch (RemoteException re) {
- Slog.e(TAG, "Failed to notify PM about dex load for package " + packageName, re);
- }
- }
+ // Register the app data directory with the reporter. It will
+ // help deciding whether or not a dex file is the primary apk or a
+ // secondary dex.
+ DexLoadReporter.getInstance().registerAppDataDir(mPackageName, mDataDir);
}
/**
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index a098591..aee9d386 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1935,7 +1935,9 @@
if (this.actions != null) {
that.actions = new Action[this.actions.length];
for(int i=0; i<this.actions.length; i++) {
- that.actions[i] = this.actions[i].clone();
+ if ( this.actions[i] != null) {
+ that.actions[i] = this.actions[i].clone();
+ }
}
}
@@ -3432,7 +3434,9 @@
* @param action The action to add.
*/
public Builder addAction(Action action) {
- mActions.add(action);
+ if (action != null) {
+ mActions.add(action);
+ }
return this;
}
@@ -3446,7 +3450,9 @@
public Builder setActions(Action... actions) {
mActions.clear();
for (int i = 0; i < actions.length; i++) {
- mActions.add(actions[i]);
+ if (actions[i] != null) {
+ mActions.add(actions[i]);
+ }
}
return this;
}
@@ -5651,11 +5657,13 @@
static final String KEY_SENDER = "sender";
static final String KEY_DATA_MIME_TYPE = "type";
static final String KEY_DATA_URI= "uri";
+ static final String KEY_EXTRAS_BUNDLE = "extras";
private final CharSequence mText;
private final long mTimestamp;
private final CharSequence mSender;
+ private Bundle mExtras = new Bundle();
private String mDataMimeType;
private Uri mDataUri;
@@ -5724,6 +5732,13 @@
}
/**
+ * Get the extras Bundle for this message.
+ */
+ public Bundle getExtras() {
+ return mExtras;
+ }
+
+ /**
* Get the text used to display the contact's name in the messaging experience
*/
public CharSequence getSender() {
@@ -5760,6 +5775,9 @@
if (mDataUri != null) {
bundle.putParcelable(KEY_DATA_URI, mDataUri);
}
+ if (mExtras != null) {
+ bundle.putBundle(KEY_EXTRAS_BUNDLE, mExtras);
+ }
return bundle;
}
@@ -5794,10 +5812,12 @@
bundle.getLong(KEY_TIMESTAMP), bundle.getCharSequence(KEY_SENDER));
if (bundle.containsKey(KEY_DATA_MIME_TYPE) &&
bundle.containsKey(KEY_DATA_URI)) {
-
message.setData(bundle.getString(KEY_DATA_MIME_TYPE),
(Uri) bundle.getParcelable(KEY_DATA_URI));
}
+ if (bundle.containsKey(KEY_EXTRAS_BUNDLE)) {
+ message.getExtras().putAll(bundle.getBundle(KEY_EXTRAS_BUNDLE));
+ }
return message;
}
} catch (ClassCastException e) {
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 2a78b6b..0379970 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -498,6 +498,30 @@
}
/**
+ * Returns all notification channel groups belonging to the calling app.
+ */
+ public List<NotificationChannelGroup> getNotificationChannelGroups() {
+ INotificationManager service = getService();
+ try {
+ return service.getNotificationChannelGroups(mContext.getPackageName()).getList();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Deletes the given notification channel group.
+ */
+ public void deleteNotificationChannelGroup(String groupId) {
+ INotificationManager service = getService();
+ try {
+ service.deleteNotificationChannelGroup(mContext.getPackageName(), groupId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* @hide
*/
@TestApi
diff --git a/core/java/android/app/RemoteAction.java b/core/java/android/app/RemoteAction.java
index 5958bc1..e7fe407 100644
--- a/core/java/android/app/RemoteAction.java
+++ b/core/java/android/app/RemoteAction.java
@@ -41,12 +41,14 @@
private final CharSequence mTitle;
private final CharSequence mContentDescription;
private final PendingIntent mActionIntent;
+ private boolean mEnabled;
RemoteAction(Parcel in) {
mIcon = Icon.CREATOR.createFromParcel(in);
mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
mActionIntent = PendingIntent.CREATOR.createFromParcel(in);
+ mEnabled = in.readBoolean();
}
public RemoteAction(@NonNull Icon icon, @NonNull CharSequence title,
@@ -59,6 +61,21 @@
mTitle = title;
mContentDescription = contentDescription;
mActionIntent = intent;
+ mEnabled = true;
+ }
+
+ /**
+ * Sets whether this action is enabled.
+ */
+ public void setEnabled(boolean enabled) {
+ mEnabled = enabled;
+ }
+
+ /**
+ * Return whether this action is enabled.
+ */
+ public boolean isEnabled() {
+ return mEnabled;
}
/**
@@ -91,7 +108,9 @@
@Override
public RemoteAction clone() {
- return new RemoteAction(mIcon, mTitle, mContentDescription, mActionIntent);
+ RemoteAction action = new RemoteAction(mIcon, mTitle, mContentDescription, mActionIntent);
+ action.setEnabled(mEnabled);
+ return action;
}
@Override
@@ -105,11 +124,13 @@
TextUtils.writeToParcel(mTitle, out, flags);
TextUtils.writeToParcel(mContentDescription, out, flags);
mActionIntent.writeToParcel(out, flags);
+ out.writeBoolean(mEnabled);
}
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix);
pw.print("title=" + mTitle);
+ pw.print(" enabled=" + mEnabled);
pw.print(" contentDescription=" + mContentDescription);
pw.print(" icon=" + mIcon);
pw.print(" action=" + mActionIntent.getIntent());
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index 0fb5966..d9b6eed 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -17,6 +17,7 @@
package android.app.admin;
import android.accounts.AccountManager;
+import android.annotation.BroadcastBehavior;
import android.annotation.IntDef;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -81,6 +82,7 @@
* that other applications can not abuse it.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_DEVICE_ADMIN_ENABLED
= "android.app.action.DEVICE_ADMIN_ENABLED";
@@ -94,6 +96,7 @@
* to the user before they disable your admin.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED
= "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED";
@@ -115,6 +118,7 @@
* its intent filter.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_DEVICE_ADMIN_DISABLED
= "android.app.action.DEVICE_ADMIN_DISABLED";
@@ -131,6 +135,7 @@
* this broadcast.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_PASSWORD_CHANGED
= "android.app.action.ACTION_PASSWORD_CHANGED";
@@ -147,6 +152,7 @@
* this broadcast.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_PASSWORD_FAILED
= "android.app.action.ACTION_PASSWORD_FAILED";
@@ -160,6 +166,7 @@
* this broadcast.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_PASSWORD_SUCCEEDED
= "android.app.action.ACTION_PASSWORD_SUCCEEDED";
@@ -173,6 +180,7 @@
* this broadcast.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_PASSWORD_EXPIRING
= "android.app.action.ACTION_PASSWORD_EXPIRING";
@@ -187,6 +195,7 @@
* @see DevicePolicyManager#isLockTaskPermitted(String)
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_LOCK_TASK_ENTERING
= "android.app.action.LOCK_TASK_ENTERING";
@@ -200,6 +209,7 @@
* @see DevicePolicyManager#isLockTaskPermitted(String)
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_LOCK_TASK_EXITING
= "android.app.action.LOCK_TASK_EXITING";
@@ -232,6 +242,7 @@
* <p>Output: Nothing</p>
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_PROFILE_PROVISIONING_COMPLETE =
"android.app.action.PROFILE_PROVISIONING_COMPLETE";
@@ -244,6 +255,7 @@
* @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_BUGREPORT_SHARING_DECLINED =
"android.app.action.BUGREPORT_SHARING_DECLINED";
@@ -256,6 +268,7 @@
* @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_BUGREPORT_FAILED = "android.app.action.BUGREPORT_FAILED";
/**
@@ -266,6 +279,7 @@
* @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_BUGREPORT_SHARE =
"android.app.action.BUGREPORT_SHARE";
@@ -274,6 +288,7 @@
* @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_SECURITY_LOGS_AVAILABLE
= "android.app.action.SECURITY_LOGS_AVAILABLE";
@@ -283,6 +298,7 @@
* @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_NETWORK_LOGS_AVAILABLE
= "android.app.action.NETWORK_LOGS_AVAILABLE";
@@ -314,7 +330,8 @@
* @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_USER_ADDED = "android.app.action.USER_ADDED";
+ @BroadcastBehavior(explicitOnly = true)
+ public static final String ACTION_USER_ADDED = "android.app.action.USER_ADDED";
/**
* Broadcast action: notify the device owner that a user or profile has been removed.
@@ -323,6 +340,7 @@
* @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_USER_REMOVED = "android.app.action.USER_REMOVED";
/**
@@ -401,6 +419,7 @@
* @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_NOTIFY_PENDING_SYSTEM_UPDATE =
"android.app.action.NOTIFY_PENDING_SYSTEM_UPDATE";
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index b1fbc8f..27bfb51 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -1612,9 +1612,8 @@
return newChild(index, false, 0, 0);
}
- // TODO(b/33197203, b/33802548): add CTS/unit test
@Override
- public ViewStructure newChildForAutofill(int index, int virtualId, int flags) {
+ public ViewStructure newChild(int index, int virtualId, int flags) {
return newChild(index, true, virtualId, flags);
}
@@ -1624,7 +1623,7 @@
}
@Override
- public ViewStructure asyncNewChildForAutofill(int index, int virtualId, int flags) {
+ public ViewStructure asyncNewChild(int index, int virtualId, int flags) {
return asyncNewChild(index, true, virtualId);
}
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 67c791d..74a39e8 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -16,8 +16,11 @@
package android.appwidget;
+import android.annotation.BroadcastBehavior;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
@@ -81,12 +84,14 @@
*
* @see #ACTION_APPWIDGET_CONFIGURE
*/
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_APPWIDGET_PICK = "android.appwidget.action.APPWIDGET_PICK";
/**
* Similar to ACTION_APPWIDGET_PICK, but used from keyguard
* @hide
*/
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String
ACTION_KEYGUARD_APPWIDGET_PICK = "android.appwidget.action.KEYGUARD_APPWIDGET_PICK";
@@ -133,6 +138,7 @@
* @see #ACTION_APPWIDGET_CONFIGURE
*
*/
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_APPWIDGET_BIND = "android.appwidget.action.APPWIDGET_BIND";
/**
@@ -157,6 +163,7 @@
* and not display this AppWidget, and you will receive a {@link #ACTION_APPWIDGET_DELETED}
* broadcast.
*/
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_APPWIDGET_CONFIGURE = "android.appwidget.action.APPWIDGET_CONFIGURE";
/**
@@ -290,6 +297,8 @@
*
* @see AppWidgetProvider#onUpdate AppWidgetProvider.onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
*/
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_APPWIDGET_UPDATE = "android.appwidget.action.APPWIDGET_UPDATE";
/**
@@ -302,6 +311,8 @@
* AppWidgetProvider.onAppWidgetOptionsChanged(Context context,
* AppWidgetManager appWidgetManager, int appWidgetId, Bundle newExtras)
*/
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_APPWIDGET_OPTIONS_CHANGED = "android.appwidget.action.APPWIDGET_UPDATE_OPTIONS";
/**
@@ -312,6 +323,8 @@
*
* @see AppWidgetProvider#onDeleted AppWidgetProvider.onDeleted(Context context, int[] appWidgetIds)
*/
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_APPWIDGET_DELETED = "android.appwidget.action.APPWIDGET_DELETED";
/**
@@ -322,6 +335,8 @@
*
* @see AppWidgetProvider#onEnabled AppWidgetProvider.onDisabled(Context context)
*/
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_APPWIDGET_DISABLED = "android.appwidget.action.APPWIDGET_DISABLED";
/**
@@ -334,6 +349,8 @@
*
* @see AppWidgetProvider#onEnabled AppWidgetProvider.onEnabled(Context context)
*/
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_APPWIDGET_ENABLED = "android.appwidget.action.APPWIDGET_ENABLED";
/**
@@ -365,6 +382,8 @@
*
* @see #ACTION_APPWIDGET_HOST_RESTORED
*/
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_APPWIDGET_RESTORED
= "android.appwidget.action.APPWIDGET_RESTORED";
@@ -402,6 +421,8 @@
*
* @see #ACTION_APPWIDGET_RESTORED
*/
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(explicitOnly = true)
public static final String ACTION_APPWIDGET_HOST_RESTORED
= "android.appwidget.action.APPWIDGET_HOST_RESTORED";
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 488511b..4e1e42d 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1483,6 +1483,25 @@
}
/**
+ * Return the maximum LE advertising data length,
+ * if LE Extended Advertising feature is supported.
+ *
+ * @return the maximum LE advertising data length.
+ */
+ public int getLeMaximumAdvertisingDataLength() {
+ if (!getLeAccess()) return 0;
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null) return mService.getLeMaximumAdvertisingDataLength();
+ } catch (RemoteException e) {
+ Log.e(TAG, "failed to get getLeMaximumAdvertisingDataLength, error: ", e);
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ return 0;
+ }
+
+ /**
* Return true if hardware has entries available for matching beacons
*
* @return true if there are hw entries available for matching beacons
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 76ca554..b337817 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -108,6 +108,7 @@
boolean isLeCodedPhySupported();
boolean isLeExtendedAdvertisingSupported();
boolean isLePeriodicAdvertisingSupported();
+ int getLeMaximumAdvertisingDataLength();
BluetoothActivityEnergyInfo reportActivityInfo();
/**
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 33fedc7..29f29e7 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -50,14 +50,6 @@
void stopScan(in int scannerId);
void flushPendingBatchResults(in int scannerId);
- void registerAdvertiser(in IAdvertiserCallback callback);
- void unregisterAdvertiser(in int advertiserId);
- void startMultiAdvertising(in int advertiserId,
- in AdvertiseData advertiseData,
- in AdvertiseData scanResponse,
- in AdvertiseSettings settings);
- void stopMultiAdvertising(in int advertiserId);
-
void startAdvertisingSet(in AdvertisingSetParameters parameters, in AdvertiseData advertiseData,
in AdvertiseData scanResponse, in PeriodicAdvertisingParameters periodicParameters,
in AdvertiseData periodicData, in IAdvertisingSetCallback callback);
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index e03c947..c9f1d7a 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -28,6 +28,7 @@
import android.os.RemoteException;
import android.util.Log;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@@ -60,11 +61,12 @@
private final IBluetoothManager mBluetoothManager;
private final Handler mHandler;
private BluetoothAdapter mBluetoothAdapter;
- private final Map<AdvertiseCallback, AdvertiseCallbackWrapper>
- mLeAdvertisers = new HashMap<AdvertiseCallback, AdvertiseCallbackWrapper>();
+ private final Map<AdvertiseCallback, AdvertisingSetCallback>
+ mLegacyAdvertisers = new HashMap<>();
private final Map<AdvertisingSetCallback, IAdvertisingSetCallback>
- advertisingSetCallbackWrappers = new HashMap<>();
- private final Map<Integer, AdvertisingSet> advertisingSets = new HashMap<>();
+ mCallbackWrappers = Collections.synchronizedMap(new HashMap<>());
+ private final Map<Integer, AdvertisingSet>
+ mAdvertisingSets = Collections.synchronizedMap(new HashMap<>());
/**
* Use BluetoothAdapter.getLeAdvertiser() instead.
@@ -109,7 +111,7 @@
public void startAdvertising(AdvertiseSettings settings,
AdvertiseData advertiseData, AdvertiseData scanResponse,
final AdvertiseCallback callback) {
- synchronized (mLeAdvertisers) {
+ synchronized (mLegacyAdvertisers) {
BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
@@ -120,25 +122,65 @@
postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
return;
}
- if (mLeAdvertisers.containsKey(callback)) {
+ if (mLegacyAdvertisers.containsKey(callback)) {
postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED);
return;
}
- IBluetoothGatt gatt;
- try {
- gatt = mBluetoothManager.getBluetoothGatt();
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
- postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
- return;
+ AdvertisingSetParameters.Builder parameters = new AdvertisingSetParameters.Builder();
+ parameters.setLegacyMode(true);
+ parameters.setConnectable(isConnectable);
+ parameters.setTimeout(settings.getTimeout());
+ if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_LOW_POWER) {
+ parameters.setInterval(1600); // 1s
+ } else if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_BALANCED) {
+ parameters.setInterval(400); // 250ms
+ } else if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY) {
+ parameters.setInterval(160); // 100ms
}
- AdvertiseCallbackWrapper wrapper = new AdvertiseCallbackWrapper(callback, advertiseData,
- scanResponse, settings, gatt);
- wrapper.startRegisteration();
+
+ if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW) {
+ parameters.setTxPowerLevel(-21);
+ } else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_LOW) {
+ parameters.setTxPowerLevel(-15);
+ } else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM) {
+ parameters.setTxPowerLevel(-7);
+ } else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) {
+ parameters.setTxPowerLevel(1);
+ }
+
+ AdvertisingSetCallback wrapped = wrapOldCallback(callback, settings);
+ mLegacyAdvertisers.put(callback, wrapped);
+ startAdvertisingSet(parameters.build(), advertiseData, scanResponse, null, null,
+ wrapped);
}
}
+ AdvertisingSetCallback wrapOldCallback(AdvertiseCallback callback, AdvertiseSettings settings) {
+ return new AdvertisingSetCallback() {
+ public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int status) {
+ if (status != AdvertisingSetCallback.ADVERTISE_SUCCESS) {
+ postStartFailure(callback, status);
+ return;
+ }
+
+ postStartSuccess(callback, settings);
+ }
+
+ /* Legacy advertiser is disabled on timeout */
+ public void onAdvertisingEnabled(int advertiserId, boolean enabled, int status) {
+ if (enabled == true) {
+ Log.e(TAG, "Legacy advertiser should be only disabled on timeout," +
+ " but was enabled!");
+ return;
+ }
+
+ stopAdvertising(callback);
+ }
+
+ };
+ }
+
/**
* Stop Bluetooth LE advertising. The {@code callback} must be the same one use in
* {@link BluetoothLeAdvertiser#startAdvertising}.
@@ -148,20 +190,21 @@
* @param callback {@link AdvertiseCallback} identifies the advertising instance to stop.
*/
public void stopAdvertising(final AdvertiseCallback callback) {
- synchronized (mLeAdvertisers) {
+ synchronized (mLegacyAdvertisers) {
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
}
- AdvertiseCallbackWrapper wrapper = mLeAdvertisers.get(callback);
+ AdvertisingSetCallback wrapper = mLegacyAdvertisers.get(callback);
if (wrapper == null) return;
- wrapper.stopAdvertising();
+
+ stopAdvertisingSet(wrapper);
}
}
/**
* Creates a new advertising set. If operation succeed, device will start advertising. This
* method returns immediately, the operation status is delivered through
- * {@code callback.onNewAdvertisingSet()}.
+ * {@code callback.onAdvertisingSetStarted()}.
* <p>
* @param parameters advertising set parameters.
* @param advertiseData Advertisement data to be broadcasted.
@@ -180,7 +223,7 @@
/**
* Creates a new advertising set. If operation succeed, device will start advertising. This
* method returns immediately, the operation status is delivered through
- * {@code callback.onNewAdvertisingSet()}.
+ * {@code callback.onAdvertisingSetStarted()}.
* <p>
* @param parameters advertising set parameters.
* @param advertiseData Advertisement data to be broadcasted.
@@ -209,7 +252,10 @@
}
IAdvertisingSetCallback wrapped = wrap(callback, handler);
- advertisingSetCallbackWrappers.put(callback, wrapped);
+ if (mCallbackWrappers.putIfAbsent(callback, wrapped) != null) {
+ throw new IllegalArgumentException(
+ "callback instance already associated with advertising");
+ }
try {
gatt.startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
@@ -229,10 +275,9 @@
throw new IllegalArgumentException("callback cannot be null");
}
- IAdvertisingSetCallback wrapped = advertisingSetCallbackWrappers.remove(callback);
+ IAdvertisingSetCallback wrapped = mCallbackWrappers.remove(callback);
if (wrapped == null) {
- throw new IllegalArgumentException(
- "callback does not represent valid registered callback.");
+ return;
}
IBluetoothGatt gatt;
@@ -251,7 +296,9 @@
* @hide
*/
public void cleanup() {
- mLeAdvertisers.clear();
+ mLegacyAdvertisers.clear();
+ mCallbackWrappers.clear();
+ mAdvertisingSets.clear();
}
// Compute the size of advertisement data or scan resp
@@ -317,13 +364,13 @@
public void run() {
if (status != AdvertisingSetCallback.ADVERTISE_SUCCESS) {
callback.onAdvertisingSetStarted(null, status);
- advertisingSetCallbackWrappers.remove(callback);
+ mCallbackWrappers.remove(callback);
return;
}
AdvertisingSet advertisingSet =
new AdvertisingSet(advertiserId, mBluetoothManager);
- advertisingSets.put(advertiserId, advertisingSet);
+ mAdvertisingSets.put(advertiserId, advertisingSet);
callback.onAdvertisingSetStarted(advertisingSet, status);
}
});
@@ -333,10 +380,10 @@
handler.post(new Runnable() {
@Override
public void run() {
- AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+ AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onAdvertisingSetStopped(advertisingSet);
- advertisingSets.remove(advertiserId);
- advertisingSetCallbackWrappers.remove(callback);
+ mAdvertisingSets.remove(advertiserId);
+ mCallbackWrappers.remove(callback);
}
});
}
@@ -345,7 +392,7 @@
handler.post(new Runnable() {
@Override
public void run() {
- AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+ AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onAdvertisingEnabled(advertisingSet, enabled, status);
}
});
@@ -355,7 +402,7 @@
handler.post(new Runnable() {
@Override
public void run() {
- AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+ AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onAdvertisingDataSet(advertisingSet, status);
}
});
@@ -365,7 +412,7 @@
handler.post(new Runnable() {
@Override
public void run() {
- AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+ AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onScanResponseDataSet(advertisingSet, status);
}
});
@@ -375,7 +422,7 @@
handler.post(new Runnable() {
@Override
public void run() {
- AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+ AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onAdvertisingParametersUpdated(advertisingSet, status);
}
});
@@ -385,7 +432,7 @@
handler.post(new Runnable() {
@Override
public void run() {
- AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+ AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onPeriodicAdvertisingParametersUpdated(advertisingSet, status);
}
});
@@ -395,7 +442,7 @@
handler.post(new Runnable() {
@Override
public void run() {
- AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+ AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onPeriodicAdvertisingDataSet(advertisingSet, status);
}
});
@@ -405,7 +452,7 @@
handler.post(new Runnable() {
@Override
public void run() {
- AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+ AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onPeriodicAdvertisingEnable(advertisingSet, enable, status);
}
});
@@ -413,144 +460,6 @@
};
}
- /**
- * Bluetooth GATT interface callbacks for advertising.
- */
- private class AdvertiseCallbackWrapper extends IAdvertiserCallback.Stub {
- private static final int LE_CALLBACK_TIMEOUT_MILLIS = 2000;
- private final AdvertiseCallback mAdvertiseCallback;
- private final AdvertiseData mAdvertisement;
- private final AdvertiseData mScanResponse;
- private final AdvertiseSettings mSettings;
- private final IBluetoothGatt mBluetoothGatt;
-
- // mAdvertiserId -1: not registered
- // -2: advertise stopped or registration timeout
- // >=0: registered and advertising started
- private int mAdvertiserId;
- private boolean mIsAdvertising = false;
- private int registrationError = AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR;
-
- public AdvertiseCallbackWrapper(AdvertiseCallback advertiseCallback,
- AdvertiseData advertiseData, AdvertiseData scanResponse,
- AdvertiseSettings settings,
- IBluetoothGatt bluetoothGatt) {
- mAdvertiseCallback = advertiseCallback;
- mAdvertisement = advertiseData;
- mScanResponse = scanResponse;
- mSettings = settings;
- mBluetoothGatt = bluetoothGatt;
- mAdvertiserId = -1;
- }
-
- public void startRegisteration() {
- synchronized (this) {
- if (mAdvertiserId == -2) return;
-
- try {
- mBluetoothGatt.registerAdvertiser(this);
- wait(LE_CALLBACK_TIMEOUT_MILLIS);
- } catch (InterruptedException | RemoteException e) {
- Log.e(TAG, "Failed to start registeration", e);
- }
- if (mAdvertiserId >= 0 && mIsAdvertising) {
- mLeAdvertisers.put(mAdvertiseCallback, this);
- } else if (mAdvertiserId < 0) {
-
- // Registration timeout, reset mClientIf to -2 so no subsequent operations can
- // proceed.
- if (mAdvertiserId == -1) mAdvertiserId = -2;
- // Post internal error if registration failed.
- postStartFailure(mAdvertiseCallback, registrationError);
- } else {
- // Unregister application if it's already registered but advertise failed.
- try {
- mBluetoothGatt.unregisterAdvertiser(mAdvertiserId);
- mAdvertiserId = -2;
- } catch (RemoteException e) {
- Log.e(TAG, "remote exception when unregistering", e);
- }
- }
- }
- }
-
- public void stopAdvertising() {
- synchronized (this) {
- try {
- mBluetoothGatt.stopMultiAdvertising(mAdvertiserId);
- wait(LE_CALLBACK_TIMEOUT_MILLIS);
- } catch (InterruptedException | RemoteException e) {
- Log.e(TAG, "Failed to stop advertising", e);
- }
- // Advertise callback should have been removed from LeAdvertisers when
- // onMultiAdvertiseCallback was called. In case onMultiAdvertiseCallback is never
- // invoked and wait timeout expires, remove callback here.
- if (mLeAdvertisers.containsKey(mAdvertiseCallback)) {
- mLeAdvertisers.remove(mAdvertiseCallback);
- }
- }
- }
-
- /**
- * Advertiser interface registered - app is ready to go
- */
- @Override
- public void onAdvertiserRegistered(int status, int advertiserId) {
- Log.d(TAG, "onAdvertiserRegistered() - status=" + status + " advertiserId=" + advertiserId);
- synchronized (this) {
- if (status == BluetoothGatt.GATT_SUCCESS) {
- try {
- if (mAdvertiserId == -2) {
- // Registration succeeds after timeout, unregister advertiser.
- mBluetoothGatt.unregisterAdvertiser(advertiserId);
- } else {
- mAdvertiserId = advertiserId;
- mBluetoothGatt.startMultiAdvertising(mAdvertiserId, mAdvertisement,
- mScanResponse, mSettings);
- }
- return;
- } catch (RemoteException e) {
- Log.e(TAG, "failed to start advertising", e);
- }
- } else if (status == AdvertiseCallback.ADVERTISE_FAILED_TOO_MANY_ADVERTISERS) {
- registrationError = status;
- }
- // Registration failed.
- mAdvertiserId = -2;
- notifyAll();
- }
- }
-
- @Override
- public void onMultiAdvertiseCallback(int status, boolean isStart,
- AdvertiseSettings settings) {
- synchronized (this) {
- if (isStart) {
- if (status == AdvertiseCallback.ADVERTISE_SUCCESS) {
- // Start success
- mIsAdvertising = true;
- postStartSuccess(mAdvertiseCallback, settings);
- } else {
- // Start failure.
- postStartFailure(mAdvertiseCallback, status);
- }
- } else {
- // unregister advertiser for stop.
- try {
- mBluetoothGatt.unregisterAdvertiser(mAdvertiserId);
- mAdvertiserId = -2;
- mIsAdvertising = false;
- mLeAdvertisers.remove(mAdvertiseCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "remote exception when unregistering", e);
- }
- }
- notifyAll();
- }
-
- }
- }
-
private void postStartFailure(final AdvertiseCallback callback, final int error) {
mHandler.post(new Runnable() {
@Override
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 1f01e28..4dc6fd2 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -17,6 +17,7 @@
package android.content;
import android.annotation.AnyRes;
+import android.annotation.BroadcastBehavior;
import android.annotation.IntDef;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -1992,6 +1993,7 @@
* This is a protected intent that can only be sent by the system.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(includeBackground = true)
public static final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
/**
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 33f57e0..10ffab2 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2355,6 +2355,13 @@
= "android.hardware.vr.high_performance";
/**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+ * The device implements headtracking suitable for a VR device.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_VR_HEADTRACKING = "android.hardware.vr.headtracking";
+
+ /**
* Action to external storage service to clean out removed apps.
* @hide
*/
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index e15a0e2..be6dc05 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -211,6 +211,14 @@
CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
}
+ private static final boolean LOG_UNSAFE_BROADCASTS = false;
+
+ // Set of broadcast actions that are safe for manifest receivers
+ private static final Set<String> SAFE_BROADCASTS = new ArraySet<>();
+ static {
+ SAFE_BROADCASTS.add(Intent.ACTION_BOOT_COMPLETED);
+ }
+
/** @hide */
public static class NewPermissionInfo {
public final String name;
@@ -4203,6 +4211,7 @@
sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
if (visibleToEphemeral) {
a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
+ owner.visibleToInstantApps = true;
}
sa.recycle();
@@ -4247,6 +4256,18 @@
if (intent.isVisibleToInstantApp()) {
a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
}
+ if (LOG_UNSAFE_BROADCASTS && receiver
+ && (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) {
+ for (int i = 0; i < intent.countActions(); i++) {
+ final String action = intent.getAction(i);
+ if (action == null || !action.startsWith("android.")) continue;
+ if (!SAFE_BROADCASTS.contains(action)) {
+ Slog.w(TAG, "Broadcast " + action + " may never be delivered to "
+ + owner.packageName + " as requested at: "
+ + parser.getPositionDescription());
+ }
+ }
+ }
} else if (!receiver && parser.getName().equals("preferred")) {
ActivityIntentInfo intent = new ActivityIntentInfo(a);
if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/,
@@ -4696,6 +4717,7 @@
sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
if (visibleToEphemeral) {
p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL;
+ owner.visibleToInstantApps = true;
}
sa.recycle();
@@ -5012,6 +5034,7 @@
sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false);
if (visibleToEphemeral) {
s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL;
+ owner.visibleToInstantApps = true;
}
sa.recycle();
@@ -5615,6 +5638,11 @@
public byte[] restrictUpdateHash;
+ /**
+ * Set if the app or any of its components are visible to Instant Apps.
+ */
+ public boolean visibleToInstantApps;
+
public Package(String packageName) {
this.packageName = packageName;
this.manifestPackageName = packageName;
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 8bc65af..e3b97e8 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -100,6 +100,8 @@
private final CameraCharacteristics mCharacteristics;
private final int mTotalPartialCount;
+ private static final long NANO_PER_SECOND = 1000000000; //ns
+
/**
* A list tracking request and its expected last regular frame number and last reprocess frame
* number. Updated when calling ICameraDeviceUser methods.
@@ -1239,6 +1241,14 @@
private final List<CaptureRequest> mRequestList;
private final Handler mHandler;
private final int mSessionId;
+ /**
+ * <p>Determine if the callback holder is for a constrained high speed request list that
+ * expects batched capture results. Capture results will be batched if the request list
+ * is interleaved with preview and video requests. Capture results won't be batched if the
+ * request list only contains preview requests, or if the request doesn't belong to a
+ * constrained high speed list.
+ */
+ private final boolean mHasBatchedOutputs;
CaptureCallbackHolder(CaptureCallback callback, List<CaptureRequest> requestList,
Handler handler, boolean repeating, int sessionId) {
@@ -1251,6 +1261,25 @@
mRequestList = new ArrayList<CaptureRequest>(requestList);
mCallback = callback;
mSessionId = sessionId;
+
+ // Check whether this callback holder is for batched outputs.
+ // The logic here should match createHighSpeedRequestList.
+ boolean hasBatchedOutputs = true;
+ for (int i = 0; i < requestList.size(); i++) {
+ CaptureRequest request = requestList.get(i);
+ if (!request.isPartOfCRequestList()) {
+ hasBatchedOutputs = false;
+ break;
+ }
+ if (i == 0) {
+ Collection<Surface> targets = request.getTargets();
+ if (targets.size() != 2) {
+ hasBatchedOutputs = false;
+ break;
+ }
+ }
+ }
+ mHasBatchedOutputs = hasBatchedOutputs;
}
public boolean isRepeating() {
@@ -1288,6 +1317,14 @@
public int getSessionId() {
return mSessionId;
}
+
+ public int getRequestCount() {
+ return mRequestList.size();
+ }
+
+ public boolean hasBatchedOutputs() {
+ return mHasBatchedOutputs;
+ }
}
/**
@@ -1777,10 +1814,27 @@
@Override
public void run() {
if (!CameraDeviceImpl.this.isClosed()) {
- holder.getCallback().onCaptureStarted(
- CameraDeviceImpl.this,
- holder.getRequest(resultExtras.getSubsequenceId()),
- timestamp, frameNumber);
+ final int subsequenceId = resultExtras.getSubsequenceId();
+ final CaptureRequest request = holder.getRequest(subsequenceId);
+
+ if (holder.hasBatchedOutputs()) {
+ // Send derived onCaptureStarted for requests within the batch
+ final Range<Integer> fpsRange =
+ request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
+ for (int i = 0; i < holder.getRequestCount(); i++) {
+ holder.getCallback().onCaptureStarted(
+ CameraDeviceImpl.this,
+ holder.getRequest(i),
+ timestamp - (subsequenceId - i) *
+ NANO_PER_SECOND/fpsRange.getUpper(),
+ frameNumber - (subsequenceId - i));
+ }
+ } else {
+ holder.getCallback().onCaptureStarted(
+ CameraDeviceImpl.this,
+ holder.getRequest(resultExtras.getSubsequenceId()),
+ timestamp, frameNumber);
+ }
}
}
});
@@ -1845,46 +1899,91 @@
Runnable resultDispatch = null;
CaptureResult finalResult;
+ // Make a copy of the native metadata before it gets moved to a CaptureResult
+ // object.
+ final CameraMetadataNative resultCopy;
+ if (holder.hasBatchedOutputs()) {
+ resultCopy = new CameraMetadataNative(result);
+ } else {
+ resultCopy = null;
+ }
// Either send a partial result or the final capture completed result
if (isPartialResult) {
final CaptureResult resultAsCapture =
new CaptureResult(result, request, resultExtras);
-
// Partial result
resultDispatch = new Runnable() {
@Override
public void run() {
- if (!CameraDeviceImpl.this.isClosed()){
- holder.getCallback().onCaptureProgressed(
- CameraDeviceImpl.this,
- request,
- resultAsCapture);
+ if (!CameraDeviceImpl.this.isClosed()) {
+ if (holder.hasBatchedOutputs()) {
+ // Send derived onCaptureProgressed for requests within
+ // the batch.
+ for (int i = 0; i < holder.getRequestCount(); i++) {
+ CameraMetadataNative resultLocal =
+ new CameraMetadataNative(resultCopy);
+ CaptureResult resultInBatch = new CaptureResult(
+ resultLocal, holder.getRequest(i), resultExtras);
+
+ holder.getCallback().onCaptureProgressed(
+ CameraDeviceImpl.this,
+ holder.getRequest(i),
+ resultInBatch);
+ }
+ } else {
+ holder.getCallback().onCaptureProgressed(
+ CameraDeviceImpl.this,
+ request,
+ resultAsCapture);
+ }
}
}
};
-
finalResult = resultAsCapture;
} else {
List<CaptureResult> partialResults =
mFrameNumberTracker.popPartialResults(frameNumber);
+ final long sensorTimestamp =
+ result.get(CaptureResult.SENSOR_TIMESTAMP);
+ final Range<Integer> fpsRange =
+ request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
+ final int subsequenceId = resultExtras.getSubsequenceId();
final TotalCaptureResult resultAsCapture = new TotalCaptureResult(result,
request, resultExtras, partialResults, holder.getSessionId());
-
// Final capture result
resultDispatch = new Runnable() {
@Override
public void run() {
if (!CameraDeviceImpl.this.isClosed()){
- holder.getCallback().onCaptureCompleted(
- CameraDeviceImpl.this,
- request,
- resultAsCapture);
+ if (holder.hasBatchedOutputs()) {
+ // Send derived onCaptureCompleted for requests within
+ // the batch.
+ for (int i = 0; i < holder.getRequestCount(); i++) {
+ resultCopy.set(CaptureResult.SENSOR_TIMESTAMP,
+ sensorTimestamp - (subsequenceId - i) *
+ NANO_PER_SECOND/fpsRange.getUpper());
+ CameraMetadataNative resultLocal =
+ new CameraMetadataNative(resultCopy);
+ TotalCaptureResult resultInBatch = new TotalCaptureResult(
+ resultLocal, holder.getRequest(i), resultExtras,
+ partialResults, holder.getSessionId());
+
+ holder.getCallback().onCaptureCompleted(
+ CameraDeviceImpl.this,
+ holder.getRequest(i),
+ resultInBatch);
+ }
+ } else {
+ holder.getCallback().onCaptureCompleted(
+ CameraDeviceImpl.this,
+ request,
+ resultAsCapture);
+ }
}
}
};
-
finalResult = resultAsCapture;
}
diff --git a/core/java/android/hardware/radio/RadioModule.java b/core/java/android/hardware/radio/RadioModule.java
index fc7d0d2..8964893 100644
--- a/core/java/android/hardware/radio/RadioModule.java
+++ b/core/java/android/hardware/radio/RadioModule.java
@@ -16,6 +16,8 @@
package android.hardware.radio;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
@@ -23,6 +25,7 @@
import android.os.Looper;
import android.os.Message;
import java.lang.ref.WeakReference;
+import java.util.List;
import java.util.UUID;
/**
@@ -76,6 +79,8 @@
public native int getProgramInformation(RadioManager.ProgramInfo[] info);
+ public native @NonNull List<RadioManager.ProgramInfo> getProgramList(@Nullable String filter);
+
public native boolean isAntennaConnected();
public native boolean hasControl();
diff --git a/core/java/android/hardware/radio/RadioTuner.java b/core/java/android/hardware/radio/RadioTuner.java
index 5c82555..c8034eb 100644
--- a/core/java/android/hardware/radio/RadioTuner.java
+++ b/core/java/android/hardware/radio/RadioTuner.java
@@ -16,6 +16,8 @@
package android.hardware.radio;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
@@ -23,6 +25,7 @@
import android.os.Looper;
import android.os.Message;
import java.lang.ref.WeakReference;
+import java.util.List;
import java.util.UUID;
/**
@@ -209,6 +212,20 @@
public abstract int getProgramInformation(RadioManager.ProgramInfo[] info);
/**
+ * Get the list of discovered radio stations.
+ *
+ * To get the full list, set filter to null or empty string. Otherwise, client application
+ * must verify vendor product/name before setting this parameter to anything else.
+ *
+ * @param filter vendor-specific selector for radio stations.
+ * @return a list of radio stations.
+ * @throws IllegalStateException if the scan is in progress or has not been started.
+ * @throws IllegalArgumentException if the filter argument is not valid.
+ * @hide FutureFeature
+ */
+ public abstract @NonNull List<RadioManager.ProgramInfo> getProgramList(@Nullable String filter);
+
+ /**
* Get current antenna connection state for current configuration.
* Only valid if a configuration has been applied.
* @return {@code true} if the antenna is connected, {@code false} otherwise.
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 0136979..7906707 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -66,7 +66,8 @@
* of classes can potentially create leaks.
*/
private static final boolean FIND_POTENTIAL_LEAKS = false;
- private static final boolean CHECK_PARCEL_SIZE = false;
+ /** @hide */
+ public static final boolean CHECK_PARCEL_SIZE = false;
static final String TAG = "Binder";
/** @hide */
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index a265dd0..94fd5b0 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -219,6 +219,7 @@
public native final void writeStatus(int status);
public native final void verifySuccess();
public native final void releaseTemporaryStorage();
+ public native final void release();
public native final void send();
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index caea202..f503b3a 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -2638,7 +2638,7 @@
dest.writeString(broadcastIntentAction);
dest.writeStringArray(tags);
int total = dest.dataPosition()-start;
- if (total > 10*1024) {
+ if (Binder.CHECK_PARCEL_SIZE && total > 10*1024) {
Slog.d(TAG, "VIO: policy=" + policy + " dur=" + durationMillis
+ " numLoop=" + violationNumThisLoop
+ " anim=" + numAnimationsRunning
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index a638cd4..f6712f8 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -22,6 +22,7 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.Activity;
@@ -763,6 +764,16 @@
public static final int PIN_VERIFICATION_SUCCESS = -1;
/**
+ * Sent when user restrictions have changed.
+ *
+ * @hide
+ */
+ @SystemApi
+ @TestApi // To allow seeing it from CTS.
+ public static final String ACTION_USER_RESTRICTIONS_CHANGED =
+ "android.os.action.USER_RESTRICTIONS_CHANGED";
+
+ /**
* Error result indicating that this user is not allowed to add other users on this device.
* This is a result code returned from the activity created by the intent
* {@link #createUserCreationIntent(String, String, String, PersistableBundle)}.
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 6663f03..6213d27 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -215,8 +215,10 @@
* @throws IllegalArgumentException if {@code requiredIds} is {@code null} or empty.
*/
public Builder(@SaveDataType int type, @NonNull AutofillId[] requiredIds) {
+ if (false) {// TODO(b/33197203): re-move when clients use it
Preconditions.checkArgument(requiredIds != null && requiredIds.length > 0,
- "must have at least on required id: " + Arrays.toString(requiredIds));
+ "must have at least one required id: " + Arrays.toString(requiredIds));
+ }
switch (type) {
case SAVE_DATA_TYPE_PASSWORD:
case SAVE_DATA_TYPE_ADDRESS:
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 70e0461..f55c7cf 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -149,13 +149,13 @@
// Notification cancellation reasons
/** Notification was canceled by the status bar reporting a notification click. */
- public static final int REASON_DELEGATE_CLICK = 1;
+ public static final int REASON_CLICK = 1;
/** Notification was canceled by the status bar reporting a user dismissal. */
- public static final int REASON_DELEGATE_CANCEL = 2;
+ public static final int REASON_CANCEL = 2;
/** Notification was canceled by the status bar reporting a user dismiss all. */
- public static final int REASON_DELEGATE_CANCEL_ALL = 3;
+ public static final int REASON_CANCEL_ALL = 3;
/** Notification was canceled by the status bar reporting an inflation error. */
- public static final int REASON_DELEGATE_ERROR = 4;
+ public static final int REASON_ERROR = 4;
/** Notification was canceled by the package manager modifying the package. */
public static final int REASON_PACKAGE_CHANGED = 5;
/** Notification was canceled by the owning user context being stopped. */
diff --git a/core/java/android/service/vr/IVrManager.aidl b/core/java/android/service/vr/IVrManager.aidl
index 10e4177..6034c18 100644
--- a/core/java/android/service/vr/IVrManager.aidl
+++ b/core/java/android/service/vr/IVrManager.aidl
@@ -50,5 +50,13 @@
* @param enabled true if the device should be placed in persistent VR mode.
*/
void setPersistentVrModeEnabled(in boolean enabled);
+
+ /**
+ * Return current virtual display id.
+ *
+ * @return {@link android.view.Display.INVALID_DISPLAY} if there is no virtual display
+ * currently, else return the display id of the virtual display
+ */
+ int getCompatibilityDisplayId();
}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 483a49b..6bbb0ff 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -18,11 +18,11 @@
import android.content.res.TypedArray;
import android.graphics.Canvas;
+import android.util.MergedConfiguration;
import android.view.WindowInsets;
import com.android.internal.R;
import com.android.internal.os.HandlerCaller;
-import com.android.internal.util.ScreenShapeHelper;
import com.android.internal.view.BaseIWindow;
import com.android.internal.view.BaseSurfaceHolder;
@@ -32,7 +32,6 @@
import android.app.WallpaperManager;
import android.content.Context;
import android.content.Intent;
-import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
@@ -55,7 +54,6 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerGlobal;
import java.io.FileDescriptor;
@@ -169,7 +167,7 @@
final Rect mFinalSystemInsets = new Rect();
final Rect mFinalStableInsets = new Rect();
final Rect mBackdropFrame = new Rect();
- final Configuration mConfiguration = new Configuration();
+ final MergedConfiguration mMergedConfiguration = new MergedConfiguration();
final WindowManager.LayoutParams mLayout
= new WindowManager.LayoutParams();
@@ -288,7 +286,7 @@
@Override
public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
- Configuration newConfig, Rect backDropRect, boolean forceLayout,
+ MergedConfiguration mergedConfiguration, Rect backDropRect, boolean forceLayout,
boolean alwaysConsumeNavBar, int displayId) {
Message msg = mCaller.obtainMessageIO(MSG_WINDOW_RESIZED,
reportDraw ? 1 : 0, outsets);
@@ -568,7 +566,8 @@
out.print(mVisibleInsets.toShortString());
out.print(" mWinFrame="); out.print(mWinFrame.toShortString());
out.print(" mContentInsets="); out.println(mContentInsets.toShortString());
- out.print(prefix); out.print("mConfiguration="); out.println(mConfiguration);
+ out.print(prefix); out.print("mConfiguration=");
+ out.println(mMergedConfiguration.getMergedConfiguration());
out.print(prefix); out.print("mLayout="); out.println(mLayout);
synchronized (mLock) {
out.print(prefix); out.print("mPendingXOffset="); out.print(mPendingXOffset);
@@ -695,7 +694,7 @@
mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
View.VISIBLE, 0, mWinFrame, mOverscanInsets, mContentInsets,
mVisibleInsets, mStableInsets, mOutsets, mBackdropFrame,
- mConfiguration, mSurfaceHolder.mSurface);
+ mMergedConfiguration, mSurfaceHolder.mSurface);
if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface
+ ", frame=" + mWinFrame);
diff --git a/core/java/android/util/LauncherIcons.java b/core/java/android/util/LauncherIcons.java
new file mode 100644
index 0000000..e5aa2b5
--- /dev/null
+++ b/core/java/android/util/LauncherIcons.java
@@ -0,0 +1,113 @@
+/*
+ * 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 android.util;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.PaintFlagsDrawFilter;
+import android.graphics.Path;
+import android.graphics.RectF;
+import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+
+/**
+ * Utility class to handle icon treatments (e.g., shadow generation) for the Launcher icons.
+ * @hide
+ */
+public final class LauncherIcons {
+
+ private final Paint mPaint = new Paint();
+ private final Canvas mCanvas = new Canvas();
+
+ private static final int KEY_SHADOW_ALPHA = 61;
+ private static final int AMBIENT_SHADOW_ALPHA = 30;
+ private static final float BLUR_FACTOR = 0.5f / 48;
+ private int mShadowInset;
+ private Bitmap mShadowBitmap;
+ private int mIconSize;
+ private Resources mRes;
+
+ public LauncherIcons(Context context) {
+ mRes = context.getResources();
+ DisplayMetrics metrics = mRes.getDisplayMetrics();
+ mShadowInset = (int) metrics.density / DisplayMetrics.DENSITY_DEFAULT;
+ mCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
+ Paint.FILTER_BITMAP_FLAG));
+ mIconSize = (int) mRes.getDimensionPixelSize(android.R.dimen.app_icon_size);
+ }
+
+ /**
+ * Draw the drawable into a bitmap.
+ */
+ public Bitmap createIconBitmap(Drawable icon) {
+ final Bitmap bitmap = Bitmap.createBitmap(mIconSize, mIconSize, Bitmap.Config.ARGB_8888);
+ mPaint.setAlpha(255);
+ mCanvas.setBitmap(bitmap);
+ int iconInset = 0;
+ if (mShadowBitmap != null) {
+ mCanvas.drawBitmap(mShadowBitmap, 0, 0, mPaint);
+ iconInset = mShadowInset;
+ }
+
+ icon.setBounds(iconInset, iconInset, mIconSize - iconInset,
+ mIconSize - iconInset);
+ icon.draw(mCanvas);
+ mCanvas.setBitmap(null);
+ return bitmap;
+ }
+
+ public Drawable wrapIconDrawableWithShadow(Drawable drawable) {
+ if (!(drawable instanceof AdaptiveIconDrawable)) {
+ return drawable;
+ }
+ AdaptiveIconDrawable d =
+ (AdaptiveIconDrawable) drawable.getConstantState().newDrawable().mutate();
+ getShadowBitmap(d);
+ Bitmap iconbitmap = createIconBitmap(d);
+ return new BitmapDrawable(mRes, iconbitmap);
+ }
+
+ private Bitmap getShadowBitmap(AdaptiveIconDrawable d) {
+ if (mShadowBitmap != null) {
+ return mShadowBitmap;
+ }
+
+ int shadowSize = mIconSize - mShadowInset;
+ mShadowBitmap = Bitmap.createBitmap(mIconSize, mIconSize, Bitmap.Config.ALPHA_8);
+ mCanvas.setBitmap(mShadowBitmap);
+
+ // Draw key shadow
+ mPaint.setColor(Color.TRANSPARENT);
+ float blur = BLUR_FACTOR * mIconSize;
+ mPaint.setShadowLayer(blur, 0, mShadowInset, KEY_SHADOW_ALPHA << 24);
+ d.setBounds(mShadowInset, mShadowInset, mIconSize - mShadowInset, mIconSize - mShadowInset);
+ mCanvas.drawPath(d.getIconMask(), mPaint);
+
+ // Draw ambient shadow
+ mPaint.setShadowLayer(blur, 0, 0, AMBIENT_SHADOW_ALPHA << 24);
+ d.setBounds(mShadowInset, 2 * mShadowInset, mIconSize - mShadowInset, mIconSize);
+ mCanvas.drawPath(d.getIconMask(), mPaint);
+ mPaint.clearShadowLayer();
+
+ return mShadowBitmap;
+ }
+}
diff --git a/core/java/android/util/MergedConfiguration.aidl b/core/java/android/util/MergedConfiguration.aidl
new file mode 100644
index 0000000..c24dbbe
--- /dev/null
+++ b/core/java/android/util/MergedConfiguration.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.util;
+
+parcelable MergedConfiguration;
\ No newline at end of file
diff --git a/core/java/android/util/MergedConfiguration.java b/core/java/android/util/MergedConfiguration.java
new file mode 100644
index 0000000..d94af8a
--- /dev/null
+++ b/core/java/android/util/MergedConfiguration.java
@@ -0,0 +1,122 @@
+/*
+ * 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 android.util;
+
+import android.annotation.NonNull;
+import android.content.res.Configuration;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Container that holds global and override config and their merge product.
+ * Merged configuration updates automatically whenever global or override configs are updated via
+ * setters.
+ *
+ * {@hide}
+ */
+public class MergedConfiguration implements Parcelable {
+
+ private Configuration mGlobalConfig = new Configuration();
+ private Configuration mOverrideConfig = new Configuration();
+ private Configuration mMergedConfig = new Configuration();
+
+ public MergedConfiguration() {
+ }
+
+ public MergedConfiguration(Configuration globalConfig, Configuration overrideConfig) {
+ setConfiguration(globalConfig, overrideConfig);
+ }
+
+ public MergedConfiguration(MergedConfiguration mergedConfiguration) {
+ setConfiguration(mergedConfiguration.getGlobalConfiguration(),
+ mergedConfiguration.getOverrideConfiguration());
+ }
+
+ private MergedConfiguration(Parcel in) {
+ readFromParcel(in);
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mGlobalConfig, flags);
+ dest.writeParcelable(mOverrideConfig, flags);
+ dest.writeParcelable(mMergedConfig, flags);
+ }
+
+ public void readFromParcel(Parcel source) {
+ mGlobalConfig = source.readParcelable(Configuration.class.getClassLoader());
+ mOverrideConfig = source.readParcelable(Configuration.class.getClassLoader());
+ mMergedConfig = source.readParcelable(Configuration.class.getClassLoader());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<MergedConfiguration> CREATOR = new Creator<MergedConfiguration>() {
+ @Override
+ public MergedConfiguration createFromParcel(Parcel in) {
+ return new MergedConfiguration(in);
+ }
+
+ @Override
+ public MergedConfiguration[] newArray(int size) {
+ return new MergedConfiguration[size];
+ }
+ };
+
+ /**
+ * Update global and override configurations.
+ * Merged configuration will automatically be updated.
+ * @param globalConfig New global configuration.
+ * @param overrideConfig New override configuration.
+ */
+ public void setConfiguration(Configuration globalConfig, Configuration overrideConfig) {
+ mGlobalConfig.setTo(globalConfig);
+ mOverrideConfig.setTo(overrideConfig);
+ updateMergedConfig();
+ }
+
+ /**
+ * @return Stored global configuration value.
+ */
+ @NonNull
+ public Configuration getGlobalConfiguration() {
+ return mGlobalConfig;
+ }
+
+ /**
+ * @return Stored override configuration value.
+ */
+ public Configuration getOverrideConfiguration() {
+ return mOverrideConfig;
+ }
+
+ /**
+ * @return Stored merged configuration value.
+ */
+ public Configuration getMergedConfiguration() {
+ return mMergedConfig;
+ }
+
+ /** Update merged config when global or override config changes. */
+ private void updateMergedConfig() {
+ mMergedConfig.setTo(mGlobalConfig);
+ mMergedConfig.updateFrom(mOverrideConfig);
+ }
+}
diff --git a/core/java/android/view/AccessibilityIterators.java b/core/java/android/view/AccessibilityIterators.java
index e59937d..ca54bef 100644
--- a/core/java/android/view/AccessibilityIterators.java
+++ b/core/java/android/view/AccessibilityIterators.java
@@ -16,7 +16,6 @@
package android.view;
-import android.content.ComponentCallbacks;
import android.content.res.Configuration;
import java.text.BreakIterator;
@@ -65,7 +64,7 @@
}
static class CharacterTextSegmentIterator extends AbstractTextSegmentIterator
- implements ComponentCallbacks {
+ implements ViewRootImpl.ConfigChangedCallback {
private static CharacterTextSegmentIterator sInstance;
private Locale mLocale;
@@ -144,19 +143,14 @@
}
@Override
- public void onConfigurationChanged(Configuration newConfig) {
- Locale locale = newConfig.locale;
+ public void onConfigurationChanged(Configuration globalConfig) {
+ final Locale locale = globalConfig.getLocales().get(0);
if (!mLocale.equals(locale)) {
mLocale = locale;
onLocaleChanged(locale);
}
}
- @Override
- public void onLowMemory() {
- /* ignore */
- }
-
protected void onLocaleChanged(Locale locale) {
mImpl = BreakIterator.getCharacterInstance(locale);
}
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 14b2abe..611cc63 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -17,7 +17,6 @@
package android.view;
-import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
@@ -26,6 +25,7 @@
import android.view.MotionEvent;
import com.android.internal.os.IResultReceiver;
+import android.util.MergedConfiguration;
/**
* API back to a client window that the Window Manager uses to inform it of
@@ -49,8 +49,8 @@
void resized(in Rect frame, in Rect overscanInsets, in Rect contentInsets,
in Rect visibleInsets, in Rect stableInsets, in Rect outsets, boolean reportDraw,
- in Configuration newConfig, in Rect backDropFrame, boolean forceLayout,
- boolean alwaysConsumeNavBar, int displayId);
+ in MergedConfiguration newMergedConfiguration, in Rect backDropFrame,
+ boolean forceLayout, boolean alwaysConsumeNavBar, int displayId);
void moved(int newX, int newY);
void dispatchAppVisibility(boolean visible);
void dispatchGetNewSurface();
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 7e6af11..51d6514 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -11,17 +11,17 @@
** 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
+** See the License for the specific language governing permissions and
** limitations under the License.
*/
package android.view;
import android.content.ClipData;
-import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Bundle;
+import android.util.MergedConfiguration;
import android.view.InputChannel;
import android.view.IWindow;
import android.view.IWindowId;
@@ -83,9 +83,9 @@
* treat as real display. Example of such area is a chin in some models of wearable devices.
* @param outBackdropFrame Rect which is used draw the resizing background during a resize
* operation.
- * @param outConfiguration New configuration of window, if it is now
- * becoming visible and the global configuration has changed since it
- * was last displayed.
+ * @param outMergedConfiguration New config container that holds global, override and merged
+ * config for window, if it is now becoming visible and the merged configuration has changed
+ * since it was last displayed.
* @param outSurface Object in which is placed the new display surface.
*
* @return int Result flags: {@link WindowManagerGlobal#RELAYOUT_SHOW_FOCUS},
@@ -95,8 +95,8 @@
int requestedWidth, int requestedHeight, int viewVisibility,
int flags, out Rect outFrame, out Rect outOverscanInsets,
out Rect outContentInsets, out Rect outVisibleInsets, out Rect outStableInsets,
- out Rect outOutsets, out Rect outBackdropFrame, out Configuration outConfig,
- out Surface outSurface);
+ out Rect outOutsets, out Rect outBackdropFrame,
+ out MergedConfiguration outMergedConfiguration, out Surface outSurface);
/*
* Notify the window manager that an application is relaunching and
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 6d320ef..824e035 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -16,8 +16,9 @@
package android.view;
-import static android.view.WindowManagerPolicy.APPLICATION_MEDIA_SUBLAYER;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
import static android.view.WindowManagerPolicy.APPLICATION_MEDIA_OVERLAY_SUBLAYER;
+import static android.view.WindowManagerPolicy.APPLICATION_MEDIA_SUBLAYER;
import static android.view.WindowManagerPolicy.APPLICATION_PANEL_SUBLAYER;
import android.content.Context;
@@ -28,6 +29,7 @@
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Region;
+import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
@@ -777,6 +779,31 @@
}
/**
+ * This method still exists only for compatibility reasons because some applications have relied
+ * on this method via reflection. See Issue 36345857 for details.
+ *
+ * @deprecated No platform code is using this method anymore.
+ * @hide
+ */
+ @Deprecated
+ public void setWindowType(int type) {
+ if (getContext().getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.N_MR1) {
+ throw new UnsupportedOperationException(
+ "SurfaceView#setWindowType() has never been a public API.");
+ }
+
+ if (type == TYPE_APPLICATION_PANEL) {
+ Log.e(TAG, "If you are calling SurfaceView#setWindowType(TYPE_APPLICATION_PANEL) "
+ + "just to make the SurfaceView to be placed on top of its window, you must "
+ + "call setZOrderOnTop(true) instead.", new Throwable());
+ setZOrderOnTop(true);
+ return;
+ }
+ Log.e(TAG, "SurfaceView#setWindowType(int) is deprecated and now does nothing. "
+ + "type=" + type, new Throwable());
+ }
+
+ /**
* Check to see if the surface has fixed size dimensions or if the surface's
* dimensions are dimensions are dependent on its current layout.
*
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 80f6c32..583dad4 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2749,13 +2749,8 @@
* x * NO LONGER NEEDED, SHOULD BE REUSED *
* 1 PFLAG3_FINGER_DOWN
* 1 PFLAG3_FOCUSED_BY_DEFAULT
-<<<<<<< HEAD
* 11 PFLAG3_AUTO_FILL_MODE_MASK
* 11 PFLAG3_IMPORTANT_FOR_AUTOFILL
-=======
- * 11 PFLAG3_AUTOFILL_MODE_MASK
- * xx * NO LONGER NEEDED, SHOULD BE REUSED *
->>>>>>> Replaced auto-fill by autofill to keep it consistent with API style.
* 1 PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
* 1 PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
* 1 PFLAG3_TEMPORARY_DETACH
@@ -7384,13 +7379,13 @@
* <p>When implementing this method, subclasses must follow the rules below:
*
* <ol>
- * <li>Also implement {@link #autofillVirtual(int, AutofillValue)} to autofill the virtual
+ * <li>Also implement {@link #autofill(int, AutofillValue)} to autofill the virtual
* children.
* <li>Call
- * {@link android.view.autofill.AutofillManager#notifyVirtualViewEntered} and
- * {@link android.view.autofill.AutofillManager#notifyVirtualViewExited(View, int)}
+ * {@link android.view.autofill.AutofillManager#notifyViewEntered} and
+ * {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
* when the focus inside the view changed.
- * <li>Call {@link android.view.autofill.AutofillManager#notifyVirtualValueChanged(View, int,
+ * <li>Call {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int,
* AutofillValue)} when the value of a child changed.
* <li>Call {@link AutofillManager#commit()} when the autofill context
* of the view structure changed and you want the current autofill interaction if such
@@ -7445,8 +7440,11 @@
* </pre>
*
* @param value value to be autofilled.
+ *
+ * @return {@code true} if the view was successfully autofilled, {@code false} otherwise
*/
- public void autofill(@SuppressWarnings("unused") AutofillValue value) {
+ public boolean autofill(@SuppressWarnings("unused") AutofillValue value) {
+ return false;
}
/**
@@ -7457,14 +7455,17 @@
*
* @param value value to be autofilled.
* @param virtualId id identifying the virtual child inside the custom view.
+ *
+ * @return {@code true} if the view was successfully autofilled, {@code false} otherwise
*/
- public void autofillVirtual(@SuppressWarnings("unused") int virtualId,
+ public boolean autofill(@SuppressWarnings("unused") int virtualId,
@SuppressWarnings("unused") AutofillValue value) {
+ return false;
}
/**
* Describes the autofill type that should be used on calls to
- * {@link #autofill(AutofillValue)} and {@link #autofillVirtual(int, AutofillValue)}.
+ * {@link #autofill(AutofillValue)} and {@link #autofill(int, AutofillValue)}.
*
* <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it (and
* {@link #autofill(AutofillValue)} to support the Autofill Framework.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ed42385..1681787 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -16,6 +16,7 @@
package android.view;
+import static android.view.Display.INVALID_DISPLAY;
import static android.view.View.PFLAG_DRAW_ANIMATION;
import static android.view.WindowCallbacks.RESIZE_MODE_DOCKED_DIVIDER;
import static android.view.WindowCallbacks.RESIZE_MODE_FREEFORM;
@@ -28,10 +29,10 @@
import android.animation.LayoutTransition;
import android.annotation.NonNull;
import android.app.ActivityManager;
+import android.app.ActivityThread;
import android.app.ResourcesManager;
import android.content.ClipData;
import android.content.ClipDescription;
-import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.CompatibilityInfo;
@@ -67,6 +68,7 @@
import android.util.AndroidRuntimeException;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.MergedConfiguration;
import android.util.Slog;
import android.util.TimeUtils;
import android.util.TypedValue;
@@ -161,7 +163,44 @@
static final ArrayList<Runnable> sFirstDrawHandlers = new ArrayList();
static boolean sFirstDrawComplete = false;
- static final ArrayList<ComponentCallbacks> sConfigCallbacks = new ArrayList();
+ /**
+ * Callback for notifying about global configuration changes.
+ */
+ public interface ConfigChangedCallback {
+
+ /** Notifies about global config change. */
+ void onConfigurationChanged(Configuration globalConfig);
+ }
+
+ private static final ArrayList<ConfigChangedCallback> sConfigCallbacks = new ArrayList<>();
+
+ /**
+ * Callback for notifying activities about override configuration changes.
+ */
+ public interface ActivityConfigCallback {
+
+ /**
+ * Notifies about override config change and/or move to different display.
+ * @param overrideConfig New override config to apply to activity.
+ * @param newDisplayId New display id, {@link Display#INVALID_DISPLAY} if not changed.
+ */
+ void onConfigurationChanged(Configuration overrideConfig, int newDisplayId);
+ }
+
+ /**
+ * Callback used to notify corresponding activity about override configuration change and make
+ * sure that all resources are set correctly before updating the ViewRootImpl's internal state.
+ */
+ private ActivityConfigCallback mActivityConfigCallback;
+
+ /**
+ * Used when configuration change first updates the config of corresponding activity.
+ * In that case we receive a call back from {@link ActivityThread} and this flag is used to
+ * preserve the initial value.
+ *
+ * @see #performConfigurationChange(Configuration, Configuration, boolean, int)
+ */
+ private boolean mForceNextConfigUpdate;
/**
* Signals that compatibility booleans have been initialized according to
@@ -344,8 +383,12 @@
private WindowInsets mLastWindowInsets;
- final Configuration mLastConfiguration = new Configuration();
- final Configuration mPendingConfiguration = new Configuration();
+ /** Last applied configuration obtained from resources. */
+ private final Configuration mLastConfigurationFromResources = new Configuration();
+ /** Last configuration reported from WM or via {@link #MSG_UPDATE_CONFIGURATION}. */
+ private final MergedConfiguration mLastReportedMergedConfiguration = new MergedConfiguration();
+ /** Configurations waiting to be applied. */
+ private final MergedConfiguration mPendingMergedConfiguration = new MergedConfiguration();
boolean mScrollMayChange;
@SoftInputModeFlags
@@ -464,7 +507,7 @@
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
if (!sCompatibilityDone) {
- sAlwaysAssignFocus = mTargetSdkVersion < Build.VERSION_CODES.O;
+ sAlwaysAssignFocus = true;
sCompatibilityDone = true;
}
@@ -480,12 +523,18 @@
}
}
- public static void addConfigCallback(ComponentCallbacks callback) {
+ /** Add static config callback to be notified about global config changes. */
+ public static void addConfigCallback(ConfigChangedCallback callback) {
synchronized (sConfigCallbacks) {
sConfigCallbacks.add(callback);
}
}
+ /** Add activity config callback to be notified about override config changes. */
+ public void setActivityConfigCallback(ActivityConfigCallback callback) {
+ mActivityConfigCallback = callback;
+ }
+
public void addWindowCallbacks(WindowCallbacks callback) {
if (USE_MT_RENDERER) {
synchronized (mWindowCallbacks) {
@@ -1558,6 +1607,7 @@
mFullRedrawNeeded = true;
mLayoutRequested = true;
+ final Configuration config = mContext.getResources().getConfiguration();
if (shouldUseDisplaySize(lp)) {
// NOTE -- system code, won't try to do compat mode.
Point size = new Point();
@@ -1565,7 +1615,6 @@
desiredWindowWidth = size.x;
desiredWindowHeight = size.y;
} else {
- Configuration config = mContext.getResources().getConfiguration();
desiredWindowWidth = dipToPx(config.screenWidthDp);
desiredWindowHeight = dipToPx(config.screenHeightDp);
}
@@ -1577,11 +1626,11 @@
mAttachInfo.mHasWindowFocus = false;
mAttachInfo.mWindowVisibility = viewVisibility;
mAttachInfo.mRecomputeGlobalAttributes = false;
- mLastConfiguration.setTo(host.getResources().getConfiguration());
+ mLastConfigurationFromResources.setTo(config);
mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
// Set the layout direction if it has not been set before (inherit is the default)
if (mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
- host.setLayoutDirection(mLastConfiguration.getLayoutDirection());
+ host.setLayoutDirection(config.getLayoutDirection());
}
host.dispatchAttachedToWindow(mAttachInfo, 0);
mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(true);
@@ -1826,11 +1875,14 @@
+ " outsets=" + mPendingOutsets.toShortString()
+ " surface=" + mSurface);
- if (mPendingConfiguration.seq != 0) {
+ final Configuration pendingMergedConfig =
+ mPendingMergedConfiguration.getMergedConfiguration();
+ if (pendingMergedConfig.seq != 0) {
if (DEBUG_CONFIGURATION) Log.v(mTag, "Visible with new config: "
- + mPendingConfiguration);
- updateConfiguration(new Configuration(mPendingConfiguration), !mFirst);
- mPendingConfiguration.seq = 0;
+ + pendingMergedConfig);
+ performConfigurationChange(mPendingMergedConfiguration, !mFirst,
+ INVALID_DISPLAY /* same display */);
+ pendingMergedConfig.seq = 0;
updatedConfiguration = true;
}
@@ -3388,43 +3440,82 @@
unscheduleTraversals();
}
- void updateConfiguration(Configuration config, boolean force) {
- if (DEBUG_CONFIGURATION) Log.v(mTag,
- "Applying new config to window "
- + mWindowAttributes.getTitle()
- + ": " + config);
+ /**
+ * Notifies all callbacks that configuration and/or display has changed and updates internal
+ * state.
+ * @param mergedConfiguration New global and override config in {@link MergedConfiguration}
+ * container.
+ * @param force Flag indicating if we should force apply the config.
+ * @param newDisplayId Id of new display if moved, {@link Display#INVALID_DISPLAY} if not
+ * changed.
+ */
+ private void performConfigurationChange(MergedConfiguration mergedConfiguration, boolean force,
+ int newDisplayId) {
+ if (mergedConfiguration == null) {
+ throw new IllegalArgumentException("No merged config provided.");
+ }
- CompatibilityInfo ci = mDisplay.getDisplayAdjustments().getCompatibilityInfo();
+ Configuration globalConfig = mergedConfiguration.getGlobalConfiguration();
+ final Configuration overrideConfig = mergedConfiguration.getOverrideConfiguration();
+ if (DEBUG_CONFIGURATION) Log.v(mTag,
+ "Applying new config to window " + mWindowAttributes.getTitle()
+ + ", globalConfig: " + globalConfig
+ + ", overrideConfig: " + overrideConfig);
+
+ final CompatibilityInfo ci = mDisplay.getDisplayAdjustments().getCompatibilityInfo();
if (!ci.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) {
- config = new Configuration(config);
- ci.applyToConfiguration(mNoncompatDensity, config);
+ globalConfig = new Configuration(globalConfig);
+ ci.applyToConfiguration(mNoncompatDensity, globalConfig);
}
synchronized (sConfigCallbacks) {
for (int i=sConfigCallbacks.size()-1; i>=0; i--) {
- sConfigCallbacks.get(i).onConfigurationChanged(config);
+ sConfigCallbacks.get(i).onConfigurationChanged(globalConfig);
}
}
- if (mView != null) {
- // At this point the resources have been updated to
- // have the most recent config, whatever that is. Use
- // the one in them which may be newer.
- final Resources localResources = mView.getResources();
- config = localResources.getConfiguration();
- if (force || mLastConfiguration.diff(config) != 0) {
- // Update the display with new DisplayAdjustments.
- mDisplay = ResourcesManager.getInstance().getAdjustedDisplay(
- mDisplay.getDisplayId(), localResources);
- final int lastLayoutDirection = mLastConfiguration.getLayoutDirection();
- final int currentLayoutDirection = config.getLayoutDirection();
- mLastConfiguration.setTo(config);
- if (lastLayoutDirection != currentLayoutDirection &&
- mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
- mView.setLayoutDirection(currentLayoutDirection);
- }
- mView.dispatchConfigurationChanged(config);
+ mLastReportedMergedConfiguration.setConfiguration(globalConfig, overrideConfig);
+
+ mForceNextConfigUpdate = force;
+ if (mActivityConfigCallback != null) {
+ // An activity callback is set - notify it about override configuration update.
+ // This basically initiates a round trip to ActivityThread and back, which will ensure
+ // that corresponding activity and resources are updated before updating inner state of
+ // ViewRootImpl. Eventually it will call #updateConfiguration().
+ mActivityConfigCallback.onConfigurationChanged(overrideConfig, newDisplayId);
+ } else {
+ // There is no activity callback - update the configuration right away.
+ updateConfiguration();
+ }
+ mForceNextConfigUpdate = false;
+ }
+
+ /**
+ * Update display and views if last applied merged configuration changed.
+ */
+ public void updateConfiguration() {
+ if (mView == null) {
+ return;
+ }
+
+ // At this point the resources have been updated to
+ // have the most recent config, whatever that is. Use
+ // the one in them which may be newer.
+ final Resources localResources = mView.getResources();
+ final Configuration config = localResources.getConfiguration();
+ if (mForceNextConfigUpdate || mLastConfigurationFromResources.diff(config) != 0) {
+ // Update the display with new DisplayAdjustments.
+ mDisplay = ResourcesManager.getInstance().getAdjustedDisplay(
+ mDisplay.getDisplayId(), localResources);
+
+ final int lastLayoutDirection = mLastConfigurationFromResources.getLayoutDirection();
+ final int currentLayoutDirection = config.getLayoutDirection();
+ mLastConfigurationFromResources.setTo(config);
+ if (lastLayoutDirection != currentLayoutDirection
+ && mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
+ mView.setLayoutDirection(currentLayoutDirection);
}
+ mView.dispatchConfigurationChanged(config);
}
}
@@ -3582,13 +3673,16 @@
if (mAdded) {
SomeArgs args = (SomeArgs) msg.obj;
- if (mDisplay.getDisplayId() != args.argi3) {
- onMovedToDisplay(args.argi3);
+ final int displayId = args.argi3;
+ final boolean displayChanged = mDisplay.getDisplayId() != displayId;
+ if (displayChanged) {
+ onMovedToDisplay(displayId);
}
- Configuration config = (Configuration) args.arg4;
- if (config != null) {
- updateConfiguration(config, false);
+ final MergedConfiguration mergedConfiguration = (MergedConfiguration) args.arg4;
+ if (mergedConfiguration != null) {
+ performConfigurationChange(mergedConfiguration, false /* force */,
+ displayChanged ? displayId : INVALID_DISPLAY /* same display */);
}
final boolean framesChanged = !mWinFrame.equals(args.arg1)
@@ -3759,11 +3853,19 @@
handleDispatchSystemUiVisibilityChanged((SystemUiVisibilityInfo) msg.obj);
} break;
case MSG_UPDATE_CONFIGURATION: {
- Configuration config = (Configuration)msg.obj;
- if (config.isOtherSeqNewer(mLastConfiguration)) {
- config = mLastConfiguration;
+ Configuration config = (Configuration) msg.obj;
+ if (config.isOtherSeqNewer(
+ mLastReportedMergedConfiguration.getMergedConfiguration())) {
+ // If we already have a newer merged config applied - use its global part.
+ config = mLastReportedMergedConfiguration.getGlobalConfiguration();
}
- updateConfiguration(config, false);
+
+ // Use the newer global config and last reported override config.
+ mPendingMergedConfiguration.setConfiguration(config,
+ mLastReportedMergedConfiguration.getOverrideConfiguration());
+
+ performConfigurationChange(mPendingMergedConfiguration, false /* force */,
+ INVALID_DISPLAY /* same display */);
} break;
case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST: {
setAccessibilityFocus(null, null);
@@ -5902,7 +6004,7 @@
if (params != null) {
if (DBG) Log.d(mTag, "WindowLayout in layoutWindow:" + params);
}
- mPendingConfiguration.seq = 0;
+ mPendingMergedConfiguration.getMergedConfiguration().seq = 0;
//Log.d(mTag, ">>>>>> CALLING relayout");
if (params != null && mOrigWindowType != params.type) {
// For compatibility with old apps, don't crash here.
@@ -5918,8 +6020,8 @@
(int) (mView.getMeasuredHeight() * appScale + 0.5f),
viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
- mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingConfiguration,
- mSurface);
+ mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame,
+ mPendingMergedConfiguration, mSurface);
mPendingAlwaysConsumeNavBar =
(relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR) != 0;
@@ -6199,9 +6301,9 @@
}
}
- public void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
+ private void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
- Configuration newConfig, Rect backDropFrame, boolean forceLayout,
+ MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout,
boolean alwaysConsumeNavBar, int displayId) {
if (DEBUG_LAYOUT) Log.v(mTag, "Resizing " + this + ": frame=" + frame.toShortString()
+ " contentInsets=" + contentInsets.toShortString()
@@ -6233,7 +6335,8 @@
args.arg1 = sameProcessCall ? new Rect(frame) : frame;
args.arg2 = sameProcessCall ? new Rect(contentInsets) : contentInsets;
args.arg3 = sameProcessCall ? new Rect(visibleInsets) : visibleInsets;
- args.arg4 = sameProcessCall && newConfig != null ? new Configuration(newConfig) : newConfig;
+ args.arg4 = sameProcessCall && mergedConfiguration != null
+ ? new MergedConfiguration(mergedConfiguration) : null;
args.arg5 = sameProcessCall ? new Rect(overscanInsets) : overscanInsets;
args.arg6 = sameProcessCall ? new Rect(stableInsets) : stableInsets;
args.arg7 = sameProcessCall ? new Rect(outsets) : outsets;
@@ -7243,13 +7346,13 @@
@Override
public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
- Configuration newConfig, Rect backDropFrame, boolean forceLayout,
+ MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout,
boolean alwaysConsumeNavBar, int displayId) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
viewAncestor.dispatchResized(frame, overscanInsets, contentInsets,
- visibleInsets, stableInsets, outsets, reportDraw, newConfig, backDropFrame,
- forceLayout, alwaysConsumeNavBar, displayId);
+ visibleInsets, stableInsets, outsets, reportDraw, mergedConfiguration,
+ backDropFrame, forceLayout, alwaysConsumeNavBar, displayId);
}
}
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 38c7738..4168756 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -275,13 +275,12 @@
* {@link #addChildCount(int)} and {@link #setChildCount(int)}.
* @param virtualId an opaque ID to the Android System (although it could be meaningful to the
* {@link View} creating the {@link ViewStructure}), but it's the same id used on
- * {@link View#autofillVirtual(int, AutofillValue)}.
+ * {@link View#autofill(int, AutofillValue)}.
* @param flags currently {@code 0}.
*
* @return Returns an fresh {@link ViewStructure} ready to be filled in.
*/
- // TODO(b/33197203, b/33802548): add CTS/unit test
- public abstract ViewStructure newChildForAutofill(int index, int virtualId, int flags);
+ public abstract ViewStructure newChild(int index, int virtualId, int flags);
/**
* Like {@link #newChild}, but allows the caller to asynchronously populate the returned
@@ -294,7 +293,7 @@
public abstract ViewStructure asyncNewChild(int index);
/**
- * Like {@link #newChildForAutofill(int, int, int)}, but allows the caller to asynchronously
+ * Like {@link #newChild(int, int, int)}, but allows the caller to asynchronously
* populate the returned child.
*
* <p>It can transfer the returned {@link ViewStructure} to another thread for it to build its
@@ -307,13 +306,12 @@
* {@link #addChildCount(int)} and {@link #setChildCount(int)}.
* @param virtualId an opaque ID to the Android System (although it could be meaningful to the
* {@link View} creating the {@link ViewStructure}), but it's the same id used on
- * {@link View#autofillVirtual(int, AutofillValue)}.
+ * {@link View#autofill(int, AutofillValue)}.
* @param flags currently {@code 0}.
*
* @return Returns an fresh {@link ViewStructure} ready to be filled in.
*/
- // TODO(b/33197203, b/33802548): add CTS/unit test
- public abstract ViewStructure asyncNewChildForAutofill(int index, int virtualId, int flags);
+ public abstract ViewStructure asyncNewChild(int index, int virtualId, int flags);
/**
* Sets the {@link View#getAutofillType()} that can be used to autofill this node.
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index f036b9c..9ed6371 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -83,7 +83,7 @@
/** @hide */ public static final int FLAG_VIEW_EXITED = 0x20000000;
/** @hide */ public static final int FLAG_VALUE_CHANGED = 0x10000000;
- private final Rect mTempRect = new Rect();
+ @NonNull private final Rect mTempRect = new Rect();
private final IAutoFillManager mService;
private IAutoFillManagerClient mServiceClient;
@@ -196,6 +196,9 @@
ensureServiceClientAddedIfNeeded();
if (!mEnabled) {
+ if (mCallback != null) {
+ mCallback.onAutofillEvent(view, AutofillCallback.EVENT_INPUT_UNAVAILABLE);
+ }
return;
}
@@ -236,11 +239,13 @@
* @param childId id identifying the virtual child inside the view.
* @param bounds child boundaries, relative to the top window.
*/
- public void notifyVirtualViewEntered(@NonNull View view, int childId,
- @NonNull Rect bounds) {
+ public void notifyViewEntered(@NonNull View view, int childId, @NonNull Rect bounds) {
ensureServiceClientAddedIfNeeded();
if (!mEnabled) {
+ if (mCallback != null) {
+ mCallback.onAutofillEvent(view, childId, AutofillCallback.EVENT_INPUT_UNAVAILABLE);
+ }
return;
}
@@ -261,7 +266,7 @@
* @param view the {@link View} whose descendant is the virtual view.
* @param childId id identifying the virtual child inside the view.
*/
- public void notifyVirtualViewExited(@NonNull View view, int childId) {
+ public void notifyViewExited(@NonNull View view, int childId) {
ensureServiceClientAddedIfNeeded();
if (mEnabled && mHasSession) {
@@ -295,7 +300,7 @@
* @param childId id identifying the virtual child inside the parent view.
* @param value new value of the child.
*/
- public void notifyVirtualValueChanged(View view, int childId, AutofillValue value) {
+ public void notifyValueChanged(View view, int childId, AutofillValue value) {
if (!mEnabled || !mHasSession) {
return;
}
@@ -371,8 +376,8 @@
return new AutofillId(parent.getAccessibilityViewId(), childId);
}
- private void startSession(AutofillId id, IBinder windowToken, Rect bounds,
- AutofillValue value, int flags) {
+ private void startSession(@NonNull AutofillId id, @NonNull IBinder windowToken,
+ @NonNull Rect bounds, @NonNull AutofillValue value, int flags) {
if (DEBUG) {
Log.d(TAG, "startSession(): id=" + id + ", bounds=" + bounds + ", value=" + value
+ ", flags=" + flags);
@@ -381,8 +386,8 @@
try {
mService.startSession(mContext.getActivityToken(), windowToken,
mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
- mCallback != null, flags);
- final AutofillClient client = getClient();
+ mCallback != null, flags, mContext.getOpPackageName());
+ AutofillClient client = getClient();
if (client != null) {
client.resetableStateAvailable();
}
@@ -503,7 +508,7 @@
return;
}
if (id.isVirtual()) {
- mCallback.onAutofillEventVirtual(view, id.getVirtualChildId(), event);
+ mCallback.onAutofillEvent(view, id.getVirtualChildId(), event);
} else {
mCallback.onAutofillEvent(view, event);
}
@@ -539,13 +544,23 @@
public static final int EVENT_INPUT_HIDDEN = 2;
/**
+ * The auto-fill input UI affordance associated with the view won't be shown because
+ * autofill is not available.
+ *
+ * <p>If the view provides its own auto-complete UI affordance but was not displaying it
+ * to avoid flickering, it could shown it upon receiving this event.
+ */
+ public static final int EVENT_INPUT_UNAVAILABLE = 3;
+
+ /**
* 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) {}
+ public void onAutofillEvent(@NonNull View view, @AutofillEventType int event) {
+ }
/**
* Called after a change in the autofill state associated with a virtual view.
@@ -555,8 +570,8 @@
*
* @param event currently either {@link #EVENT_INPUT_SHOWN} or {@link #EVENT_INPUT_HIDDEN}.
*/
- public void onAutofillEventVirtual(@NonNull View view, int childId,
- @AutofillEventType int event) {}
+ public void onAutofillEvent(@NonNull View view, int childId, @AutofillEventType int event) {
+ }
}
private static final class AutofillManagerClient extends IAutoFillManagerClient.Stub {
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index 85b05e5..97210cc 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -32,7 +32,7 @@
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,
- boolean hasCallback, int flags);
+ boolean hasCallback, int flags, String packageName);
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);
diff --git a/core/java/android/widget/AbsSpinner.java b/core/java/android/widget/AbsSpinner.java
index 020e80a..fae5742 100644
--- a/core/java/android/widget/AbsSpinner.java
+++ b/core/java/android/widget/AbsSpinner.java
@@ -514,14 +514,15 @@
}
@Override
- public void autofill(AutofillValue value) {
- if (!isEnabled()) return;
+ public boolean autofill(AutofillValue value) {
+ if (!isEnabled()) return false;
if (value.isList()) {
setSelection(value.getListValue());
} else {
Log.w(LOG_TAG, value + " could not be autofilled into " + this);
}
+ return true;
}
@Override
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 899a824..9dc61ab 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -584,14 +584,16 @@
}
@Override
- public void autofill(AutofillValue value) {
- if (!isEnabled()) return;
+ public boolean autofill(AutofillValue value) {
+ if (!isEnabled()) return false;
if (value.isToggle()) {
setChecked(value.getToggleValue());
} else {
Log.w(LOG_TAG, value + " could not be autofilled into " + this);
}
+
+ return true;
}
@Override
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index f63573f..7d04f35 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -775,14 +775,16 @@
}
@Override
- public void autofill(AutofillValue value) {
- if (!isEnabled()) return;
+ public boolean autofill(AutofillValue value) {
+ if (!isEnabled()) return false;
if (value.isDate()) {
mDelegate.updateDate(value.getDateValue());
} else {
Log.w(LOG_TAG, value + " could not be autofilled into " + this);
}
+
+ return true;
}
@Override
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index 5e8279a..a7574c7 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -426,23 +426,24 @@
}
@Override
- public void autofill(AutofillValue value) {
- if (!isEnabled()) return;
+ public boolean autofill(AutofillValue value) {
+ if (!isEnabled()) return false;
int index;
if (value.isList()) {
index = value.getListValue();
} else {
Log.w(LOG_TAG, value + " could not be autofilled into " + this);
- return;
+ return false;
}
final View child = getChildAt(index);
if (child == null) {
Log.w(VIEW_LOG_TAG, "RadioGroup.autoFill(): no child with index " + index);
- return;
+ return false;
}
check(child.getId());
+ return true;
}
@Override
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index c5c317d..26edc43 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -10028,14 +10028,17 @@
}
@Override
- public void autofill(AutofillValue value) {
+ public boolean autofill(AutofillValue value) {
if (value.isText()) {
if (isTextEditable()) {
setText(value.getTextValue(), mBufferType, true, 0);
+ return true;
}
} else {
Log.w(LOG_TAG, value + " could not be autofilled into " + this);
}
+
+ return false;
}
@Override
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index cfa78b5..1e97e3b 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -530,14 +530,16 @@
}
@Override
- public void autofill(AutofillValue value) {
- if (!isEnabled()) return;
+ public boolean autofill(AutofillValue value) {
+ if (!isEnabled()) return false;
if (value.isDate()) {
mDelegate.setDate(value.getDateValue());
} else {
Log.w(LOG_TAG, value + " could not be autofilled into " + this);
}
+
+ return true;
}
@Override
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index 96468ab..0a9faa1 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -142,6 +142,21 @@
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from wrapper");
}
- RuntimeInit.applicationInit(targetSdkVersion, argv, null);
+ // Check whether the first argument is a "-cp" in argv, and assume the next argument is the
+ // classpath. If found, create a PathClassLoader and use it for applicationInit.
+ ClassLoader classLoader = null;
+ if (argv != null && argv.length > 2 && argv[0].equals("-cp")) {
+ classLoader = ZygoteInit.createPathClassLoader(argv[1], targetSdkVersion);
+
+ // Install this classloader as the context classloader, too.
+ Thread.currentThread().setContextClassLoader(classLoader);
+
+ // Remove the classpath from the arguments.
+ String removedArgs[] = new String[argv.length - 2];
+ System.arraycopy(argv, 2, removedArgs, 0, argv.length - 2);
+ argv = removedArgs;
+ }
+
+ RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 76d8af1..b2a2fec 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -468,7 +468,8 @@
String[] amendedArgs = new String[args.length + 2];
amendedArgs[0] = "-cp";
amendedArgs[1] = systemServerClasspath;
- System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
+ System.arraycopy(args, 0, amendedArgs, 2, args.length);
+ args = amendedArgs;
}
WrapperInit.execApplication(parsedArgs.invokeWith,
@@ -477,8 +478,7 @@
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
- cl = createSystemServerClassLoader(systemServerClasspath,
- parsedArgs.targetSdkVersion);
+ cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}
@@ -493,15 +493,14 @@
}
/**
- * Creates a PathClassLoader for the system server. It also creates
- * a shared namespace associated with the classloader to let it access
- * platform-private native libraries.
+ * Creates a PathClassLoader for the given class path that is associated with a shared
+ * namespace, i.e., this classloader can access platform-private native libraries. The
+ * classloader will use java.library.path as the native library path.
*/
- private static PathClassLoader createSystemServerClassLoader(String systemServerClasspath,
- int targetSdkVersion) {
+ static PathClassLoader createPathClassLoader(String classPath, int targetSdkVersion) {
String libraryPath = System.getProperty("java.library.path");
- return PathClassLoaderFactory.createClassLoader(systemServerClasspath,
+ return PathClassLoaderFactory.createClassLoader(classPath,
libraryPath,
libraryPath,
ClassLoader.getSystemClassLoader(),
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index ce51dc4..361fd3da 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -16,12 +16,12 @@
package com.android.internal.view;
-import android.content.res.Configuration;
import android.graphics.Rect;
import android.hardware.input.InputManager;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
+import android.util.MergedConfiguration;
import android.view.DragEvent;
import android.view.IWindow;
import android.view.IWindowSession;
@@ -39,8 +39,9 @@
@Override
public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets,
- Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig,
- Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeNavBar, int displayId) {
+ Rect stableInsets, Rect outsets, boolean reportDraw,
+ MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout,
+ boolean alwaysConsumeNavBar, int displayId) {
if (reportDraw) {
try {
mSession.finishDrawing(this);
diff --git a/core/java/com/android/internal/widget/ImageFloatingTextView.java b/core/java/com/android/internal/widget/ImageFloatingTextView.java
index 80207ee..e86932c 100644
--- a/core/java/com/android/internal/widget/ImageFloatingTextView.java
+++ b/core/java/com/android/internal/widget/ImageFloatingTextView.java
@@ -115,6 +115,7 @@
// Lets calculate how many lines the given measurement allows us.
int availableHeight = height - mPaddingTop - mPaddingBottom;
int maxLines = availableHeight / getLineHeight();
+ maxLines = Math.max(1, maxLines);
if (getMaxLines() > 0) {
maxLines = Math.min(getMaxLines(), maxLines);
}
diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java
index b259ad1..1104318 100644
--- a/core/java/com/android/internal/widget/MessagingLinearLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java
@@ -16,8 +16,6 @@
package com.android.internal.widget;
-import com.android.internal.R;
-
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.TypedArray;
@@ -28,6 +26,8 @@
import android.view.ViewGroup;
import android.widget.RemoteViews;
+import com.android.internal.R;
+
/**
* A custom-built layout for the Notification.MessagingStyle.
*
@@ -119,23 +119,30 @@
}
final View child = getChildAt(i);
LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams();
-
+ ImageFloatingTextView textChild = null;
if (child instanceof ImageFloatingTextView) {
// Pretend we need the image padding for all views, we don't know which
// one will end up needing to do this (might end up not using all the space,
// but calculating this exactly would be more expensive).
- ((ImageFloatingTextView) child).setNumIndentLines(
- mIndentLines == 2 ? 3 : mIndentLines);
+ textChild = (ImageFloatingTextView) child;
+ textChild.setNumIndentLines(mIndentLines == 2 ? 3 : mIndentLines);
}
- measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
+ int spacing = first ? 0 : mSpacing;
+ measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, totalHeight
+ - mPaddingTop - mPaddingBottom + spacing);
final int childHeight = child.getMeasuredHeight();
int newHeight = Math.max(totalHeight, totalHeight + childHeight + lp.topMargin +
- lp.bottomMargin + (first ? 0 : mSpacing));
+ lp.bottomMargin + spacing);
first = false;
+ boolean measuredTooSmall = false;
+ if (textChild != null) {
+ measuredTooSmall = childHeight < textChild.getLayout().getHeight()
+ + textChild.getPaddingTop() + textChild.getPaddingBottom();
+ }
- if (newHeight <= targetHeight) {
+ if (newHeight <= targetHeight && !measuredTooSmall) {
totalHeight = newHeight;
lp.hide = false;
} else {
@@ -168,7 +175,15 @@
}
boolean changed = textChild.setNumIndentLines(Math.max(0, imageLines));
if (changed || !recalculateVisibility) {
- measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
+ final int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
+ mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin,
+ lp.width);
+ // we want to measure it at most as high as it is currently, otherwise we'll
+ // drop later lines
+ final int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
+ targetHeight - child.getMeasuredHeight(), lp.height);
+
+ child.measure(childWidthMeasureSpec, childHeightMeasureSpec);;
}
imageLines -= textChild.getLineCount();
}
diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp
index 79439e2..5553a3e 100644
--- a/core/jni/android/graphics/ColorFilter.cpp
+++ b/core/jni/android/graphics/ColorFilter.cpp
@@ -30,7 +30,7 @@
class SkColorFilterGlue {
public:
- static void finalizer(JNIEnv* env, jobject clazz, jlong skFilterHandle) {
+ static void SafeUnref(JNIEnv* env, jobject clazz, jlong skFilterHandle) {
SkColorFilter* filter = reinterpret_cast<SkColorFilter *>(skFilterHandle);
SkSafeUnref(filter);
}
@@ -57,19 +57,19 @@
};
static const JNINativeMethod colorfilter_methods[] = {
- {"destroyFilter", "(J)V", (void*) SkColorFilterGlue::finalizer}
+ {"nSafeUnref", "(J)V", (void*) SkColorFilterGlue::SafeUnref}
};
static const JNINativeMethod porterduff_methods[] = {
- { "native_CreatePorterDuffFilter", "(II)J", (void*) SkColorFilterGlue::CreatePorterDuffFilter },
+ { "native_CreatePorterDuffFilter", "(II)J", (void*) SkColorFilterGlue::CreatePorterDuffFilter },
};
static const JNINativeMethod lighting_methods[] = {
- { "native_CreateLightingFilter", "(II)J", (void*) SkColorFilterGlue::CreateLightingFilter },
+ { "native_CreateLightingFilter", "(II)J", (void*) SkColorFilterGlue::CreateLightingFilter },
};
static const JNINativeMethod colormatrix_methods[] = {
- { "nativeColorMatrixFilter", "([F)J", (void*) SkColorFilterGlue::CreateColorMatrixFilter },
+ { "nativeColorMatrixFilter", "([F)J", (void*) SkColorFilterGlue::CreateColorMatrixFilter },
};
int register_android_graphics_ColorFilter(JNIEnv* env) {
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index 1bd2333..678041f 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -404,6 +404,11 @@
signalExceptionForError(env, err);
}
+static void JHwParcel_native_release(
+ JNIEnv *env, jobject thiz) {
+ JHwParcel::GetNativeContext(env, thiz)->setParcel(NULL, false /* assumeOwnership */);
+}
+
static void JHwParcel_native_releaseTemporaryStorage(
JNIEnv *env, jobject thiz) {
JHwParcel::GetNativeContext(env, thiz)->getStorage()->release(env);
@@ -955,6 +960,10 @@
{ "writeBuffer", "(L" PACKAGE_PATH "/HwBlob;)V",
(void *)JHwParcel_native_writeBuffer },
+
+ { "release", "()V",
+ (void *)JHwParcel_native_release },
+
};
namespace android {
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 9660de4..956b724 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -26,7 +26,9 @@
#include <sys/un.h>
#include <unistd.h>
+#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
#include <android-base/strings.h>
// Static whitelist of open paths that the zygote is allowed to keep open.
@@ -65,9 +67,10 @@
return true;
}
- static const std::string kFrameworksPrefix = "/system/framework/";
- static const std::string kJarSuffix = ".jar";
- if (StartsWith(path, kFrameworksPrefix) && EndsWith(path, kJarSuffix)) {
+ static const char* kFrameworksPrefix = "/system/framework/";
+ static const char* kJarSuffix = ".jar";
+ if (android::base::StartsWith(path, kFrameworksPrefix)
+ && android::base::EndsWith(path, kJarSuffix)) {
return true;
}
@@ -79,28 +82,31 @@
// /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap
// /data/resource-cache/system@vendor@overlay-subdir@pg@framework-res.apk@idmap
// See AssetManager.cpp for more details on overlay-subdir.
- static const std::string kOverlayDir = "/system/vendor/overlay/";
- static const std::string kVendorOverlayDir = "/vendor/overlay";
- static const std::string kOverlaySubdir = "/system/vendor/overlay-subdir/";
- static const std::string kApkSuffix = ".apk";
+ static const char* kOverlayDir = "/system/vendor/overlay/";
+ static const char* kVendorOverlayDir = "/vendor/overlay";
+ static const char* kOverlaySubdir = "/system/vendor/overlay-subdir/";
+ static const char* kApkSuffix = ".apk";
- if ((StartsWith(path, kOverlayDir) || StartsWith(path, kOverlaySubdir)
- || StartsWith(path, kVendorOverlayDir))
- && EndsWith(path, kApkSuffix)
+ if ((android::base::StartsWith(path, kOverlayDir)
+ || android::base::StartsWith(path, kOverlaySubdir)
+ || android::base::StartsWith(path, kVendorOverlayDir))
+ && android::base::EndsWith(path, kApkSuffix)
&& path.find("/../") == std::string::npos) {
return true;
}
- static const std::string kOverlayIdmapPrefix = "/data/resource-cache/";
- static const std::string kOverlayIdmapSuffix = ".apk@idmap";
- if (StartsWith(path, kOverlayIdmapPrefix) && EndsWith(path, kOverlayIdmapSuffix)
+ static const char* kOverlayIdmapPrefix = "/data/resource-cache/";
+ static const char* kOverlayIdmapSuffix = ".apk@idmap";
+ if (android::base::StartsWith(path, kOverlayIdmapPrefix)
+ && android::base::EndsWith(path, kOverlayIdmapSuffix)
&& path.find("/../") == std::string::npos) {
return true;
}
// All regular files that are placed under this path are whitelisted automatically.
- static const std::string kZygoteWhitelistPath = "/vendor/zygote_whitelist/";
- if (StartsWith(path, kZygoteWhitelistPath) && path.find("/../") == std::string::npos) {
+ static const char* kZygoteWhitelistPath = "/vendor/zygote_whitelist/";
+ if (android::base::StartsWith(path, kZygoteWhitelistPath)
+ && path.find("/../") == std::string::npos) {
return true;
}
@@ -111,24 +117,6 @@
: whitelist_() {
}
-// TODO: Call android::base::StartsWith instead of copying the code here.
-// static
-bool FileDescriptorWhitelist::StartsWith(const std::string& str,
- const std::string& prefix) {
- return str.compare(0, prefix.size(), prefix) == 0;
-}
-
-// TODO: Call android::base::EndsWith instead of copying the code here.
-// static
-bool FileDescriptorWhitelist::EndsWith(const std::string& str,
- const std::string& suffix) {
- if (suffix.size() > str.size()) {
- return false;
- }
-
- return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
-}
-
FileDescriptorWhitelist* FileDescriptorWhitelist::instance_ = nullptr;
// static
@@ -174,7 +162,8 @@
}
std::string file_path;
- if (!Readlink(fd, &file_path)) {
+ const std::string fd_path = android::base::StringPrintf("/proc/self/fd/%d", fd);
+ if (!android::base::Readlink(fd_path, &file_path)) {
return NULL;
}
@@ -299,30 +288,6 @@
is_sock(false) {
}
-// TODO: Call android::base::Readlink instead of copying the code here.
-// static
-bool FileDescriptorInfo::Readlink(const int fd, std::string* result) {
- char path[64];
- snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
-
- // Code copied from android::base::Readlink starts here :
-
- // Annoyingly, the readlink system call returns EINVAL for a zero-sized buffer,
- // and truncates to whatever size you do supply, so it can't be used to query.
- // We could call lstat first, but that would introduce a race condition that
- // we couldn't detect.
- // ext2 and ext4 both have PAGE_SIZE limitations, so we assume that here.
- char buf[4096];
- ssize_t len = readlink(path, buf, sizeof(buf));
- if (len == -1) {
- PLOG(ERROR) << "Readlink on " << fd << " failed.";
- return false;
- }
-
- result->assign(buf, len);
- return true;
-}
-
// static
bool FileDescriptorInfo::GetSocketName(const int fd, std::string* result) {
sockaddr_storage ss;
diff --git a/core/jni/fd_utils.h b/core/jni/fd_utils.h
index 03298c3..a39e387 100644
--- a/core/jni/fd_utils.h
+++ b/core/jni/fd_utils.h
@@ -59,10 +59,6 @@
private:
FileDescriptorWhitelist();
- static bool StartsWith(const std::string& str, const std::string& prefix);
-
- static bool EndsWith(const std::string& str, const std::string& suffix);
-
static FileDescriptorWhitelist* instance_;
std::vector<std::string> whitelist_;
@@ -99,8 +95,6 @@
FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
int fd_flags, int fs_flags, off_t offset);
- static bool Readlink(const int fd, std::string* result);
-
// Returns the locally-bound name of the socket |fd|. Returns true
// iff. all of the following hold :
//
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c991f22..58e4051 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3593,7 +3593,7 @@
android:permission="android.permission.BIND_JOB_SERVICE" >
</service>
- <service android:name="com.android.server.BackgroundDexOptJobService"
+ <service android:name="com.android.server.pm.BackgroundDexOptService"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE">
</service>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 6e0d9dc..385f256 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1386,6 +1386,9 @@
<!-- Boolean indicating if current platform supports BLE peripheral mode -->
<bool name="config_bluetooth_le_peripheral_mode_supported">false</bool>
+ <!-- Boolean indicating if current platform supports HFP inband ringing -->
+ <bool name="config_bluetooth_hfp_inband_ringing_support">false</bool>
+
<!-- Max number of scan filters supported by blutooth controller. 0 if the
device does not support hardware scan filters-->
<integer translatable="false" name="config_bluetooth_max_scan_filters">0</integer>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 1ed069b..d1c14e9 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4567,22 +4567,25 @@
<!-- Accessibility string used for describing the button in time picker that changes the dialog to circular clock mode. [CHAR LIMIT=NONE] -->
<string name="time_picker_radial_mode_description">Switch to clock mode for the time input.</string>
- <!-- Title for the auto-fill save dialog shown when the the contents of the activity can be saved
- by an auto-fill service, but the service does not know what the activity represents [CHAR LIMIT=NONE] -->
+ <!-- Accessibility title for the autofill dialog used to select a list of options to autofill an activity. [CHAR LIMIT=NONE] -->
+ <string name="autofill_picker_accessibility_title">Autofill options</string>
+
+ <!-- Title for the autofill save dialog shown when the the contents of the activity can be saved
+ by an autofill service, but the service does not know what the activity represents [CHAR LIMIT=NONE] -->
<string name="autofill_save_title">Save to <xliff:g id="label" example="MyPass">%1$s</xliff:g>?</string>
- <!-- Title for the auto-fill save dialog shown when the the contents of the activity can be saved
- by an auto-fill service, and the service does knows what the activity represents (for example, credit card info) [CHAR LIMIT=NONE] -->
+ <!-- Title for the autofill save dialog shown when the the contents of the activity can be saved
+ by an autofill service, and the service does knows what the activity represents (for example, credit card info) [CHAR LIMIT=NONE] -->
<string name="autofill_save_title_with_type">Save <xliff:g id="type" example="Credit Card">%1$s</xliff:g> to <xliff:g id="label" example="MyPass">%2$s</xliff:g>?</string>
- <!-- Label for the auto-fill save button [CHAR LIMIT=NONE] -->
+ <!-- Label for the autofill save button [CHAR LIMIT=NONE] -->
<string name="autofill_save_yes">Save</string>
- <!-- Label for the auto-fill cancel button [CHAR LIMIT=NONE] -->
+ <!-- Label for the autofill cancel button [CHAR LIMIT=NONE] -->
<string name="autofill_save_no">No thanks</string>
- <!-- Label for the type of data being saved for auto-fill when it represent user credentials with a password [CHAR LIMIT=NONE] -->
+ <!-- Label for the type of data being saved for autofill when it represent user credentials with a password [CHAR LIMIT=NONE] -->
<string name="autofill_save_type_password">password</string>
- <!-- Label for the type of data being saved for auto-fill when it represent an address (street, city, etc.) [CHAR LIMIT=NONE] -->
+ <!-- Label for the type of data being saved for autofill when it represent an address (street, city, etc.) [CHAR LIMIT=NONE] -->
<string name="autofill_save_type_address">address</string>
- <!-- Label for the type of data being saved for auto-fill when it represents a credit card [CHAR LIMIT=NONE] -->
+ <!-- Label for the type of data being saved for autofill when it represents a credit card [CHAR LIMIT=NONE] -->
<string name="autofill_save_type_credit_card">credit card</string>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 07cecbc..0d4a407 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -242,6 +242,7 @@
<java-symbol type="bool" name="config_bluetooth_address_validation" />
<java-symbol type="bool" name="config_bluetooth_sco_off_call" />
<java-symbol type="bool" name="config_bluetooth_le_peripheral_mode_supported" />
+ <java-symbol type="bool" name="config_bluetooth_hfp_inband_ringing_support" />
<java-symbol type="bool" name="config_cellBroadcastAppLinks" />
<java-symbol type="bool" name="config_duplicate_port_omadm_wappush" />
<java-symbol type="bool" name="config_enableAutoPowerModes" />
@@ -2848,6 +2849,7 @@
<java-symbol type="id" name="autofill_save_yes" />
<java-symbol type="id" name="autofill_save_close" />
<java-symbol type="string" name="autofill" />
+ <java-symbol type="string" name="autofill_picker_accessibility_title " />
<java-symbol type="string" name="autofill_save_title" />
<java-symbol type="string" name="autofill_save_title_with_type" />
<java-symbol type="string" name="autofill_save_yes" />
diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk
index fba8e23..dbc9e5d 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -40,6 +40,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner conscrypt telephony-common org.apache.http.legacy
LOCAL_PACKAGE_NAME := FrameworksCoreTests
+LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_CERTIFICATE := platform
diff --git a/graphics/java/android/graphics/ColorFilter.java b/graphics/java/android/graphics/ColorFilter.java
index ac62bf4..0ca3729 100644
--- a/graphics/java/android/graphics/ColorFilter.java
+++ b/graphics/java/android/graphics/ColorFilter.java
@@ -28,21 +28,51 @@
*/
public class ColorFilter {
/**
- * Holds the pointer to the native SkColorFilter instance.
- *
- * @hide
+ * @deprecated Use subclass constructors directly instead.
*/
- public long native_instance;
+ @Deprecated
+ public ColorFilter() {}
+
+ /**
+ * Holds the pointer to the native SkColorFilter instance.
+ */
+ private long mNativeInstance;
+
+ long createNativeInstance() {
+ return 0;
+ }
+
+ void discardNativeInstance() {
+ if (mNativeInstance != 0) {
+ nSafeUnref(mNativeInstance);
+ mNativeInstance = 0;
+ }
+ }
@Override
protected void finalize() throws Throwable {
try {
- super.finalize();
+ if (mNativeInstance != 0) {
+ nSafeUnref(mNativeInstance);
+ }
+ mNativeInstance = -1;
} finally {
- destroyFilter(native_instance);
- native_instance = 0;
+ super.finalize();
}
}
- static native void destroyFilter(long native_instance);
+ /** @hide */
+ public long getNativeInstance() {
+ if (mNativeInstance == -1) {
+ throw new IllegalStateException("attempting to use a finalized ColorFilter");
+ }
+
+ if (mNativeInstance == 0) {
+ mNativeInstance = createNativeInstance();
+ }
+ return mNativeInstance;
+
+ }
+
+ static native void nSafeUnref(long native_instance);
}
diff --git a/graphics/java/android/graphics/ColorMatrix.java b/graphics/java/android/graphics/ColorMatrix.java
index 1b1849e..6299b2c 100644
--- a/graphics/java/android/graphics/ColorMatrix.java
+++ b/graphics/java/android/graphics/ColorMatrix.java
@@ -268,4 +268,21 @@
m[5] = 1; m[6] = -0.34414f; m[7] = -0.71414f;
m[10] = 1; m[11] = 1.772f; m[12] = 0;
}
+
+ @Override
+ public boolean equals(Object obj) {
+ // if (obj == this) return true; -- NaN value would mean matrix != itself
+ if (!(obj instanceof ColorMatrix)) {
+ return false;
+ }
+
+ // we don't use Arrays.equals(), since that considers NaN == NaN
+ final float[] other = ((ColorMatrix) obj).mArray;
+ for (int i = 0; i < 20; i++) {
+ if (other[i] != mArray[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
}
diff --git a/graphics/java/android/graphics/ColorMatrixColorFilter.java b/graphics/java/android/graphics/ColorMatrixColorFilter.java
index 291c8ff..61f6cc5 100644
--- a/graphics/java/android/graphics/ColorMatrixColorFilter.java
+++ b/graphics/java/android/graphics/ColorMatrixColorFilter.java
@@ -16,6 +16,9 @@
package android.graphics;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
/**
* A color filter that transforms colors through a 4x5 color matrix. This filter
* can be used to change the saturation of pixels, convert from YUV to RGB, etc.
@@ -32,9 +35,8 @@
* the filter, so changes made to the matrix after the filter
* is constructed will not be reflected in the filter.
*/
- public ColorMatrixColorFilter(ColorMatrix matrix) {
+ public ColorMatrixColorFilter(@NonNull ColorMatrix matrix) {
mMatrix.set(matrix);
- update();
}
/**
@@ -44,84 +46,76 @@
* matrix. The first 20 entries of the array are copied into
* the filter. See ColorMatrix.
*/
- public ColorMatrixColorFilter(float[] array) {
+ public ColorMatrixColorFilter(@NonNull float[] array) {
if (array.length < 20) {
throw new ArrayIndexOutOfBoundsException();
}
mMatrix.set(array);
- update();
}
/**
- * Returns the {@link ColorMatrix} used by this filter. The returned
- * value is never null. Modifying the returned matrix does not have
- * any effect until you call {@link #setColorMatrix(ColorMatrix)}.
+ * Copies the ColorMatrix from the filter into the passed ColorMatrix.
*
- * @see #setColorMatrix(ColorMatrix)
- *
- * @hide
+ * @param colorMatrix Set to the current value of the filter's ColorMatrix.
*/
- public ColorMatrix getColorMatrix() {
- return mMatrix;
+ public void getColorMatrix(ColorMatrix colorMatrix) {
+ colorMatrix.set(mMatrix);
}
/**
- * Specifies the color matrix used by this filter. If the specified
- * color matrix is null, this filter's color matrix will be reset to
- * the identity matrix.
+ * Copies the provided color matrix to be used by this filter.
+ *
+ * If the specified color matrix is null, this filter's color matrix will be reset to the
+ * identity matrix.
*
* @param matrix A {@link ColorMatrix} or null
*
- * @see #getColorMatrix()
- * @see android.graphics.ColorMatrix#reset()
- * @see #setColorMatrix(float[])
- *
- * @hide
+ * @see #getColorMatrix(ColorMatrix)
+ * @see #setColorMatrixArray(float[])
+ * @see ColorMatrix#reset()
*/
- public void setColorMatrix(ColorMatrix matrix) {
+ public void setColorMatrix(@Nullable ColorMatrix matrix) {
+ discardNativeInstance();
if (matrix == null) {
mMatrix.reset();
- } else if (matrix != mMatrix) {
+ } else {
mMatrix.set(matrix);
}
- update();
}
/**
- * Specifies the color matrix used by this filter. If the specified
- * color matrix is null, this filter's color matrix will be reset to
- * the identity matrix.
+ * Copies the provided color matrix to be used by this filter.
+ *
+ * If the specified color matrix is null, this filter's color matrix will be reset to the
+ * identity matrix.
*
* @param array Array of floats used to transform colors, treated as a 4x5
* matrix. The first 20 entries of the array are copied into
* the filter. See {@link ColorMatrix}.
*
- * @see #getColorMatrix()
- * @see android.graphics.ColorMatrix#reset()
+ * @see #getColorMatrix(ColorMatrix)
* @see #setColorMatrix(ColorMatrix)
+ * @see ColorMatrix#reset()
*
* @throws ArrayIndexOutOfBoundsException if the specified array's
* length is < 20
- *
- * @hide
*/
- public void setColorMatrix(float[] array) {
+ public void setColorMatrixArray(@Nullable float[] array) {
+ // called '...Array' so that passing null isn't ambiguous
+ discardNativeInstance();
if (array == null) {
mMatrix.reset();
} else {
if (array.length < 20) {
throw new ArrayIndexOutOfBoundsException();
}
-
mMatrix.set(array);
}
- update();
}
- private void update() {
- final float[] colorMatrix = mMatrix.getArray();
- destroyFilter(native_instance);
- native_instance = nativeColorMatrixFilter(colorMatrix);
+ @Override
+ long createNativeInstance() {
+ return nativeColorMatrixFilter(mMatrix.getArray());
}
private static native long nativeColorMatrixFilter(float[] array);
diff --git a/graphics/java/android/graphics/LightingColorFilter.java b/graphics/java/android/graphics/LightingColorFilter.java
index ad78430..b0c145b 100644
--- a/graphics/java/android/graphics/LightingColorFilter.java
+++ b/graphics/java/android/graphics/LightingColorFilter.java
@@ -21,6 +21,8 @@
package android.graphics;
+import android.annotation.ColorInt;
+
/**
* A color filter that can be used to simulate simple lighting effects.
* A <code>LightingColorFilter</code> is defined by two parameters, one
@@ -37,7 +39,9 @@
* The result is pinned to the <code>[0..255]</code> range for each channel.
*/
public class LightingColorFilter extends ColorFilter {
+ @ColorInt
private int mMul;
+ @ColorInt
private int mAdd;
/**
@@ -45,10 +49,9 @@
* and then adds a second color. The alpha components of the mul and add
* arguments are ignored.
*/
- public LightingColorFilter(int mul, int add) {
+ public LightingColorFilter(@ColorInt int mul, @ColorInt int add) {
mMul = mul;
mAdd = add;
- update();
}
/**
@@ -56,9 +59,8 @@
* color filter is applied.
*
* @see #setColorMultiply(int)
- *
- * @hide
*/
+ @ColorInt
public int getColorMultiply() {
return mMul;
}
@@ -69,12 +71,12 @@
* The alpha channel of this color is ignored.
*
* @see #getColorMultiply()
- *
- * @hide
*/
- public void setColorMultiply(int mul) {
- mMul = mul;
- update();
+ public void setColorMultiply(@ColorInt int mul) {
+ if (mMul != mul) {
+ mMul = mul;
+ discardNativeInstance();
+ }
}
/**
@@ -82,9 +84,8 @@
* when the color filter is applied.
*
* @see #setColorAdd(int)
- *
- * @hide
*/
+ @ColorInt
public int getColorAdd() {
return mAdd;
}
@@ -95,17 +96,17 @@
* The alpha channel of this color is ignored.
*
* @see #getColorAdd()
- *
- * @hide
*/
- public void setColorAdd(int add) {
- mAdd = add;
- update();
+ public void setColorAdd(@ColorInt int add) {
+ if (mAdd != add) {
+ mAdd = add;
+ discardNativeInstance();
+ }
}
- private void update() {
- destroyFilter(native_instance);
- native_instance = native_CreateLightingFilter(mMul, mAdd);
+ @Override
+ long createNativeInstance() {
+ return native_CreateLightingFilter(mMul, mAdd);
}
private static native long native_CreateLightingFilter(int mul, int add);
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 7ca4615..5d6aa8a 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -42,7 +42,8 @@
public class Paint {
private long mNativePaint;
- private long mNativeShader = 0;
+ private long mNativeShader;
+ private long mNativeColorFilter;
// The approximate size of a native paint object.
private static final long NATIVE_PAINT_SIZE = 98;
@@ -584,6 +585,11 @@
mNativeShader = newNativeShader;
nSetShader(mNativePaint, mNativeShader);
}
+ long newNativeColorFilter = mColorFilter == null ? 0 : mColorFilter.getNativeInstance();
+ if (newNativeColorFilter != mNativeColorFilter) {
+ mNativeColorFilter = newNativeColorFilter;
+ nSetColorFilter(mNativePaint, mNativeColorFilter);
+ }
return mNativePaint;
}
@@ -1044,10 +1050,13 @@
* @return filter
*/
public ColorFilter setColorFilter(ColorFilter filter) {
- long filterNative = 0;
- if (filter != null)
- filterNative = filter.native_instance;
- nSetColorFilter(mNativePaint, filterNative);
+ // If mColorFilter changes, cached value of native shader aren't valid, since
+ // old shader's pointer may be reused by another shader allocation later
+ if (mColorFilter != filter) {
+ mNativeColorFilter = -1;
+ }
+
+ // Defer setting the filter natively until getNativeInstance() is called
mColorFilter = filter;
return filter;
}
diff --git a/graphics/java/android/graphics/PorterDuffColorFilter.java b/graphics/java/android/graphics/PorterDuffColorFilter.java
index 69d6891..ccc6ead 100644
--- a/graphics/java/android/graphics/PorterDuffColorFilter.java
+++ b/graphics/java/android/graphics/PorterDuffColorFilter.java
@@ -24,6 +24,7 @@
* color and a specific {@link PorterDuff Porter-Duff composite mode}.
*/
public class PorterDuffColorFilter extends ColorFilter {
+ @ColorInt
private int mColor;
private PorterDuff.Mode mMode;
@@ -40,7 +41,6 @@
public PorterDuffColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
mColor = color;
mMode = mode;
- update();
}
/**
@@ -49,9 +49,8 @@
*
* @see Color
* @see #setColor(int)
- *
- * @hide
*/
+ @ColorInt
public int getColor() {
return mColor;
}
@@ -65,12 +64,12 @@
* @see Color
* @see #getColor()
* @see #getMode()
- *
- * @hide
*/
- public void setColor(int color) {
- mColor = color;
- update();
+ public void setColor(@ColorInt int color) {
+ if (mColor != color) {
+ mColor = color;
+ discardNativeInstance();
+ }
}
/**
@@ -79,8 +78,6 @@
*
* @see PorterDuff
* @see #setMode(android.graphics.PorterDuff.Mode)
- *
- * @hide
*/
public PorterDuff.Mode getMode() {
return mMode;
@@ -93,17 +90,18 @@
* @see PorterDuff
* @see #getMode()
* @see #getColor()
- *
- * @hide
*/
public void setMode(@NonNull PorterDuff.Mode mode) {
+ if (mode == null) {
+ throw new IllegalArgumentException("mode must be non-null");
+ }
mMode = mode;
- update();
+ discardNativeInstance();
}
- private void update() {
- destroyFilter(native_instance);
- native_instance = native_CreatePorterDuffFilter(mColor, mMode.nativeInt);
+ @Override
+ long createNativeInstance() {
+ return native_CreatePorterDuffFilter(mColor, mMode.nativeInt);
}
@Override
@@ -115,10 +113,7 @@
return false;
}
final PorterDuffColorFilter other = (PorterDuffColorFilter) object;
- if (mColor != other.mColor || mMode != other.mMode) {
- return false;
- }
- return true;
+ return (mColor == other.mColor && mMode.nativeInt == other.mMode.nativeInt);
}
@Override
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index b584e0d..8410ab2 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -106,8 +106,10 @@
}
void discardNativeInstance() {
- nativeSafeUnref(mNativeInstance);
- mNativeInstance = 0;
+ if (mNativeInstance != 0) {
+ nativeSafeUnref(mNativeInstance);
+ mNativeInstance = 0;
+ }
}
/**
@@ -120,7 +122,9 @@
@Override
protected void finalize() throws Throwable {
try {
- nativeSafeUnref(mNativeInstance);
+ if (mNativeInstance != 0) {
+ nativeSafeUnref(mNativeInstance);
+ }
mNativeInstance = -1;
} finally {
super.finalize();
diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
index 0722c18..c6c9271 100644
--- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
+++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
@@ -218,6 +218,8 @@
}
/**
+ * Only call this method after bound is set on this drawable.
+ *
* @return the mask path object used to clip the drawable
*/
public Path getIconMask() {
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 3a12419..a1539b8 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -333,7 +333,7 @@
// Color filters always override tint filters.
final ColorFilter colorFilter = (mColorFilter == null ? mTintFilter : mColorFilter);
final long colorFilterNativeInstance = colorFilter == null ? 0 :
- colorFilter.native_instance;
+ colorFilter.getNativeInstance();
boolean canReuseCache = mVectorState.canReuseCache();
int pixelCount = nDraw(mVectorState.getNativeRenderer(), canvas.getNativeCanvasWrapper(),
colorFilterNativeInstance, mTmpBounds, needMirroring(),
diff --git a/libs/hwui/FloatColor.h b/libs/hwui/FloatColor.h
index d8afa35..a738ba4 100644
--- a/libs/hwui/FloatColor.h
+++ b/libs/hwui/FloatColor.h
@@ -38,13 +38,14 @@
}
// "color" is a gamma-encoded sRGB color
- // After calling this method, the color is stored as a linear color. The color
- // is not pre-multiplied.
- void setUnPreMultipliedSRGB(uint32_t color) {
+ // After calling this method, the color is stored as a un-premultiplied linear color
+ // if linear blending is enabled. Otherwise, the color is stored as a un-premultiplied
+ // gamma-encoded sRGB color
+ void setUnPreMultiplied(uint32_t color) {
a = ((color >> 24) & 0xff) / 255.0f;
- r = EOCF_sRGB(((color >> 16) & 0xff) / 255.0f);
- g = EOCF_sRGB(((color >> 8) & 0xff) / 255.0f);
- b = EOCF_sRGB(((color ) & 0xff) / 255.0f);
+ r = EOCF(((color >> 16) & 0xff) / 255.0f);
+ g = EOCF(((color >> 8) & 0xff) / 255.0f);
+ b = EOCF(((color ) & 0xff) / 255.0f);
}
bool isNotBlack() {
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index 18bfcc2..dceb285 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -189,9 +189,9 @@
float amount, uint8_t*& dst) const {
float oppAmount = 1.0f - amount;
float a = start.a * oppAmount + end.a * amount;
- *dst++ = uint8_t(a * OECF_sRGB((start.r * oppAmount + end.r * amount)) * 255.0f);
- *dst++ = uint8_t(a * OECF_sRGB((start.g * oppAmount + end.g * amount)) * 255.0f);
- *dst++ = uint8_t(a * OECF_sRGB((start.b * oppAmount + end.b * amount)) * 255.0f);
+ *dst++ = uint8_t(a * OECF(start.r * oppAmount + end.r * amount) * 255.0f);
+ *dst++ = uint8_t(a * OECF(start.g * oppAmount + end.g * amount) * 255.0f);
+ *dst++ = uint8_t(a * OECF(start.b * oppAmount + end.b * amount) * 255.0f);
*dst++ = uint8_t(a * 255.0f);
}
@@ -201,17 +201,14 @@
float a = start.a * oppAmount + end.a * amount;
float* d = (float*) dst;
#ifdef ANDROID_ENABLE_LINEAR_BLENDING
+ // We want to stay linear
*d++ = a * (start.r * oppAmount + end.r * amount);
*d++ = a * (start.g * oppAmount + end.g * amount);
*d++ = a * (start.b * oppAmount + end.b * amount);
#else
- // What we're doing to the alpha channel here is technically incorrect
- // but reproduces Android's old behavior when the alpha was pre-multiplied
- // with gamma-encoded colors
- a = EOCF_sRGB(a);
- *d++ = a * OECF_sRGB(start.r * oppAmount + end.r * amount);
- *d++ = a * OECF_sRGB(start.g * oppAmount + end.g * amount);
- *d++ = a * OECF_sRGB(start.b * oppAmount + end.b * amount);
+ *d++ = a * OECF(start.r * oppAmount + end.r * amount);
+ *d++ = a * OECF(start.g * oppAmount + end.g * amount);
+ *d++ = a * OECF(start.b * oppAmount + end.b * amount);
#endif
*d++ = a;
dst += 4 * sizeof(float);
@@ -232,10 +229,10 @@
ChannelMixer mix = gMixers[mUseFloatTexture];
FloatColor start;
- start.setUnPreMultipliedSRGB(colors[0]);
+ start.setUnPreMultiplied(colors[0]);
FloatColor end;
- end.setUnPreMultipliedSRGB(colors[1]);
+ end.setUnPreMultiplied(colors[1]);
int currentPos = 1;
float startPos = positions[0];
@@ -250,7 +247,7 @@
currentPos++;
- end.setUnPreMultipliedSRGB(colors[currentPos]);
+ end.setUnPreMultiplied(colors[currentPos]);
distance = positions[currentPos] - startPos;
}
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 40ab778..38c23e4 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -190,7 +190,7 @@
// Dithering must be done in the quantization space
// When we are writing to an sRGB framebuffer, we must do the following:
// EOTF(OETF(color) + dither)
-// The dithering pattern is generated with a triangle noise generator in the range [-0.0,1.0]
+// The dithering pattern is generated with a triangle noise generator in the range [-1.0,1.0]
// TODO: Handle linear fp16 render targets
const char* gFS_Gradient_Functions = R"__SHADER__(
float triangleNoise(const highp vec2 n) {
@@ -202,23 +202,26 @@
)__SHADER__";
const char* gFS_Gradient_Preamble[2] = {
// Linear framebuffer
- "\nvec4 dither(const vec4 color) {\n"
- " return vec4(color.rgb + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0), color.a);\n"
- "}\n"
- "\nvec4 gammaMix(const vec4 a, const vec4 b, float v) {\n"
- " vec4 c = mix(a, b, v);\n"
- " c.a = EOTF_sRGB(c.a);\n" // This is technically incorrect but preserves compatibility
- " return vec4(OETF_sRGB(c.rgb) * c.a, c.a);\n"
- "}\n",
+ R"__SHADER__(
+ vec4 dither(const vec4 color) {
+ return color + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0);
+ }
+ vec4 gradientMix(const vec4 a, const vec4 b, float v) {
+ vec4 c = mix(a, b, v);
+ return vec4(c.rgb * c.a, c.a);
+ }
+ )__SHADER__",
// sRGB framebuffer
- "\nvec4 dither(const vec4 color) {\n"
- " vec3 dithered = sqrt(color.rgb) + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0);\n"
- " return vec4(dithered * dithered, color.a);\n"
- "}\n"
- "\nvec4 gammaMix(const vec4 a, const vec4 b, float v) {\n"
- " vec4 c = mix(a, b, v);\n"
- " return vec4(c.rgb * c.a, c.a);\n"
- "}\n"
+ R"__SHADER__(
+ vec4 dither(const vec4 color) {
+ vec3 dithered = sqrt(color.rgb) + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0);
+ return vec4(dithered * dithered, color.a);
+ }
+ vec4 gradientMixMix(const vec4 a, const vec4 b, float v) {
+ vec4 c = mix(a, b, v);
+ return vec4(c.rgb * c.a, c.a);
+ }
+ )__SHADER__",
};
// Uses luminance coefficients from Rec.709 to choose the appropriate gamma
@@ -272,19 +275,19 @@
// Linear
" vec4 gradientColor = texture2D(gradientSampler, linear);\n",
- " vec4 gradientColor = gammaMix(startColor, endColor, clamp(linear, 0.0, 1.0));\n",
+ " vec4 gradientColor = gradientMix(startColor, endColor, clamp(linear, 0.0, 1.0));\n",
// Circular
" vec4 gradientColor = texture2D(gradientSampler, vec2(length(circular), 0.5));\n",
- " vec4 gradientColor = gammaMix(startColor, endColor, clamp(length(circular), 0.0, 1.0));\n",
+ " vec4 gradientColor = gradientMix(startColor, endColor, clamp(length(circular), 0.0, 1.0));\n",
// Sweep
" highp float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
" vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n",
" highp float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
- " vec4 gradientColor = gammaMix(startColor, endColor, clamp(index - floor(index), 0.0, 1.0));\n"
+ " vec4 gradientColor = gradientMix(startColor, endColor, clamp(index - floor(index), 0.0, 1.0));\n"
};
const char* gFS_Main_FetchBitmap =
" vec4 bitmapColor = OETF(texture2D(bitmapSampler, outBitmapTexCoords));\n";
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 760c10c..4f7f9d7 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -173,8 +173,8 @@
outData->gradientSampler = 0;
outData->gradientTexture = nullptr;
- outData->startColor.setUnPreMultipliedSRGB(gradInfo.fColors[0]);
- outData->endColor.setUnPreMultipliedSRGB(gradInfo.fColors[1]);
+ outData->startColor.setUnPreMultiplied(gradInfo.fColors[0]);
+ outData->endColor.setUnPreMultiplied(gradInfo.fColors[1]);
}
return true;
diff --git a/libs/hwui/VkLayer.cpp b/libs/hwui/VkLayer.cpp
index 537b3ea..ef4784b 100644
--- a/libs/hwui/VkLayer.cpp
+++ b/libs/hwui/VkLayer.cpp
@@ -29,7 +29,7 @@
SkImageInfo info = SkImageInfo::MakeS32(mWidth, mHeight, kPremul_SkAlphaType);
surface = SkSurface::MakeRenderTarget(mRenderState.getGrContext(), SkBudgeted::kNo, info);
surface->getCanvas()->clear(SK_ColorBLUE);
- mImage = surface->makeImageSnapshot(SkBudgeted::kNo);
+ mImage = surface->makeImageSnapshot();
}
void VkLayer::onVkContextDestroyed() {
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 62fd395..c28aa5e 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -1807,6 +1807,9 @@
* {@link #TYPE_S_DMB}, and
* {@link #TYPE_T_DMB}.
*
+ * <p>This value cannot be changed once it's set. Trying to modify it will make the update
+ * fail.
+ *
* <p>This is a required field.
*
* <p>Type: TEXT
diff --git a/packages/MtpDocumentsProvider/tests/Android.mk b/packages/MtpDocumentsProvider/tests/Android.mk
index e50d6fb..148cd0d 100644
--- a/packages/MtpDocumentsProvider/tests/Android.mk
+++ b/packages/MtpDocumentsProvider/tests/Android.mk
@@ -8,5 +8,6 @@
LOCAL_PACKAGE_NAME := MtpDocumentsProviderTests
LOCAL_INSTRUMENTATION_FOR := MtpDocumentsProvider
LOCAL_CERTIFICATE := media
+LOCAL_COMPATIBILITY_SUITE := device-tests
include $(BUILD_PACKAGE)
diff --git a/packages/PrintSpooler/tests/outofprocess/Android.mk b/packages/PrintSpooler/tests/outofprocess/Android.mk
index d1d0ee4..3c02453 100644
--- a/packages/PrintSpooler/tests/outofprocess/Android.mk
+++ b/packages/PrintSpooler/tests/outofprocess/Android.mk
@@ -24,5 +24,6 @@
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ub-uiautomator mockito-target-minus-junit4
LOCAL_PACKAGE_NAME := PrintSpoolerOutOfProcessTests
+LOCAL_COMPATIBILITY_SUITE := device-tests
include $(BUILD_PACKAGE)
diff --git a/packages/SettingsLib/tests/integ/Android.mk b/packages/SettingsLib/tests/integ/Android.mk
index 60d1c77..7ace048 100644
--- a/packages/SettingsLib/tests/integ/Android.mk
+++ b/packages/SettingsLib/tests/integ/Android.mk
@@ -25,6 +25,7 @@
LOCAL_JACK_FLAGS := --multi-dex native
LOCAL_PACKAGE_NAME := SettingsLibTests
+LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 91a4e79..1f1c189 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -248,6 +248,9 @@
@GuardedBy("mLock")
private HandlerThread mHandlerThread;
+ @GuardedBy("mLock")
+ private Handler mHandler;
+
// We have to call in the user manager with no lock held,
private volatile UserManager mUserManager;
@@ -300,10 +303,13 @@
mHandlerThread = new HandlerThread(LOG_TAG,
Process.THREAD_PRIORITY_BACKGROUND);
mHandlerThread.start();
+ mHandler = new Handler(mHandlerThread.getLooper());
mSettingsRegistry = new SettingsRegistry();
}
- registerBroadcastReceivers();
- startWatchingUserRestrictionChanges();
+ mHandler.post(() -> {
+ registerBroadcastReceivers();
+ startWatchingUserRestrictionChanges();
+ });
ServiceManager.addService("settings", new SettingsService(this));
return true;
}
diff --git a/packages/Shell/tests/Android.mk b/packages/Shell/tests/Android.mk
index acd552d..48b757c 100644
--- a/packages/Shell/tests/Android.mk
+++ b/packages/Shell/tests/Android.mk
@@ -16,6 +16,7 @@
legacy-android-test \
LOCAL_PACKAGE_NAME := ShellTests
+LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_INSTRUMENTATION_FOR := Shell
LOCAL_CERTIFICATE := platform
diff --git a/packages/SystemUI/res/color/qs_user_detail_avatar_tint.xml b/packages/SystemUI/res/color/qs_user_detail_avatar_tint.xml
index 2b75c36..696e9b1 100644
--- a/packages/SystemUI/res/color/qs_user_detail_avatar_tint.xml
+++ b/packages/SystemUI/res/color/qs_user_detail_avatar_tint.xml
@@ -17,6 +17,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_enabled="false" android:color="@color/qs_tile_disabled_color" />
+ <item android:state_enabled="false" android:color="?android:attr/textColorPrimary" />
<item android:color="@android:color/transparent" />
-</selector>
\ No newline at end of file
+</selector>
diff --git a/packages/SystemUI/res/drawable/ic_add_circle_qs.xml b/packages/SystemUI/res/drawable/ic_add_circle_qs.xml
index f296076..6415ecb4 100644
--- a/packages/SystemUI/res/drawable/ic_add_circle_qs.xml
+++ b/packages/SystemUI/res/drawable/ic_add_circle_qs.xml
@@ -17,14 +17,15 @@
android:width="48.0dp"
android:height="48.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<group
android:scaleX="1.2"
android:scaleY="1.2"
android:pivotX="12.0"
android:pivotY="12.0">
<path
- android:fillColor="@color/qs_user_detail_icon_muted"
+ android:fillColor="#FFFFFFFF"
android:pathData="M12.000000,2.000000C6.500000,2.000000 2.000000,6.500000 2.000000,12.000000s4.500000,10.000000 10.000000,10.000000c5.500000,0.000000 10.000000,-4.500000 10.000000,-10.000000S17.500000,2.000000 12.000000,2.000000zM17.000000,13.000000l-4.000000,0.000000l0.000000,4.000000l-2.000000,0.000000l0.000000,-4.000000L7.000000,13.000000l0.000000,-2.000000l4.000000,0.000000L11.000000,7.000000l2.000000,0.000000l0.000000,4.000000l4.000000,0.000000L17.000000,13.000000z"/>
</group>
</vector>
diff --git a/packages/SystemUI/res/layout/pip_menu_action.xml b/packages/SystemUI/res/layout/pip_menu_action.xml
index 77efc9b..9150a00 100644
--- a/packages/SystemUI/res/layout/pip_menu_action.xml
+++ b/packages/SystemUI/res/layout/pip_menu_action.xml
@@ -18,4 +18,5 @@
android:layout_width="@dimen/pip_action_size"
android:layout_height="@dimen/pip_action_size"
android:padding="@dimen/pip_action_padding"
- android:background="?android:selectableItemBackgroundBorderless" />
\ No newline at end of file
+ android:background="?android:selectableItemBackgroundBorderless"
+ android:forceHasOverlappingRendering="false" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/pip_menu_activity.xml b/packages/SystemUI/res/layout/pip_menu_activity.xml
index c6837fa..44ced17 100644
--- a/packages/SystemUI/res/layout/pip_menu_activity.xml
+++ b/packages/SystemUI/res/layout/pip_menu_activity.xml
@@ -23,7 +23,8 @@
<FrameLayout
android:id="@+id/menu_container"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:forceHasOverlappingRendering="false">
<ImageView
android:id="@+id/dismiss"
diff --git a/packages/SystemUI/res/layout/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml
index 8d1f9e4..9d1fb8f 100644
--- a/packages/SystemUI/res/layout/qs_tile_label.xml
+++ b/packages/SystemUI/res/layout/qs_tile_label.xml
@@ -14,24 +14,39 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="48dp"
+ android:paddingTop="8dp">
+ <LinearLayout
+ android:id="@+id/label_group"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:gravity="center_horizontal"
- android:paddingTop="8dp"
- android:paddingBottom="8dp">
- <TextView android:id="@+id/tile_label"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@+id/tile_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textColor="?android:attr/textColorPrimary"
- android:gravity="center_horizontal"
- android:minLines="2"
+ android:clickable="false"
+ android:maxLines="2"
android:padding="0dp"
android:textAppearance="@style/TextAppearance.QS.TileLabel"
- android:clickable="false" />
- <ImageView android:id="@+id/restricted_padlock"
+ android:textColor="?android:attr/textColorPrimary"/>
+
+ <ImageView
+ android:id="@+id/expand_indicator"
+ android:layout_marginStart="4dp"
+ android:layout_width="12dp"
+ android:layout_height="match_parent"
+ android:src="@drawable/qs_dual_tile_caret"
+ android:tint="?android:attr/textColorPrimary" />
+
+ <ImageView android:id="@+id/restricted_padlock"
android:layout_width="@dimen/qs_tile_text_size"
android:layout_height="match_parent"
android:paddingBottom="@dimen/qs_tile_text_size"
@@ -39,4 +54,32 @@
android:layout_marginLeft="@dimen/restricted_padlock_pading"
android:scaleType="centerInside"
android:visibility="gone" />
-</LinearLayout>
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/app_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignStart="@id/label_group"
+ android:layout_alignEnd="@id/label_group"
+ android:layout_below="@id/label_group"
+ android:clickable="false"
+ android:maxLines="1"
+ android:padding="0dp"
+ android:visibility="gone"
+ android:gravity="center"
+ android:textAppearance="@style/TextAppearance.QS.TileLabel"
+ android:textColor="?android:attr/textColorPrimary"/>
+
+ <View
+ android:id="@+id/underline"
+ android:layout_width="30dp"
+ android:layout_height="1dp"
+ android:layout_marginTop="2dp"
+ android:layout_alignStart="@id/label_group"
+ android:layout_alignEnd="@id/label_group"
+ android:layout_below="@id/label_group"
+ android:alpha="?android:attr/disabledAlpha"
+ android:background="?android:attr/colorForeground"/>
+
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml
index 8c6c7cf..c7bfaef 100644
--- a/packages/SystemUI/res/layout/qs_user_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml
@@ -53,7 +53,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/qs_detail_item_secondary_text_size"
- android:textColor="@color/qs_user_detail_name"
+ android:textColor="?android:attr/textColorSecondary"
android:gravity="center_horizontal" />
<ImageView
android:id="@+id/restricted_padlock"
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index cbe822f..a549c73 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1160,7 +1160,8 @@
if (mOccluded != isOccluded) {
mOccluded = isOccluded;
- mStatusBarKeyguardViewManager.setOccluded(isOccluded, animate);
+ mStatusBarKeyguardViewManager.setOccluded(isOccluded, animate
+ && mDeviceInteractive);
adjustStatusBarLocked();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 2f9c3fc..9cb518c 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -19,8 +19,8 @@
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_ACTIONS;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_CONTROLLER_MESSENGER;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MOVEMENT_BOUNDS;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_STACK_BOUNDS;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_SHOW_MENU;
+import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_STACK_BOUNDS;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -33,13 +33,11 @@
import android.app.RemoteAction;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
-import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -84,6 +82,8 @@
private static final float MENU_BACKGROUND_ALPHA = 0.3f;
private static final float DISMISS_BACKGROUND_ALPHA = 0.8f;
+ private static final float DISABLED_ACTION_ALPHA = 0.54f;
+
private boolean mMenuVisible;
private final List<RemoteAction> mActions = new ArrayList<>();
private View mViewRoot;
@@ -249,6 +249,7 @@
private void showMenu(Rect stackBounds, Rect movementBounds) {
if (!mMenuVisible) {
+ setVisible(true);
updateActionViews(stackBounds);
if (mMenuContainerAnimator != null) {
mMenuContainerAnimator.cancel();
@@ -268,7 +269,10 @@
mMenuContainerAnimator.addUpdateListener(mMenuBgUpdateListener);
mMenuContainerAnimator.start();
} else {
+ // If we are already visible, then just start the delayed dismiss and unregister any
+ // existing input consumers from the previous drag
repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
+ notifyUnregisterInputConsumer();
}
}
@@ -292,9 +296,7 @@
if (animationFinishedRunnable != null) {
animationFinishedRunnable.run();
}
- if (getSystemService(AccessibilityManager.class).isEnabled()) {
- finish();
- }
+ setVisible(false);
}
});
mMenuContainerAnimator.addUpdateListener(mMenuBgUpdateListener);
@@ -369,13 +371,18 @@
actionView.setImageDrawable(d);
}, mHandler);
actionView.setContentDescription(action.getContentDescription());
- actionView.setOnClickListener(v -> {
- try {
- action.getActionIntent().send();
- } catch (CanceledException e) {
- Log.w(TAG, "Failed to send action", e);
- }
- });
+ if (action.isEnabled()) {
+ actionView.setOnClickListener(v -> {
+ try {
+ action.getActionIntent().send();
+ } catch (CanceledException e) {
+ Log.w(TAG, "Failed to send action", e);
+ }
+ });
+ } else {
+ actionView.setAlpha(DISABLED_ACTION_ALPHA);
+ actionView.setEnabled(false);
+ }
if (isLandscapePip && i > 0) {
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
actionView.getLayoutParams();
@@ -398,6 +405,7 @@
}
private void updateDismissFraction(float fraction) {
+ setVisible(true);
int alpha;
if (mMenuVisible) {
mMenuContainer.setAlpha(1-fraction);
@@ -416,6 +424,12 @@
sendMessage(m, "Could not notify controller to register input consumer");
}
+ private void notifyUnregisterInputConsumer() {
+ Message m = Message.obtain();
+ m.what = PipMenuActivityController.MESSAGE_UNREGISTER_INPUT_CONSUMER;
+ sendMessage(m, "Could not notify controller to unregister input consumer");
+ }
+
private void notifyMenuVisibility(boolean visible) {
mMenuVisible = visible;
Message m = Message.obtain();
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 7dc455b..724f453 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -63,6 +63,7 @@
public static final int MESSAGE_DISMISS_PIP = 103;
public static final int MESSAGE_UPDATE_ACTIVITY_CALLBACK = 104;
public static final int MESSAGE_REGISTER_INPUT_CONSUMER = 105;
+ public static final int MESSAGE_UNREGISTER_INPUT_CONSUMER = 106;
/**
* A listener interface to receive notification on changes in PIP.
@@ -135,6 +136,10 @@
mInputConsumerController.registerInputConsumer();
break;
}
+ case MESSAGE_UNREGISTER_INPUT_CONSUMER: {
+ mInputConsumerController.unregisterInputConsumer();
+ break;
+ }
case MESSAGE_UPDATE_ACTIVITY_CALLBACK: {
mToActivityMessenger = msg.replyTo;
mStartActivityRequested = false;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index c52fc3e..f70d5b4 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -504,8 +504,8 @@
return false;
}
- try {
- if (ENABLE_DISMISS_DRAG_TO_TARGET) {
+ if (ENABLE_DISMISS_DRAG_TO_TARGET) {
+ try {
mHandler.removeCallbacks(mShowDismissAffordance);
PointF vel = mTouchState.getVelocity();
final float velocity = PointF.length(vel.x, vel.y);
@@ -520,9 +520,9 @@
return true;
}
}
+ } finally {
+ mDismissViewController.destroyDismissTarget();
}
- } finally {
- mDismissViewController.destroyDismissTarget();
}
if (touchState.isDragging()) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java
index 0629d66..b080642 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java
@@ -35,19 +35,13 @@
protected void createLabel() {
super.createLabel();
mLabelMinLines = mLabel.getMinLines();
- View view = LayoutInflater.from(mContext).inflate(R.layout.qs_tile_label, null);
- mAppLabel = (TextView) view.findViewById(R.id.tile_label);
+ mAppLabel = findViewById(R.id.app_label);
mAppLabel.setAlpha(.6f);
- mAppLabel.setSingleLine(true);
- addView(view);
}
public void setShowAppLabel(boolean showAppLabel) {
mAppLabel.setVisibility(showAppLabel ? View.VISIBLE : View.GONE);
mLabel.setSingleLine(showAppLabel);
- if (!showAppLabel) {
- mLabel.setMinLines(mLabelMinLines);
- }
}
public void setAppLabel(CharSequence label) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index c0fb4d5..d8e5542 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -41,10 +41,10 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QS;
-import com.android.systemui.qs.QSDetailClipper;
import com.android.systemui.plugins.qs.QSTile;
-import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
+import com.android.systemui.qs.QSDetailClipper;
import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.KeyguardMonitor.Callback;
@@ -74,6 +74,7 @@
private boolean mFinishedFetchingTiles = false;
private int mX;
private int mY;
+ private boolean mOpening;
public QSCustomizer(Context context, AttributeSet attrs) {
super(new ContextThemeWrapper(context, R.style.edit_theme), attrs);
@@ -140,6 +141,7 @@
mY = y;
MetricsLogger.visible(getContext(), MetricsProto.MetricsEvent.QS_EDIT);
isShown = true;
+ mOpening = true;
setTileSpecs();
setVisibility(View.VISIBLE);
mClipper.animateCircularClip(x, y, true, mExpandAnimationListener);
@@ -226,7 +228,8 @@
}
private final Callback mKeyguardCallback = () -> {
- if (Dependency.get(KeyguardMonitor.class).isShowing()) {
+ if (!isAttachedToWindow()) return;
+ if (Dependency.get(KeyguardMonitor.class).isShowing() && !mOpening) {
hide(0, 0);
}
};
@@ -237,11 +240,13 @@
if (isShown) {
setCustomizing(true);
}
+ mOpening = false;
mNotifQsContainer.setCustomizerAnimating(false);
}
@Override
public void onAnimationCancel(Animator animation) {
+ mOpening = false;
mNotifQsContainer.setCustomizerAnimating(false);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 547bef7..2ac592f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -165,6 +165,7 @@
}
TileInfo info = new TileInfo();
info.state = state;
+ info.state.dualTarget = false; // No dual targets in edit.
info.state.expandedAccessibilityClassName =
Button.class.getName();
info.spec = spec;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 5ac7891..948954c2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -369,7 +369,6 @@
Dependency.get(ActivityStarter.class).postStartActivityDismissingKeyguard(
intent, 0);
} else {
- mAnnounceNextStateChange = true;
handleClick();
}
} else if (msg.what == SECONDARY_CLICK) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
index 2c04e82..d2ae6e9f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
@@ -36,11 +36,12 @@
/** View that represents a standard quick settings tile. **/
public class QSTileView extends QSTileBaseView {
- private final View mDivider;
+ private View mDivider;
protected TextView mLabel;
private ImageView mPadLock;
private int mState;
private ViewGroup mLabelContainer;
+ private View mExpandIndicator;
public QSTileView(Context context, QSIconView icon) {
this(context, icon, false);
@@ -54,8 +55,6 @@
setClickable(true);
setId(View.generateViewId());
- mDivider = LayoutInflater.from(context).inflate(R.layout.divider, this, false);
- addView(mDivider);
createLabel();
setOrientation(VERTICAL);
setGravity(Gravity.CENTER);
@@ -81,8 +80,10 @@
.inflate(R.layout.qs_tile_label, this, false);
mLabelContainer.setClipChildren(false);
mLabelContainer.setClipToPadding(false);
- mLabel = (TextView) mLabelContainer.findViewById(R.id.tile_label);
- mPadLock = (ImageView) mLabelContainer.findViewById(R.id.restricted_padlock);
+ mLabel = mLabelContainer.findViewById(R.id.tile_label);
+ mPadLock = mLabelContainer.findViewById(R.id.restricted_padlock);
+ mDivider = mLabelContainer.findViewById(R.id.underline);
+ mExpandIndicator = mLabelContainer.findViewById(R.id.expand_indicator);
addView(mLabelContainer);
}
@@ -101,6 +102,7 @@
mLabel.setText(state.label);
}
mDivider.setVisibility(state.dualTarget ? View.VISIBLE : View.INVISIBLE);
+ mExpandIndicator.setVisibility(state.dualTarget ? View.VISIBLE : View.GONE);
if (state.dualTarget != mLabelContainer.isClickable()) {
mLabelContainer.setClickable(state.dualTarget);
mLabelContainer.setLongClickable(state.dualTarget);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 47468ae..ac24e2e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -67,6 +67,7 @@
import android.os.UserManager;
import android.provider.Settings;
import android.util.ArraySet;
+import android.util.LauncherIcons;
import android.util.Log;
import android.util.MutableBoolean;
import android.view.Display;
@@ -142,6 +143,7 @@
int mDummyThumbnailHeight;
Paint mBgProtectionPaint;
Canvas mBgProtectionCanvas;
+ LauncherIcons mLauncherIcons;
private final Handler mHandler = new H();
@@ -299,6 +301,7 @@
Collections.addAll(sRecentsBlacklist,
res.getStringArray(R.array.recents_blacklist_array));
}
+ mLauncherIcons = new LauncherIcons(context);
}
/**
@@ -834,7 +837,7 @@
return new ColorDrawable(0xFF666666);
}
- Drawable icon = info.loadIcon(mPm);
+ Drawable icon = mLauncherIcons.wrapIconDrawableWithShadow(info.loadIcon(mPm));
return getBadgedIcon(icon, userId);
}
@@ -850,7 +853,7 @@
return new ColorDrawable(0xFF666666);
}
- Drawable icon = appInfo.loadIcon(mPm);
+ Drawable icon = mLauncherIcons.wrapIconDrawableWithShadow(appInfo.loadIcon(mPm));
return getBadgedIcon(icon, userId);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index 820638c..c30bb9a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -74,7 +74,7 @@
if (mUserListener == null) {
return false;
}
- return mUserListener.getUserCount() > 1;
+ return mUserListener.getUserCount() != 0;
}
public void setUserSwitcherController(UserSwitcherController userSwitcherController) {
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 576299f..ddd8d7b 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -26,6 +26,7 @@
LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
LOCAL_PACKAGE_NAME := SystemUITests
+LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
$(call all-Iaidl-files-under, src) \
@@ -46,7 +47,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
metrics-helper-lib \
android-support-test \
- mockito-updated-target-minus-junit4 \
+ mockito-target-minus-junit4 \
SystemUI-proto \
SystemUI-tags \
legacy-android-test \
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 3800f29..8a3b9af 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -56,6 +56,12 @@
// Type for APP_TRANSITION event: The transition brought an already existing activity to the
// front.
TYPE_TRANSITION_HOT_LAUNCH = 9;
+
+ // The action was successful
+ TYPE_SUCCESS = 10;
+
+ // The action failed
+ TYPE_FAILURE = 11;
}
// Known visual elements: views or controls.
@@ -1180,7 +1186,7 @@
// OS: 6.0
BRIGHTNESS_DIALOG = 220;
- // OPEN: Settings > Apps > Configure Apps > Draw over other apps
+ // OPEN: Settings > Apps > Configure Apps > Display over other apps
// CATEGORY: SETTINGS
// OS: 6.0
SYSTEM_ALERT_WINDOW_APPS = 221;
@@ -3227,7 +3233,7 @@
// ACTION: Allow "Draw over other apps" for an app
APP_SPECIAL_PERMISSION_APPDRAW_ALLOW = 770;
- // ACTION: Deny "Draw over other apps" for an app
+ // ACTION: Deny "Display over other apps" for an app
APP_SPECIAL_PERMISSION_APPDRAW_DENY = 771;
// ACTION: Allow "VR helper services" for an app
@@ -3608,6 +3614,169 @@
// CATEGORY: SETTINGS
SETTINGS_LOCK_SCREEN_PREFERENCES = 882;
+ // ACTION: An app requested the app-op permission ACCESS_NOTIFICATIONS
+ // PACKAGE: The package name of the app requesting the permission
+ ACTION_APPOP_REQUEST_ACCESS_NOTIFICATIONS = 883;
+
+ // ACTION: An app was granted the app-op permission ACCESS_NOTIFICATIONS
+ // PACKAGE: The package name of the app that was granted the permission
+ ACTION_APPOP_GRANT_ACCESS_NOTIFICATIONS = 884;
+
+ // ACTION: An app requested the app-op permission ACCESS_NOTIFICATIONS and the request was denied
+ // PACKAGE: The package name of the app requesting the permission
+ ACTION_APPOP_DENIED_ACCESS_NOTIFICATIONS = 885;
+
+ // ACTION: The app-op permission ACCESS_NOTIFICATIONS was revoked for an app
+ // PACKAGE: The package name of the app the permission was revoked for
+ ACTION_APPOP_REVOKE_ACCESS_NOTIFICATIONS = 886;
+
+ // ACTION: An app requested the app-op permission SYSTEM_ALERT_WINDOW
+ // PACKAGE: The package name of the app requesting the permission
+ ACTION_APPOP_REQUEST_SYSTEM_ALERT_WINDOW = 887;
+
+ // ACTION: An app was granted the app-op permission SYSTEM_ALERT_WINDOW
+ // PACKAGE: The package name of the app that was granted the permission
+ ACTION_APPOP_GRANT_SYSTEM_ALERT_WINDOW = 888;
+
+ // ACTION: An app requested the app-op permission SYSTEM_ALERT_WINDOW and the request was denied
+ // PACKAGE: The package name of the app requesting the permission
+ ACTION_APPOP_DENIED_SYSTEM_ALERT_WINDOW = 889;
+
+ // ACTION: The app-op permission SYSTEM_ALERT_WINDOW was revoked for an app
+ // PACKAGE: The package name of the app the permission was revoked for
+ ACTION_APPOP_REVOKE_SYSTEM_ALERT_WINDOW = 890;
+
+ // ACTION: An app requested the app-op permission REQUEST_WRITE_SETTINGS
+ // PACKAGE: The package name of the app requesting the permission
+ ACTION_APPOP_REQUEST_WRITE_SETTINGS = 891;
+
+ // ACTION: An app was granted the app-op permission REQUEST_WRITE_SETTINGS
+ // PACKAGE: The package name of the app that was granted the permission
+ ACTION_APPOP_GRANT_WRITE_SETTINGS = 892;
+
+ // ACTION: An app requested the app-op permission REQUEST_WRITE_SETTINGS and the request was denied
+ // PACKAGE: The package name of the app requesting the permission
+ ACTION_APPOP_DENIED_WRITE_SETTINGS = 893;
+
+ // ACTION: The app-op permission REQUEST_WRITE_SETTINGS was revoked for an app
+ // PACKAGE: The package name of the app the permission was revoked for
+ ACTION_APPOP_REVOKE_WRITE_SETTINGS = 894;
+
+ // ACTION: An app requested the app-op permission REQUEST_INSTALL_PACKAGES
+ // PACKAGE: The package name of the app requesting the permission
+ ACTION_APPOP_REQUEST_REQUEST_INSTALL_PACKAGES = 895;
+
+ // ACTION: An app was granted the app-op permission REQUEST_INSTALL_PACKAGES
+ // PACKAGE: The package name of the app that was granted the permission
+ ACTION_APPOP_GRANT_REQUEST_INSTALL_PACKAGES = 896;
+
+ // ACTION: An app requested the app-op permission REQUEST_INSTALL_PACKAGES and the request was denied
+ // PACKAGE: The package name of the app requesting the permission
+ ACTION_APPOP_DENIED_REQUEST_INSTALL_PACKAGES = 897;
+
+ // ACTION: The app-op permission REQUEST_INSTALL_PACKAGES was revoked for an app
+ // PACKAGE: The package name of the app the permission was revoked for
+ ACTION_APPOP_REVOKE_REQUEST_INSTALL_PACKAGES = 898;
+
+ // ACTION: Phase 1 of instant application resolution occurred
+ // OS: O
+ ACTION_INSTANT_APP_RESOLUTION_PHASE_ONE = 899;
+
+ // ACTION: Phase 2 of instant application resolution occurred
+ // OS: O
+ ACTION_INSTANT_APP_RESOLUTION_PHASE_TWO = 900;
+
+ // FIELD: The amount of time for an ephemeral resolution phase; in milliseconds
+ // OS: O
+ FIELD_INSTANT_APP_RESOLUTION_DELAY_MS = 901;
+
+ // FIELD: The status of an ephemeral resolution phase
+ // Value 0: success
+ // Value 1: no full hash match
+ // OS: O
+ FIELD_INSTANT_APP_RESOLUTION_STATUS = 902;
+
+ // FIELD - A token to identify all events that are part of the same instant application launch
+ // OS: O
+ FIELD_INSTANT_APP_LAUNCH_TOKEN = 903;
+
+ // FIELD - The name of the package responsible for launching the activity
+ // OS: O
+ APP_TRANSITION_CALLING_PACKAGE_NAME = 904;
+
+ // FIELD - Whether or not the launched activity is part of an instant application
+ // OS: O
+ APP_TRANSITION_IS_EPHEMERAL = 905;
+
+ // An autofill session was started
+ // Package: Package of app that is autofilled
+ AUTOFILL_SESSION_STARTED = 906;
+
+ // An autofill request was processed by a service
+ // Type TYPE_SUCCESS: The request succeeded
+ // Type TYPE_FAILURE: The request failed
+ // Package: Package of app that is autofilled
+ // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+ // Tag FIELD_AUTOFILL_NUM_DATASET: The number of datasets returned (only in success case)
+ AUTOFILL_REQUEST = 907;
+
+ // Tag of a field for a package of an autofill service
+ FIELD_AUTOFILL_SERVICE = 908;
+
+ // Tag of a field for the number of datasets
+ FIELD_AUTOFILL_NUM_DATASETS = 909;
+
+ // An autofill dataset selection UI was shown
+ // Type TYPE_DISMISS: UI was explicityly canceled by the user
+ // Type TYPE_CLOSE: UI was destroyed without influence of the user
+ // Type TYPE_ACTION: dataset was selected
+ // Type TYPE_DETAIL: authentication was selected
+ // Package: Package of app that was autofilled
+ // Tag FIELD_AUTOFILL_FILTERTEXT_LEN: The length of the filter text
+ // Tag FIELD_AUTOFILL_NUM_DATASETS: The number of datasets shown
+ AUTOFILL_FILL_UI = 910;
+
+ // Tag of a field for the length of the filter text
+ FIELD_AUTOFILL_FILTERTEXT_LEN = 911;
+
+ // An autofill authentification succeeded
+ // Package: Package of app that was autofilled
+ AUTOFILL_AUTHENTICATED = 912;
+
+ // An activity was autofilled and all values could be applied
+ // Package: Package of app that is autofilled
+ // Tag FIELD_AUTOFILL_NUM_VALUES: Number of values that were suggested to be autofilled
+ // Tag FIELD_AUTOFILL_NUM_VIEWS_FILLED: Number of views that could be filled
+ AUTOFILL_DATASET_APPLIED = 913;
+
+ // Tag of a field for the number values to be filled in
+ FIELD_AUTOFILL_NUM_VALUES = 914;
+
+ // Tag of a field for the number of views that were filled
+ FIELD_AUTOFILL_NUM_VIEWS_FILLED = 915;
+
+ // An autofill save UI was shown
+ // Type TYPE_DISMISS: UI was explicityly canceled by the user
+ // Type TYPE_CLOSE: UI was destroyed without influence of the user
+ // Type TYPE_ACTION: data was saved
+ // Package: Package of app that was autofilled
+ // Tag FIELD_AUTOFILL_NUM_ID: The number of ids that are saved
+ AUTOFILL_SAVE_UI = 916;
+
+ // Tag of a field for the number of saveable ids
+ FIELD_AUTOFILL_NUM_IDS = 917;
+
+ // ACTION: An autofill service was reqiested to save data
+ // Type TYPE_SUCCESS: The request succeeded
+ // Type TYPE_FAILURE: The request failed
+ // Package: Package of app that was autofilled
+ // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+ AUTOFILL_DATA_SAVE_REQUEST = 918;
+
+ // An auto-fill session was finished
+ // Package: Package of app that was autofilled
+ AUTOFILL_SESSION_FINISHED = 919;
+
// ---- 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 af1193d..c7ba1ff 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -28,6 +28,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.graphics.Rect;
@@ -53,6 +54,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.IResultReceiver;
+import com.android.internal.util.Preconditions;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
@@ -316,13 +318,27 @@
@Override
public void startSession(IBinder activityToken, IBinder windowToken, IBinder appCallback,
AutofillId autofillId, Rect bounds, AutofillValue value, int userId,
- boolean hasCallback, int flags) {
+ boolean hasCallback, int flags, String packageName) {
// TODO(b/33197203): make sure it's called by resumed / focused activity
+ activityToken = Preconditions.checkNotNull(activityToken, "activityToken");
+ appCallback = Preconditions.checkNotNull(appCallback, "appCallback");
+ autofillId = Preconditions.checkNotNull(autofillId, "autoFillId");
+ bounds = Preconditions.checkNotNull(bounds, "bounds");
+ packageName = Preconditions.checkNotNull(packageName, "packageName");
+
+ Preconditions.checkArgument(userId == UserHandle.getUserId(getCallingUid()), "userId");
+
+ try {
+ mContext.getPackageManager().getPackageInfoAsUser(packageName, 0, userId);
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new IllegalArgumentException(packageName + " is not a valid package", e);
+ }
+
synchronized (mLock) {
final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
service.startSessionLocked(activityToken, windowToken, appCallback,
- autofillId, bounds, value, hasCallback, flags);
+ autofillId, bounds, value, hasCallback, flags, packageName);
}
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 3e5ad82..df76009 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -28,6 +28,7 @@
import static com.android.server.autofill.Helper.VERBOSE;
import static com.android.server.autofill.Helper.findValue;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
@@ -43,6 +44,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.graphics.Rect;
+import android.metrics.LogMaker;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
@@ -67,7 +69,11 @@
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
import android.view.autofill.IAutoFillManagerClient;
+import android.view.autofill.AutofillManager.AutofillCallback;
+
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.os.HandlerCaller;
import com.android.internal.os.IResultReceiver;
import com.android.server.autofill.ui.AutoFillUI;
@@ -92,6 +98,7 @@
private final Context mContext;
private final Object mLock;
private final AutoFillUI mUi;
+ private final MetricsLogger mMetricsLogger = new MetricsLogger();
private RemoteCallbackList<IAutoFillManagerClient> mClients;
private AutofillServiceInfo mInfo;
@@ -228,9 +235,8 @@
if (!hasService()) {
final int sessionCount = mSessions.size();
for (int i = sessionCount - 1; i >= 0; i--) {
- Session session = mSessions.valueAt(i);
- session.destroyLocked();
- mSessions.removeAt(i);
+ final Session session = mSessions.valueAt(i);
+ session.removeSelfLocked();
}
}
sendStateToClients();
@@ -284,9 +290,10 @@
}
}
- void startSessionLocked(IBinder activityToken, IBinder windowToken, IBinder appCallbackToken,
- AutofillId autofillId, Rect bounds, AutofillValue value, boolean hasCallback,
- int flags) {
+ void startSessionLocked(@NonNull IBinder activityToken, @Nullable IBinder windowToken,
+ @NonNull IBinder appCallbackToken, @NonNull AutofillId autofillId, @NonNull Rect bounds,
+ @Nullable AutofillValue value, boolean hasCallback, int flags,
+ @NonNull String packageName) {
if (!hasService()) {
return;
}
@@ -305,7 +312,7 @@
}
final Session newSession = createSessionByTokenLocked(activityToken,
- windowToken, appCallbackToken, hasCallback, flags);
+ windowToken, appCallbackToken, hasCallback, flags, packageName);
newSession.updateLocked(autofillId, bounds, value, FLAG_START_SESSION);
}
@@ -320,7 +327,13 @@
return;
}
- session.showSaveLocked();
+ final boolean finished = session.showSaveLocked();
+ if (DEBUG) {
+ Log.d(TAG, "finishSessionLocked(): session finished on save? " + finished);
+ }
+ if (finished) {
+ session.removeSelf();
+ }
}
void cancelSessionLocked(IBinder activityToken) {
@@ -333,14 +346,14 @@
Slog.w(TAG, "cancelSessionLocked(): no session for " + activityToken);
return;
}
-
- session.destroyLocked();
+ session.removeSelfLocked();
}
- private Session createSessionByTokenLocked(IBinder activityToken, IBinder windowToken,
- IBinder appCallbackToken, boolean hasCallback, int flags) {
+ private Session createSessionByTokenLocked(@NonNull IBinder activityToken,
+ @Nullable IBinder windowToken, @NonNull IBinder appCallbackToken, boolean hasCallback,
+ int flags, @NonNull String packageName) {
final Session newSession = new Session(mContext, activityToken,
- windowToken, appCallbackToken, hasCallback, flags);
+ windowToken, appCallbackToken, hasCallback, flags, packageName);
mSessions.put(activityToken, newSession);
/*
@@ -351,7 +364,6 @@
* - display disclosure if needed
*/
try {
- // TODO(b/33197203): add MetricsLogger call
final Bundle receiverExtras = new Bundle();
receiverExtras.putBinder(EXTRA_ACTIVITY_TOKEN, activityToken);
final long identity = Binder.clearCallingIdentity();
@@ -371,7 +383,6 @@
void updateSessionLocked(IBinder activityToken, AutofillId autofillId, Rect bounds,
AutofillValue value, int flags) {
- // TODO(b/33197203): add MetricsLogger call
final Session session = mSessions.get(activityToken);
if (session == null) {
if (VERBOSE) {
@@ -595,6 +606,9 @@
private final IBinder mActivityToken;
private final IBinder mWindowToken;
+ /** Package name of the app that is auto-filled */
+ @NonNull private final String mPackageName;
+
@GuardedBy("mLock")
private final Map<AutofillId, ViewState> mViewStates = new ArrayMap<>();
@@ -634,15 +648,16 @@
* Flags used to start the session.
*/
private int mFlags;
-
- private Session(Context context, IBinder activityToken, IBinder windowToken,
- IBinder client, boolean hasCallback, int flags) {
+ private Session(@NonNull Context context, @NonNull IBinder activityToken,
+ @Nullable IBinder windowToken, @NonNull IBinder client, boolean hasCallback,
+ int flags, @NonNull String packageName) {
mRemoteFillService = new RemoteFillService(context,
mInfo.getServiceInfo().getComponentName(), mUserId, this);
mActivityToken = activityToken;
mWindowToken = windowToken;
mHasCallback = hasCallback;
mFlags = flags;
+ mPackageName = packageName;
mClient = IAutoFillManagerClient.Stub.asInterface(client);
try {
@@ -656,41 +671,82 @@
} catch (RemoteException e) {
Slog.w(TAG, "linkToDeath() on mClient failed: " + e);
}
+
+ mMetricsLogger.action(MetricsProto.MetricsEvent.AUTOFILL_SESSION_STARTED, mPackageName);
}
// FillServiceCallbacks
@Override
- public void onFillRequestSuccess(FillResponse response) {
- // TODO(b/33197203): add MetricsLogger call
+ public void onFillRequestSuccess(@Nullable FillResponse response,
+ @NonNull String servicePackageName) {
if (response == null) {
+ // Nothing to be done, but need to notify client.
+ notifyUnavailableToClient();
removeSelf();
return;
}
+
+ if ((response.getDatasets() == null || response.getDatasets().isEmpty())
+ && response.getAuthentication() == null) {
+ // Response is "empty" from an UI point of view, need to notify client.
+ notifyUnavailableToClient();
+ }
synchronized (mLock) {
processResponseLocked(response);
}
+
+ LogMaker log = (new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_REQUEST))
+ .setType(MetricsProto.MetricsEvent.TYPE_SUCCESS)
+ .setPackageName(mPackageName)
+ .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS,
+ response.getDatasets() == null ? 0 : response.getDatasets().size())
+ .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_SERVICE,
+ servicePackageName);
+ mMetricsLogger.write(log);
}
// FillServiceCallbacks
@Override
- public void onFillRequestFailure(CharSequence message) {
- // TODO(b/33197203): add MetricsLogger call
+ public void onFillRequestFailure(@Nullable CharSequence message,
+ @NonNull String servicePackageName) {
+ LogMaker log = (new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_REQUEST))
+ .setType(MetricsProto.MetricsEvent.TYPE_FAILURE)
+ .setPackageName(mPackageName)
+ .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_SERVICE,
+ servicePackageName);
+ mMetricsLogger.write(log);
+
getUiForShowing().showError(message);
removeSelf();
}
// FillServiceCallbacks
@Override
- public void onSaveRequestSuccess() {
- // TODO(b/33197203): add MetricsLogger call
+ public void onSaveRequestSuccess(@NonNull String servicePackageName) {
+ LogMaker log = (new LogMaker(
+ MetricsProto.MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST))
+ .setType(MetricsProto.MetricsEvent.TYPE_SUCCESS)
+ .setPackageName(mPackageName)
+ .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_SERVICE,
+ servicePackageName);
+ mMetricsLogger.write(log);
+
// Nothing left to do...
removeSelf();
}
// FillServiceCallbacks
@Override
- public void onSaveRequestFailure(CharSequence message) {
- // TODO(b/33197203): add MetricsLogger call
+ public void onSaveRequestFailure(@Nullable CharSequence message,
+ @NonNull String servicePackageName) {
+ LogMaker log = (new LogMaker(
+ MetricsProto.MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST))
+ .setType(MetricsProto.MetricsEvent.TYPE_FAILURE)
+ .setPackageName(mPackageName)
+ .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_SERVICE,
+ servicePackageName);
+ mMetricsLogger.write(log);
+
getUiForShowing().showError(message);
removeSelf();
}
@@ -702,9 +758,7 @@
synchronized (mLock) {
fillInIntent = createAuthFillInIntent(mStructure);
}
- mHandlerCaller.getHandler().post(() -> {
- startAuthentication(intent, fillInIntent);
- });
+ mHandlerCaller.getHandler().post(() -> startAuthentication(intent, fillInIntent));
}
// FillServiceCallbacks
@@ -724,8 +778,7 @@
Binder.restoreCallingIdentity(identity);
}
synchronized (mLock) {
- destroyLocked();
- mSessions.remove(this);
+ removeSelfLocked();
}
}
@@ -738,9 +791,7 @@
// AutoFillUiCallback
@Override
public void fill(Dataset dataset) {
- mHandlerCaller.getHandler().post(() -> {
- autoFill(dataset);
- });
+ mHandlerCaller.getHandler().post(() -> autoFill(dataset));
}
// AutoFillUiCallback
@@ -753,17 +804,13 @@
// AutoFillUiCallback
@Override
public void cancelSave() {
- mHandlerCaller.getHandler().post(() -> {
- removeSelf();
- });
+ mHandlerCaller.getHandler().post(() -> removeSelf());
}
// AutoFillUiCallback
@Override
public void onEvent(AutofillId id, int event) {
- mHandlerCaller.getHandler().post(() -> {
- notifyChangeToClient(id, event);
- });
+ mHandlerCaller.getHandler().post(() -> notifyChangeToClient(id, event));
}
public void setAuthenticationResultLocked(Bundle data) {
@@ -773,6 +820,9 @@
Parcelable result = data.getParcelable(
AutofillManager.EXTRA_AUTHENTICATION_RESULT);
if (result instanceof FillResponse) {
+ mMetricsLogger.action(MetricsProto.MetricsEvent.AUTOFILL_AUTHENTICATED,
+ mPackageName);
+
mCurrentResponse = (FillResponse) result;
processResponseLocked(mCurrentResponse);
} else if (result instanceof Dataset) {
@@ -790,12 +840,14 @@
}
/**
- * Show the save UI, when session can be saved.
+ * Shows the save UI, when session can be saved.
+ *
+ * @return {@code true} if session is done, or {@code false} if it's pending user action.
*/
- public void showSaveLocked() {
+ public boolean showSaveLocked() {
if (mStructure == null) {
Slog.wtf(TAG, "showSaveLocked(): no mStructure");
- return;
+ return true;
}
if (mCurrentResponse == null) {
// Happens when the activity / session was finished before the service replied, or
@@ -803,7 +855,7 @@
if (DEBUG) {
Slog.d(TAG, "showSaveLocked(): no mCurrentResponse");
}
- return;
+ return true;
}
final SaveInfo saveInfo = mCurrentResponse.getSaveInfo();
if (DEBUG) {
@@ -819,13 +871,13 @@
*/
if (saveInfo == null) {
- return;
+ return true;
}
final AutofillId[] requiredIds = saveInfo.getRequiredIds();
if (requiredIds == null || requiredIds.length == 0) {
Slog.w(TAG, "showSaveLocked(): no required ids on saveInfo");
- return;
+ return true;
}
boolean allRequiredAreNotEmpty = true;
@@ -894,8 +946,8 @@
if (atLeastOneChanged) {
getUiForShowing().showSaveUi(
mInfo.getServiceInfo().loadLabel(mContext.getPackageManager()),
- saveInfo);
- return;
+ saveInfo, mPackageName);
+ return false;
}
}
// Nothing changed...
@@ -904,7 +956,7 @@
+ "allRequiredAreNotNull=" + allRequiredAreNotEmpty
+ ", atLeastOneChanged=" + atLeastOneChanged);
}
- removeSelf();
+ return true;
}
/**
@@ -946,7 +998,7 @@
mStructure.dump();
}
- mRemoteFillService.onSaveRequest(mStructure, extras);
+ mRemoteFillService.onSaveRequest(mStructure, extras, () -> removeSelf());
}
void updateLocked(AutofillId id, Rect bounds, AutofillValue value, int flags) {
@@ -1034,7 +1086,7 @@
filterText = value.getTextValue().toString();
}
- getUiForShowing().showFillUi(filledId, response, bounds, filterText);
+ getUiForShowing().showFillUi(filledId, response, bounds, filterText, mPackageName);
}
private void notifyChangeToClient(AutofillId id, int event) {
@@ -1046,17 +1098,24 @@
}
}
+ private void notifyUnavailableToClient() {
+ if (mCurrentViewState == null) {
+ // TODO(b/33197203): temporary sanity check; should never happen
+ Slog.w(TAG, "notifyUnavailable(): mCurrentViewState is null");
+ return;
+ }
+ notifyChangeToClient(mCurrentViewState.mId, AutofillCallback.EVENT_INPUT_UNAVAILABLE);
+ }
+
private void processResponseLocked(FillResponse response) {
if (DEBUG) {
Slog.d(TAG, "processResponseLocked(auth=" + response.getAuthentication()
+ "):" + response);
}
- // TODO(b/33197203): add MetricsLogger calls
-
if (mCurrentViewState == null) {
// TODO(b/33197203): temporary sanity check; should never happen
- Slog.w(TAG, "processResponseLocked(): mCurrentResponse is null");
+ Slog.w(TAG, "processResponseLocked(): mCurrentViewState is null");
return;
}
@@ -1188,17 +1247,23 @@
private void destroyLocked() {
mRemoteFillService.destroy();
mUi.setCallback(null, null);
+
+ mMetricsLogger.action(MetricsProto.MetricsEvent.AUTOFILL_SESSION_FINISHED,
+ mPackageName);
}
- private void removeSelf() {
- if (VERBOSE) {
- Slog.v(TAG, "removeSelf()");
- }
-
+ void removeSelf() {
synchronized (mLock) {
- destroyLocked();
- mSessions.remove(mActivityToken);
+ removeSelfLocked();
}
}
+
+ private void removeSelfLocked() {
+ if (VERBOSE) {
+ Slog.v(TAG, "removeSelfLocked()");
+ }
+ destroyLocked();
+ mSessions.remove(mActivityToken);
+ }
}
}
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index b1cc89b..d1c8b4f8 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -16,6 +16,8 @@
package com.android.server.autofill;
+import static com.android.server.autofill.Helper.DEBUG;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.assist.AssistStructure;
@@ -38,8 +40,10 @@
import android.service.autofill.ISaveCallback;
import android.text.format.DateUtils;
import android.util.Slog;
+
import com.android.internal.os.HandlerCaller;
import com.android.server.FgThread;
+import com.android.server.autofill.AutofillManagerServiceImpl.Session;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
@@ -55,8 +59,6 @@
final class RemoteFillService implements DeathRecipient {
private static final String LOG_TAG = "RemoteFillService";
- private static final boolean DEBUG = Helper.DEBUG;
-
// How long after the last interaction with the service we would unbind
private static final long TIMEOUT_IDLE_BIND_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS;
@@ -87,10 +89,10 @@
private PendingRequest mPendingRequest;
public interface FillServiceCallbacks {
- void onFillRequestSuccess(FillResponse response);
- void onFillRequestFailure(CharSequence message);
- void onSaveRequestSuccess();
- void onSaveRequestFailure(CharSequence message);
+ void onFillRequestSuccess(@Nullable FillResponse response, @NonNull String servicePackageName);
+ void onFillRequestFailure(@Nullable CharSequence message, @NonNull String servicePackageName);
+ void onSaveRequestSuccess(@NonNull String servicePackageName);
+ void onSaveRequestFailure(@Nullable CharSequence message, @NonNull String servicePackageName);
void onServiceDied(RemoteFillService service);
void onDisableSelf();
}
@@ -139,9 +141,10 @@
mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, request).sendToTarget();
}
- public void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle extras) {
+ public void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle extras,
+ @Nullable Runnable finalizer) {
cancelScheduledUnbind();
- final PendingSaveRequest request = new PendingSaveRequest(structure, extras, this);
+ final PendingSaveRequest request = new PendingSaveRequest(structure, extras, this, finalizer);
mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, request).sendToTarget();
}
@@ -262,7 +265,7 @@
FillResponse response) {
mHandler.getHandler().post(() -> {
if (handleResponseCallbackCommon(pendingRequest)) {
- mCallbacks.onFillRequestSuccess(response);
+ mCallbacks.onFillRequestSuccess(response, mComponentName.getPackageName());
}
});
}
@@ -271,7 +274,7 @@
CharSequence message) {
mHandler.getHandler().post(() -> {
if (handleResponseCallbackCommon(pendingRequest)) {
- mCallbacks.onFillRequestFailure(message);
+ mCallbacks.onFillRequestFailure(message, mComponentName.getPackageName());
}
});
}
@@ -279,7 +282,7 @@
private void dispatchOnSaveRequestSuccess(PendingRequest pendingRequest) {
mHandler.getHandler().post(() -> {
if (handleResponseCallbackCommon(pendingRequest)) {
- mCallbacks.onSaveRequestSuccess();
+ mCallbacks.onSaveRequestSuccess(mComponentName.getPackageName());
}
});
}
@@ -288,7 +291,7 @@
CharSequence message) {
mHandler.getHandler().post(() -> {
if (handleResponseCallbackCommon(pendingRequest)) {
- mCallbacks.onSaveRequestFailure(message);
+ mCallbacks.onSaveRequestFailure(message, mComponentName.getPackageName());
}
});
}
@@ -414,8 +417,8 @@
private static final class PendingFillRequest extends PendingRequest {
private final Object mLock = new Object();
private final WeakReference<RemoteFillService> mWeakService;
- private AssistStructure mStructure;
- private Bundle mExtras;
+ private final AssistStructure mStructure;
+ private final Bundle mExtras;
private final IFillCallback mCallback;
private ICancellationSignal mCancellation;
private boolean mCancelled;
@@ -473,10 +476,6 @@
try {
remoteService.mAutoFillService.onFillRequest(mStructure,
mExtras, mCallback, mFlags);
- synchronized (mLock) {
- mStructure = null;
- mExtras = null;
- }
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Error calling on fill request", e);
cancel();
@@ -506,17 +505,18 @@
}
private static final class PendingSaveRequest extends PendingRequest {
- private final Object mLock = new Object();
private final WeakReference<RemoteFillService> mWeakService;
- private AssistStructure mStructure;
- private Bundle mExtras;
+ private final AssistStructure mStructure;
+ private final Bundle mExtras;
private final ISaveCallback mCallback;
+ private final Runnable mFinalizer;
- public PendingSaveRequest(@NonNull AssistStructure structure,
- @Nullable Bundle extras, @NonNull RemoteFillService service) {
+ public PendingSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle extras,
+ @NonNull RemoteFillService service, @Nullable Runnable finalizer) {
mStructure = structure;
mExtras = extras;
mWeakService = new WeakReference<>(service);
+ mFinalizer = finalizer;
mCallback = new ISaveCallback.Stub() {
@Override
public void onSuccess() {
@@ -540,19 +540,17 @@
@Override
public void run() {
- RemoteFillService service = mWeakService.get();
+ final RemoteFillService service = mWeakService.get();
if (service != null) {
try {
- service.mAutoFillService.onSaveRequest(mStructure,
- mExtras, mCallback);
- synchronized (mLock) {
- mStructure = null;
- mExtras = null;
- }
+ service.mAutoFillService.onSaveRequest(mStructure, mExtras, mCallback);
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Error calling on save request", e);
}
}
+ if (mFinalizer != null) {
+ mFinalizer.run();
+ }
}
@Override
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 c7e59a3..776fa1e 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.content.IntentSender;
import android.graphics.Rect;
+import android.metrics.LogMaker;
import android.os.Handler;
import android.os.IBinder;
import android.service.autofill.Dataset;
@@ -34,6 +35,8 @@
import android.view.autofill.AutofillId;
import android.widget.Toast;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.server.UiThread;
import java.io.PrintWriter;
@@ -60,6 +63,7 @@
private @Nullable IBinder mWindowToken;
private int mSaveTimeoutMs = (int) (5 * DateUtils.SECOND_IN_MILLIS);
+ private final MetricsLogger mMetricsLogger = new MetricsLogger();
public interface AutoFillUiCallback {
void authenticate(@NonNull IntentSender intent);
@@ -152,9 +156,17 @@
* @param response the current fill response
* @param anchorBounds bounds of the focused view
* @param filterText text of the view to be filled
+ * @param packageName package name of the activity that is filled
*/
public void showFillUi(@NonNull AutofillId focusedId, @NonNull FillResponse response,
- @NonNull Rect anchorBounds, @Nullable String filterText) {
+ @NonNull Rect anchorBounds, @Nullable String filterText, @NonNull String packageName) {
+ LogMaker log = (new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_FILL_UI))
+ .setPackageName(packageName)
+ .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_FILTERTEXT_LEN,
+ filterText == null ? 0 : filterText.length())
+ .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS,
+ response.getDatasets() == null ? 0 : response.getDatasets().size());
+
mHandler.post(() -> {
if (!hasCallback()) {
return;
@@ -164,6 +176,7 @@
mWindowToken, anchorBounds, filterText, new FillUi.Callback() {
@Override
public void onResponsePicked(FillResponse response) {
+ log.setType(MetricsProto.MetricsEvent.TYPE_DETAIL);
hideFillUiUiThread();
if (mCallback != null) {
mCallback.authenticate(response.getAuthentication());
@@ -172,17 +185,25 @@
@Override
public void onDatasetPicked(Dataset dataset) {
+ log.setType(MetricsProto.MetricsEvent.TYPE_ACTION);
hideFillUiUiThread();
if (mCallback != null) {
mCallback.fill(dataset);
}
- // TODO(b/33197203): add MetricsLogger call
}
@Override
public void onCanceled() {
+ log.setType(MetricsProto.MetricsEvent.TYPE_DISMISS);
hideFillUiUiThread();
- // TODO(b/33197203): add MetricsLogger call
+ }
+
+ @Override
+ public void onDestroy() {
+ if (log.getType() == MetricsProto.MetricsEvent.TYPE_UNKNOWN) {
+ log.setType(MetricsProto.MetricsEvent.TYPE_CLOSE);
+ }
+ mMetricsLogger.write(log);
}
});
mCallback.onEvent(focusedId, EVENT_INPUT_SHOWN);
@@ -192,7 +213,16 @@
/**
* Shows the UI asking the user to save for autofill.
*/
- public void showSaveUi(@NonNull CharSequence providerLabel, @NonNull SaveInfo info) {
+ public void showSaveUi(@NonNull CharSequence providerLabel, @NonNull SaveInfo info,
+ @NonNull String packageName) {
+ int numIds = 0;
+ numIds += info.getRequiredIds() == null ? 0 : info.getRequiredIds().length;
+ numIds += info.getOptionalIds() == null ? 0 : info.getOptionalIds().length;
+
+ LogMaker log = (new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_SAVE_UI))
+ .setPackageName(packageName).addTaggedData(
+ MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_IDS, numIds);
+
mHandler.post(() -> {
if (!hasCallback()) {
return;
@@ -202,16 +232,16 @@
new SaveUi.OnSaveListener() {
@Override
public void onSave() {
+ log.setType(MetricsProto.MetricsEvent.TYPE_ACTION);
hideSaveUiUiThread();
if (mCallback != null) {
mCallback.save();
}
- // TODO(b/33197203): add MetricsLogger call
}
@Override
public void onCancel(IntentSender listener) {
- // TODO(b/33197203): add MetricsLogger call
+ log.setType(MetricsProto.MetricsEvent.TYPE_DISMISS);
hideSaveUiUiThread();
if (listener != null) {
try {
@@ -225,6 +255,14 @@
mCallback.cancelSave();
}
}
+
+ @Override
+ public void onDestroy() {
+ if (log.getType() == MetricsProto.MetricsEvent.TYPE_UNKNOWN) {
+ log.setType(MetricsProto.MetricsEvent.TYPE_CLOSE);
+ }
+ mMetricsLogger.write(log);
+ }
}, mSaveTimeoutMs);
});
}
@@ -247,11 +285,17 @@
}
public void dump(PrintWriter pw) {
- pw.println("AufoFill UI");
+ pw.println("Autofill UI");
final String prefix = " ";
- pw.print(prefix); pw.print("showsFillUi: "); pw.println(mFillUi != null);
+ final String prefix2 = " ";
pw.print(prefix); pw.print("showsSaveUi: "); pw.println(mSaveUi != null);
pw.print(prefix); pw.print("save timeout: "); pw.println(mSaveTimeoutMs);
+ if (mFillUi != null) {
+ pw.print(prefix); pw.println("showsFillUi: true");
+ mFillUi.dump(pw, prefix2);
+ } else {
+ pw.print(prefix); pw.println("showsFillUi: false");
+ }
}
@android.annotation.UiThread
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index a7d9fe9..a8c8752 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -39,6 +39,7 @@
import com.android.internal.R;
import libcore.util.Objects;
+import java.io.PrintWriter;
import java.util.ArrayList;
final class FillUi {
@@ -50,6 +51,7 @@
void onResponsePicked(@NonNull FillResponse response);
void onDatasetPicked(@NonNull Dataset dataset);
void onCanceled();
+ void onDestroy();
}
private final Rect mAnchorBounds = new Rect();
@@ -63,6 +65,7 @@
private final @Nullable ArrayAdapter<ViewItem> mAdapter;
private @Nullable String mFilterText;
+ private final String mAccessibilityTitle;
private int mContentWidth;
private int mContentHeight;
@@ -76,6 +79,8 @@
mAnchorBounds.set(anchorBounds);
mCallback = callback;
+ mAccessibilityTitle = context.getString(R.string.autofill_picker_accessibility_title);
+
if (response.getAuthentication() != null) {
mListView = null;
mAdapter = null;
@@ -201,6 +206,7 @@
public void destroy() {
throwIfDestroyed();
+ mCallback.onDestroy();
mWindow.hide();
mDestroyed = true;
}
@@ -319,6 +325,7 @@
public void show(int desiredWidth, int desiredHeight, Rect anchorBounds) {
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
+
params.setTitle("FillUi");
params.token = mActivityToken;
params.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
@@ -327,6 +334,7 @@
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+ params.accessibilityTitle = mAccessibilityTitle;
mWm.getDefaultDisplay().getRealSize(mTempPoint);
final int screenWidth = mTempPoint.x;
@@ -377,4 +385,16 @@
}
}
}
+
+ public void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.print("mAnchorBounds: "); pw.println(mAnchorBounds);
+ pw.print(prefix); pw.print("mCallback: "); pw.println(mCallback != null);
+ pw.print(prefix); pw.print("mListView: "); pw.println(mListView);
+ pw.print(prefix); pw.print("mAdapter: "); pw.println(mAdapter != null);
+ pw.print(prefix); pw.print("mFilterText: "); pw.println(mFilterText);
+ pw.print(prefix); pw.print("mAccessibilityTitle: "); pw.println(mAccessibilityTitle);
+ pw.print(prefix); pw.print("mContentWidth: "); pw.println(mContentWidth);
+ pw.print(prefix); pw.print("mContentHeight: "); pw.println(mContentHeight);
+ pw.print(prefix); pw.print("mDestroyed: "); pw.println(mDestroyed);
+ }
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/Helper.java b/services/autofill/java/com/android/server/autofill/ui/Helper.java
new file mode 100644
index 0000000..996e421
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/ui/Helper.java
@@ -0,0 +1,26 @@
+/*
+ * 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.autofill.ui;
+
+final class Helper {
+
+ static final boolean DEBUG = true; // TODO(b/33197203): set to false when stable
+ static final boolean VERBOSE = false;
+ private Helper() {
+ throw new UnsupportedOperationException("contains static members only");
+ }
+}
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index 3f409ad..509351b 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -16,6 +16,8 @@
package com.android.server.autofill.ui;
+import static com.android.server.autofill.ui.Helper.DEBUG;
+
import android.annotation.NonNull;
import android.app.Dialog;
import android.content.Context;
@@ -23,6 +25,7 @@
import android.os.Handler;
import android.service.autofill.SaveInfo;
import android.text.format.DateUtils;
+import android.util.Slog;
import android.view.Gravity;
import android.view.Window;
import android.view.WindowManager;
@@ -37,22 +40,66 @@
* Autofill Save Prompt
*/
final class SaveUi {
+
+ private static final String TAG = "SaveUi";
+
public interface OnSaveListener {
void onSave();
void onCancel(IntentSender listener);
+ void onDestroy();
+ }
+
+ private class OneTimeListener implements OnSaveListener {
+
+ private final OnSaveListener mRealListener;
+ private boolean mDone;
+
+ OneTimeListener(OnSaveListener realListener) {
+ mRealListener = realListener;
+ }
+
+ @Override
+ public void onSave() {
+ if (DEBUG) Slog.d(TAG, "onSave(): " + mDone);
+ if (mDone) {
+ return;
+ }
+ mDone = true;
+ mRealListener.onSave();
+ }
+
+ @Override
+ public void onCancel(IntentSender listener) {
+ if (DEBUG) Slog.d(TAG, "onCancel(): " + mDone);
+ if (mDone) {
+ return;
+ }
+ mDone = true;
+ mRealListener.onCancel(listener);
+ }
+
+ @Override
+ public void onDestroy() {
+ if (DEBUG) Slog.d(TAG, "onDestroy(): " + mDone);
+ if (mDone) {
+ return;
+ }
+ mDone = true;
+ mRealListener.onDestroy();
+ }
}
private final Handler mHandler = UiThread.getHandler();
private final @NonNull Dialog mDialog;
- private final @NonNull OnSaveListener mListener;
+ private final @NonNull OneTimeListener mListener;
private boolean mDestroyed;
SaveUi(@NonNull Context context, @NonNull CharSequence providerLabel, @NonNull SaveInfo info,
@NonNull OnSaveListener listener, int lifeTimeMs) {
- mListener = listener;
+ mListener = new OneTimeListener(listener);
final LayoutInflater inflater = LayoutInflater.from(context);
final View view = inflater.inflate(R.layout.autofill_save, null);
@@ -117,11 +164,17 @@
mDialog.show();
- mHandler.postDelayed(() -> mListener.onCancel(null), lifeTimeMs);
+ mHandler.postDelayed(() -> {
+ if (!mListener.mDone) {
+ mListener.onCancel(null);
+ Slog.d(TAG, "Save snackbar timed out after " + lifeTimeMs + "ms");
+ }
+ }, lifeTimeMs);
}
void destroy() {
throwIfDestroyed();
+ mListener.onDestroy();
mHandler.removeCallbacksAndMessages(mListener);
mDialog.dismiss();
mDestroyed = true;
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 1864d34..794ece6 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -23,7 +23,9 @@
android.hardware.power@1.0-java \
android.hardware.tv.cec@1.0-java
-LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update2 \
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ tzdata_shared2 \
+ tzdata_update2 \
android.hidl.base@1.0-java-static \
android.hardware.biometrics.fingerprint@2.1-java-static \
diff --git a/services/core/java/com/android/server/BackgroundDexOptJobService.java b/services/core/java/com/android/server/BackgroundDexOptJobService.java
deleted file mode 100644
index 69e6ac5..0000000
--- a/services/core/java/com/android/server/BackgroundDexOptJobService.java
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT;
-
-import android.app.job.JobInfo;
-import android.app.job.JobParameters;
-import android.app.job.JobScheduler;
-import android.app.job.JobService;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.BatteryManager;
-import android.os.Environment;
-import android.os.ServiceManager;
-import android.os.storage.StorageManager;
-import android.util.ArraySet;
-import android.util.Log;
-import com.android.server.pm.PackageManagerService;
-
-import java.io.File;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.TimeUnit;
-
-public class BackgroundDexOptJobService extends JobService {
- private static final String TAG = "BackgroundDexOptJobService";
-
- private static final boolean DEBUG = false;
-
- private static final int JOB_IDLE_OPTIMIZE = 800;
- private static final int JOB_POST_BOOT_UPDATE = 801;
-
- private static final long IDLE_OPTIMIZATION_PERIOD = DEBUG
- ? TimeUnit.MINUTES.toMillis(1)
- : TimeUnit.DAYS.toMillis(1);
-
- private static ComponentName sDexoptServiceName = new ComponentName(
- "android",
- BackgroundDexOptJobService.class.getName());
-
- /**
- * Set of failed packages remembered across job runs.
- */
- static final ArraySet<String> sFailedPackageNames = new ArraySet<String>();
-
- /**
- * Atomics set to true if the JobScheduler requests an abort.
- */
- final AtomicBoolean mAbortPostBootUpdate = new AtomicBoolean(false);
- final AtomicBoolean mAbortIdleOptimization = new AtomicBoolean(false);
-
- /**
- * Atomic set to true if one job should exit early because another job was started.
- */
- final AtomicBoolean mExitPostBootUpdate = new AtomicBoolean(false);
-
- private final File mDataDir = Environment.getDataDirectory();
-
- public static void schedule(Context context) {
- JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
-
- // Schedule a one-off job which scans installed packages and updates
- // out-of-date oat files.
- js.schedule(new JobInfo.Builder(JOB_POST_BOOT_UPDATE, sDexoptServiceName)
- .setMinimumLatency(TimeUnit.MINUTES.toMillis(1))
- .setOverrideDeadline(TimeUnit.MINUTES.toMillis(1))
- .build());
-
- // Schedule a daily job which scans installed packages and compiles
- // those with fresh profiling data.
- js.schedule(new JobInfo.Builder(JOB_IDLE_OPTIMIZE, sDexoptServiceName)
- .setRequiresDeviceIdle(true)
- .setRequiresCharging(true)
- .setPeriodic(IDLE_OPTIMIZATION_PERIOD)
- .build());
-
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Jobs scheduled");
- }
- }
-
- public static void notifyPackageChanged(String packageName) {
- // The idle maintanance job skips packages which previously failed to
- // compile. The given package has changed and may successfully compile
- // now. Remove it from the list of known failing packages.
- synchronized (sFailedPackageNames) {
- sFailedPackageNames.remove(packageName);
- }
- }
-
- // Returns the current battery level as a 0-100 integer.
- private int getBatteryLevel() {
- IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
- Intent intent = registerReceiver(null, filter);
- int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
- int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
-
- if (level < 0 || scale <= 0) {
- // Battery data unavailable. This should never happen, so assume the worst.
- return 0;
- }
-
- return (100 * level / scale);
- }
-
- private long getLowStorageThreshold() {
- @SuppressWarnings("deprecation")
- final long lowThreshold = StorageManager.from(this).getStorageLowBytes(mDataDir);
- if (lowThreshold == 0) {
- Log.e(TAG, "Invalid low storage threshold");
- }
-
- return lowThreshold;
- }
-
- private boolean runPostBootUpdate(final JobParameters jobParams,
- final PackageManagerService pm, final ArraySet<String> pkgs) {
- if (mExitPostBootUpdate.get()) {
- // This job has already been superseded. Do not start it.
- return false;
- }
- new Thread("BackgroundDexOptService_PostBootUpdate") {
- @Override
- public void run() {
- postBootUpdate(jobParams, pm, pkgs);
- }
-
- }.start();
- return true;
- }
-
- private void postBootUpdate(JobParameters jobParams, PackageManagerService pm,
- ArraySet<String> pkgs) {
- // Load low battery threshold from the system config. This is a 0-100 integer.
- final int lowBatteryThreshold = getResources().getInteger(
- com.android.internal.R.integer.config_lowBatteryWarningLevel);
- final long lowThreshold = getLowStorageThreshold();
-
- mAbortPostBootUpdate.set(false);
-
- for (String pkg : pkgs) {
- if (mAbortPostBootUpdate.get()) {
- // JobScheduler requested an early abort.
- return;
- }
- if (mExitPostBootUpdate.get()) {
- // Different job, which supersedes this one, is running.
- break;
- }
- if (getBatteryLevel() < lowBatteryThreshold) {
- // Rather bail than completely drain the battery.
- break;
- }
- long usableSpace = mDataDir.getUsableSpace();
- if (usableSpace < lowThreshold) {
- // Rather bail than completely fill up the disk.
- Log.w(TAG, "Aborting background dex opt job due to low storage: " +
- usableSpace);
- break;
- }
-
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Updating package " + pkg);
- }
-
- // Update package if needed. Note that there can be no race between concurrent
- // jobs because PackageDexOptimizer.performDexOpt is synchronized.
-
- // checkProfiles is false to avoid merging profiles during boot which
- // might interfere with background compilation (b/28612421).
- // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will
- // behave differently than "pm.dexopt.bg-dexopt=speed-profile" but that's a
- // trade-off worth doing to save boot time work.
- pm.performDexOpt(pkg,
- /* checkProfiles */ false,
- PackageManagerService.REASON_BOOT,
- /* force */ false);
- }
- // Ran to completion, so we abandon our timeslice and do not reschedule.
- jobFinished(jobParams, /* reschedule */ false);
- }
-
- private boolean runIdleOptimization(final JobParameters jobParams,
- final PackageManagerService pm, final ArraySet<String> pkgs) {
- new Thread("BackgroundDexOptService_IdleOptimization") {
- @Override
- public void run() {
- idleOptimization(jobParams, pm, pkgs);
- }
- }.start();
- return true;
- }
-
- private void idleOptimization(JobParameters jobParams, PackageManagerService pm,
- ArraySet<String> pkgs) {
- Log.i(TAG, "Performing idle optimizations");
- // If post-boot update is still running, request that it exits early.
- mExitPostBootUpdate.set(true);
-
- mAbortIdleOptimization.set(false);
-
- final long lowThreshold = getLowStorageThreshold();
- for (String pkg : pkgs) {
- if (mAbortIdleOptimization.get()) {
- // JobScheduler requested an early abort.
- return;
- }
-
- synchronized (sFailedPackageNames) {
- if (sFailedPackageNames.contains(pkg)) {
- // Skip previously failing package
- continue;
- }
- }
-
- long usableSpace = mDataDir.getUsableSpace();
- if (usableSpace < lowThreshold) {
- // Rather bail than completely fill up the disk.
- Log.w(TAG, "Aborting background dex opt job due to low storage: " +
- usableSpace);
- break;
- }
-
- // Conservatively add package to the list of failing ones in case performDexOpt
- // never returns.
- synchronized (sFailedPackageNames) {
- sFailedPackageNames.add(pkg);
- }
- // Optimize package if needed. Note that there can be no race between
- // concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized.
- if (pm.performDexOpt(pkg,
- /* checkProfiles */ true,
- PackageManagerService.REASON_BACKGROUND_DEXOPT,
- /* force */ false)) {
- // Dexopt succeeded, remove package from the list of failing ones.
- synchronized (sFailedPackageNames) {
- sFailedPackageNames.remove(pkg);
- }
- }
- }
- // Ran to completion, so we abandon our timeslice and do not reschedule.
- jobFinished(jobParams, /* reschedule */ false);
- }
-
- @Override
- public boolean onStartJob(JobParameters params) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "onStartJob");
- }
-
- // NOTE: PackageManagerService.isStorageLow uses a different set of criteria from
- // the checks above. This check is not "live" - the value is determined by a background
- // restart with a period of ~1 minute.
- PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package");
- if (pm.isStorageLow()) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Low storage, skipping this run");
- }
- return false;
- }
-
- final ArraySet<String> pkgs = pm.getOptimizablePackages();
- if (pkgs == null || pkgs.isEmpty()) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "No packages to optimize");
- }
- return false;
- }
-
- if (params.getJobId() == JOB_POST_BOOT_UPDATE) {
- return runPostBootUpdate(params, pm, pkgs);
- } else {
- return runIdleOptimization(params, pm, pkgs);
- }
- }
-
- @Override
- public boolean onStopJob(JobParameters params) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "onStopJob");
- }
-
- if (params.getJobId() == JOB_POST_BOOT_UPDATE) {
- mAbortPostBootUpdate.set(true);
- } else {
- mAbortIdleOptimization.set(true);
- }
- return false;
- }
-}
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 34c73d2..c946d09 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -1488,7 +1488,7 @@
return VerifyCredentialResponse.OK;
}
- if (TextUtils.isEmpty(credential)) {
+ if (storedHash == null || TextUtils.isEmpty(credential)) {
return VerifyCredentialResponse.ERROR;
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 3667ecd..8e6310f 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2721,7 +2721,7 @@
*/
@Override
public int getPasswordType() {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL,
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
"no permission to access the crypt keeper");
waitForReady();
@@ -2747,7 +2747,7 @@
*/
@Override
public void setField(String field, String contents) throws RemoteException {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL,
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
"no permission to access the crypt keeper");
waitForReady();
@@ -2767,7 +2767,7 @@
*/
@Override
public String getField(String field) throws RemoteException {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL,
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
"no permission to access the crypt keeper");
waitForReady();
@@ -2793,7 +2793,7 @@
*/
@Override
public boolean isConvertibleToFBE() throws RemoteException {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL,
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
"no permission to access the crypt keeper");
waitForReady();
@@ -2809,7 +2809,7 @@
@Override
public String getPassword() throws RemoteException {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL,
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
"only keyguard can retrieve password");
if (!isReady()) {
@@ -2834,7 +2834,7 @@
@Override
public void clearPassword() throws RemoteException {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL,
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
"only keyguard can clear password");
if (!isReady()) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index accae0d..f954f75 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -35,7 +35,6 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityThread;
-import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.INotificationManager;
import android.app.Notification;
@@ -64,7 +63,6 @@
import android.content.pm.UserInfo;
import android.database.Cursor;
import android.database.sqlite.SQLiteStatement;
-import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
@@ -80,7 +78,6 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
-import android.os.storage.StorageManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
@@ -113,7 +110,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@@ -158,6 +154,11 @@
public void onUnlockUser(int userHandle) {
mService.onUnlockUser(userHandle);
}
+
+ @Override
+ public void onCleanupUser(int userHandle) {
+ mService.onCleanupUser(userHandle);
+ }
}
final Context mContext;
@@ -303,18 +304,6 @@
}
}, intentFilter);
- IntentFilter userFilter = new IntentFilter();
- userFilter.addAction(Intent.ACTION_USER_REMOVED);
- mContext.registerReceiverAsUser(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (Intent.ACTION_USER_REMOVED.equals(action)) {
- onUserRemoved(intent);
- }
- }
- }, UserHandle.ALL, userFilter, null, null);
-
injector.addLocalService(new AccountManagerInternalImpl());
// Need to cancel account request notifications if the update/install can access the account
@@ -1133,16 +1122,12 @@
}
}
- private void onUserRemoved(Intent intent) {
- int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
- if (userId < 1) return;
-
+ private void onCleanupUser(int userId) {
+ Log.i(TAG, "onCleanupUser " + userId);
UserAccounts accounts;
- boolean userUnlocked;
synchronized (mUsers) {
accounts = mUsers.get(userId);
mUsers.remove(userId);
- userUnlocked = mLocalUnlockedUsers.get(userId);
mLocalUnlockedUsers.delete(userId);
}
if (accounts != null) {
@@ -1150,18 +1135,6 @@
accounts.accountsDb.close();
}
}
- Log.i(TAG, "Removing database files for user " + userId);
- File dbFile = new File(mInjector.getDeDatabaseName(userId));
-
- AccountsDb.deleteDbFileWarnIfFailed(dbFile);
- // Remove CE file if user is unlocked, or FBE is not enabled
- boolean fbeEnabled = StorageManager.isFileEncryptedNativeOrEmulated();
- if (!fbeEnabled || userUnlocked) {
- File ceDb = new File(mInjector.getCeDatabaseName(userId));
- if (ceDb.exists()) {
- AccountsDb.deleteDbFileWarnIfFailed(ceDb);
- }
- }
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 100d821..df250b1 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -105,16 +105,16 @@
}
private void updateConstants() {
+ final String setting = Settings.Global.getString(mResolver,
+ Settings.Global.ACTIVITY_MANAGER_CONSTANTS);
synchronized (mService) {
try {
- mParser.setString(Settings.Global.getString(mResolver,
- Settings.Global.ACTIVITY_MANAGER_CONSTANTS));
+ mParser.setString(setting);
} catch (IllegalArgumentException e) {
// Failed to parse the settings string, log this and move on
// with defaults.
Slog.e("ActivityManagerConstants", "Bad activity manager config settings", e);
}
-
ENFORCE_BG_CHECK = mParser.getBoolean(KEY_ENFORCE_BG_CHECK, DEFAULT_ENFORCE_BG_CHECK);
MAX_CACHED_PROCESSES = mParser.getInt(KEY_MAX_CACHED_PROCESSES,
DEFAULT_MAX_CACHED_PROCESSES);
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index ebbce02..918747b 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -251,7 +251,8 @@
* ActivityManagerInternal.APP_TRANSITION_* reasons.
*/
void notifyTransitionStarting(SparseIntArray stackIdReasons) {
- if (!isAnyTransitionActive() || mLoggedTransitionStarting) {
+ // TODO (b/36339388): Figure out why stackIdReasons can be null
+ if (stackIdReasons == null || !isAnyTransitionActive() || mLoggedTransitionStarting) {
return;
}
mCurrentTransitionDelayMs = calculateCurrentDelay();
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 2e26bed..2b2471b 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1953,11 +1953,6 @@
}
void setRequestedOrientation(int requestedOrientation) {
- if (task != null && (!task.mFullscreen || !task.getStack().mFullscreen)) {
- // Fixed screen orientation isn't supported when activities aren't in full screen mode.
- return;
- }
-
final int displayId = getDisplayId();
final Configuration displayConfig =
mStackSupervisor.getDisplayOverrideConfiguration(displayId);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 42efe0b..217515b 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
import static android.Manifest.permission.START_ANY_ACTIVITY;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
@@ -1612,8 +1613,8 @@
return true;
}
- // Check if the caller can launch anything.
- final int startAnyPerm = mService.checkPermission(START_ANY_ACTIVITY, callingPid,
+ // Check if the caller can manage activity stacks.
+ final int startAnyPerm = mService.checkPermission(MANAGE_ACTIVITY_STACKS, callingPid,
callingUid);
if (startAnyPerm == PERMISSION_GRANTED) {
if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:"
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 36a913f..f927cce 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -857,17 +857,26 @@
ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
- String[] nativeProcs = NATIVE_STACKS_OF_INTEREST;
- // don't dump native PIDs for background ANRs
- File tracesFile = null;
+ // don't dump native PIDs for background ANRs unless it is the process of interest
+ String[] nativeProcs = null;
if (isSilentANR) {
- tracesFile = mService.dumpStackTraces(true, firstPids, null, lastPids,
- null);
+ for (int i = 0; i < NATIVE_STACKS_OF_INTEREST.length; i++) {
+ if (NATIVE_STACKS_OF_INTEREST[i].equals(app.processName)) {
+ nativeProcs = new String[] { app.processName };
+ break;
+ }
+ }
} else {
- tracesFile = mService.dumpStackTraces(true, firstPids, processCpuTracker, lastPids,
- nativeProcs);
+ nativeProcs = NATIVE_STACKS_OF_INTEREST;
}
+ // For background ANRs, don't pass the ProcessCpuTracker to
+ // avoid spending 1/2 second collecting stats to rank lastPids.
+ File tracesFile = mService.dumpStackTraces(true, firstPids,
+ (isSilentANR) ? null : processCpuTracker,
+ (isSilentANR) ? null : lastPids,
+ nativeProcs);
+
String cpuInfo = null;
if (ActivityManagerService.MONITOR_CPU_USAGE) {
mService.updateCpuStatsNow();
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 2787895..dd3d4e0 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -1152,17 +1152,14 @@
skip = true;
}
}
- final boolean visibleToInstantApps =
- (r.intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) != 0;
if (!skip && info.activityInfo.applicationInfo.isInstantApp()
- && !visibleToInstantApps
&& r.callingUid != info.activityInfo.applicationInfo.uid) {
Slog.w(TAG, "Instant App Denial: receiving "
+ r.intent
+ " to " + component.flattenToShortString()
+ " due to sender " + r.callerPackage
+ " (uid " + r.callingUid + ")"
- + " not specifying FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS");
+ + " Instant Apps do not support manifest receivers");
skip = true;
}
if (!skip && r.callerInstantApp
diff --git a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
index dec2f77..8c6430c 100644
--- a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
+++ b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
@@ -16,6 +16,8 @@
package com.android.server.connectivity.tethering;
+import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH;
+
import android.net.INetd;
import android.net.IpPrefix;
import android.net.LinkAddress;
@@ -48,7 +50,6 @@
public class IPv6TetheringInterfaceServices {
private static final String TAG = IPv6TetheringInterfaceServices.class.getSimpleName();
private static final IpPrefix LINK_LOCAL_PREFIX = new IpPrefix("fe80::/64");
- private static final int RFC7421_IP_PREFIX_LENGTH = 64;
private final String mIfName;
private final INetworkManagementService mNMService;
@@ -124,7 +125,7 @@
params.hasDefaultRoute = v6only.hasIPv6DefaultRoute();
for (LinkAddress linkAddr : v6only.getLinkAddresses()) {
- if (linkAddr.getPrefixLength() != RFC7421_IP_PREFIX_LENGTH) continue;
+ if (linkAddr.getPrefixLength() != RFC7421_PREFIX_LENGTH) continue;
final IpPrefix prefix = new IpPrefix(
linkAddr.getAddress(), linkAddr.getPrefixLength());
@@ -206,7 +207,7 @@
for (Inet6Address dns : deprecatedDnses) {
final String dnsString = dns.getHostAddress();
try {
- netd.interfaceDelAddress(mIfName, dnsString, RFC7421_IP_PREFIX_LENGTH);
+ netd.interfaceDelAddress(mIfName, dnsString, RFC7421_PREFIX_LENGTH);
} catch (ServiceSpecificException | RemoteException e) {
Log.e(TAG, "Failed to remove local dns IP: " + dnsString, e);
}
@@ -223,7 +224,7 @@
for (Inet6Address dns : addedDnses) {
final String dnsString = dns.getHostAddress();
try {
- netd.interfaceAddAddress(mIfName, dnsString, RFC7421_IP_PREFIX_LENGTH);
+ netd.interfaceAddAddress(mIfName, dnsString, RFC7421_PREFIX_LENGTH);
} catch (ServiceSpecificException | RemoteException e) {
Log.e(TAG, "Failed to add local dns IP: " + dnsString, e);
newDnses.remove(dns);
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 3262151..bdba64f 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -97,7 +97,6 @@
static final String TAG = "FingerprintService";
static final boolean DEBUG = true;
private static final String FP_DATA_DIR = "fpdata";
- private static final String FINGERPRINT_HIDL = "fingerprint_hal";
private static final int MSG_USER_SWITCHING = 10;
private static final String ACTION_LOCKOUT_RESET =
"com.android.server.fingerprint.ACTION_LOCKOUT_RESET";
@@ -219,7 +218,7 @@
public synchronized IBiometricsFingerprint getFingerprintDaemon() {
if (mDaemon == null) {
try {
- mDaemon = IBiometricsFingerprint.getService(FINGERPRINT_HIDL);
+ mDaemon = IBiometricsFingerprint.getService();
} catch (java.util.NoSuchElementException e) {
// Service doesn't exist or cannot be opened. Logged below.
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 7285a4c..3dcc5d9 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -22,10 +22,10 @@
import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL_ALL;
import static android.service.notification.NotificationListenerService.REASON_CHANNEL_BANNED;
-import static android.service.notification.NotificationListenerService.REASON_DELEGATE_CANCEL;
-import static android.service.notification.NotificationListenerService.REASON_DELEGATE_CANCEL_ALL;
-import static android.service.notification.NotificationListenerService.REASON_DELEGATE_CLICK;
-import static android.service.notification.NotificationListenerService.REASON_DELEGATE_ERROR;
+import static android.service.notification.NotificationListenerService.REASON_CANCEL;
+import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL;
+import static android.service.notification.NotificationListenerService.REASON_CLICK;
+import static android.service.notification.NotificationListenerService.REASON_ERROR;
import static android.service.notification.NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED;
import static android.service.notification.NotificationListenerService.REASON_LISTENER_CANCEL;
import static android.service.notification.NotificationListenerService.REASON_LISTENER_CANCEL_ALL;
@@ -88,7 +88,6 @@
import android.media.AudioManager;
import android.media.AudioManagerInternal;
import android.media.IRingtonePlayer;
-import android.metrics.LogMaker;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -179,7 +178,6 @@
import java.nio.charset.StandardCharsets;
import java.util.ArrayDeque;
import java.util.ArrayList;
-import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -543,7 +541,7 @@
@Override
public void onClearAll(int callingUid, int callingPid, int userId) {
synchronized (mNotificationLock) {
- cancelAllLocked(callingUid, callingPid, userId, REASON_DELEGATE_CANCEL_ALL, null,
+ cancelAllLocked(callingUid, callingPid, userId, REASON_CANCEL_ALL, null,
/*includeCurrentProfiles*/ true);
}
}
@@ -567,7 +565,7 @@
cancelNotification(callingUid, callingPid, sbn.getPackageName(), sbn.getTag(),
sbn.getId(), Notification.FLAG_AUTO_CANCEL,
Notification.FLAG_FOREGROUND_SERVICE, false, r.getUserId(),
- REASON_DELEGATE_CLICK, null);
+ REASON_CLICK, null);
}
}
@@ -596,7 +594,7 @@
String pkg, String tag, int id, int userId) {
cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE,
- true, userId, REASON_DELEGATE_CANCEL, null);
+ true, userId, REASON_CANCEL, null);
}
@Override
@@ -631,7 +629,7 @@
Slog.d(TAG, "onNotification error pkg=" + pkg + " tag=" + tag + " id=" + id
+ "; will crashApplication(uid=" + uid + ", pid=" + initialPid + ")");
cancelNotification(callingUid, callingPid, pkg, tag, id, 0, 0, false, userId,
- REASON_DELEGATE_ERROR, null);
+ REASON_ERROR, null);
long ident = Binder.clearCallingIdentity();
try {
ActivityManager.getService().crashApplication(uid, initialPid, pkg, -1,
@@ -1658,8 +1656,7 @@
public NotificationChannel getNotificationChannelForPackage(String pkg, int uid,
String channelId, boolean includeDeleted) {
checkCallerIsSystem();
- return mRankingHelper.getNotificationChannel
- (pkg, uid, channelId, includeDeleted);
+ return mRankingHelper.getNotificationChannel(pkg, uid, channelId, includeDeleted);
}
@Override
@@ -1675,6 +1672,27 @@
}
@Override
+ public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(
+ String pkg) {
+ checkCallerIsSystemOrSameApp(pkg);
+ return new ParceledListSlice<>(new ArrayList(
+ mRankingHelper.getNotificationChannelGroups(pkg, Binder.getCallingUid())));
+ }
+
+ @Override
+ public void deleteNotificationChannelGroup(String pkg, String channelGroupId) {
+ checkCallerIsSystemOrSameApp(pkg);
+
+ List<String> deletedChannelIds = mRankingHelper.deleteNotificationChannelGroup(
+ pkg, Binder.getCallingUid(), channelGroupId);
+ for (int i = 0; i < deletedChannelIds.size(); i++) {
+ cancelAllNotificationsInt(MY_UID, MY_PID, pkg, deletedChannelIds.get(i), 0, 0, true,
+ UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED, null);
+ }
+ savePolicyFile();
+ }
+
+ @Override
public void updateNotificationChannelForPackage(String pkg, int uid,
NotificationChannel channel) {
enforceSystemOrSystemUI("Caller not system or systemui");
@@ -3355,7 +3373,7 @@
Slog.e(TAG, "Not posting notification without small icon: " + notification);
if (old != null && !old.isCanceled) {
mListeners.notifyRemovedLocked(n,
- NotificationListenerService.REASON_DELEGATE_ERROR);
+ NotificationListenerService.REASON_ERROR);
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -4002,8 +4020,8 @@
// Record usage stats
// TODO: add unbundling stats?
switch (reason) {
- case REASON_DELEGATE_CANCEL:
- case REASON_DELEGATE_CANCEL_ALL:
+ case REASON_CANCEL:
+ case REASON_CANCEL_ALL:
case REASON_LISTENER_CANCEL:
case REASON_LISTENER_CANCEL_ALL:
mUsageStats.registerDismissedByUser(r);
@@ -4063,7 +4081,7 @@
// Ideally we'd do this in the caller of this method. However, that would
// require the caller to also find the notification.
- if (reason == REASON_DELEGATE_CLICK) {
+ if (reason == REASON_CLICK) {
mUsageStats.registerClickedByUser(r);
}
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index e239164..02f92fe 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -15,8 +15,6 @@
*/
package com.android.server.notification;
-import static android.app.NotificationManager.IMPORTANCE_NONE;
-
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
@@ -654,8 +652,6 @@
@Override
public void deleteNotificationChannel(String pkg, int uid, String channelId) {
- Preconditions.checkNotNull(pkg);
- Preconditions.checkNotNull(channelId);
Record r = getRecord(pkg, uid);
if (r == null) {
return;
@@ -667,6 +663,7 @@
LogMaker lm = getChannelLog(channel, pkg);
lm.setType(MetricsProto.MetricsEvent.TYPE_CLOSE);
MetricsLogger.action(lm);
+ updateConfig();
}
@Override
@@ -679,6 +676,7 @@
return;
}
r.channels.remove(channelId);
+ updateConfig();
}
@Override
@@ -695,6 +693,7 @@
r.channels.remove(key);
}
}
+ updateConfig();
}
public NotificationChannelGroup getNotificationChannelGroup(String groupId, String pkg,
@@ -719,12 +718,15 @@
final NotificationChannel nc = r.channels.valueAt(i);
if (includeDeleted || !nc.isDeleted()) {
if (nc.getGroup() != null) {
- NotificationChannelGroup ncg = groups.get(nc.getGroup());
- if (ncg == null ) {
- ncg = r.groups.get(nc.getGroup()).clone();
- groups.put(nc.getGroup(), ncg);
+ if (r.groups.get(nc.getGroup()) != null) {
+ NotificationChannelGroup ncg = groups.get(nc.getGroup());
+ if (ncg == null) {
+ ncg = r.groups.get(nc.getGroup()).clone();
+ groups.put(nc.getGroup(), ncg);
+
+ }
+ ncg.addChannel(nc);
}
- ncg.addChannel(nc);
} else {
nonGrouped.addChannel(nc);
}
@@ -736,8 +738,29 @@
return new ParceledListSlice<>(new ArrayList<>(groups.values()));
}
+ public List<String> deleteNotificationChannelGroup(String pkg, int uid,
+ String groupId) {
+ List<String> deletedChannelIds = new ArrayList<>();
+ Record r = getRecord(pkg, uid);
+ if (r == null || TextUtils.isEmpty(groupId)) {
+ return deletedChannelIds;
+ }
+
+ r.groups.remove(groupId);
+
+ int N = r.channels.size();
+ for (int i = 0; i < N; i++) {
+ final NotificationChannel nc = r.channels.valueAt(i);
+ if (groupId.equals(nc.getGroup())) {
+ nc.setDeleted(true);
+ deletedChannelIds.add(nc.getId());
+ }
+ }
+ updateConfig();
+ return deletedChannelIds;
+ }
+
@Override
- @VisibleForTesting
public Collection<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
int uid) {
Record r = getRecord(pkg, uid);
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 7aa96cf..d8900c0 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -49,8 +49,6 @@
private static final boolean DEBUG = false;
- private static final long RETRY_LATENCY = 4 * AlarmManager.INTERVAL_HOUR;
-
private static final int JOB_IDLE_OPTIMIZE = 800;
private static final int JOB_POST_BOOT_UPDATE = 801;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4ac1cce..1d1bf0d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -260,7 +260,6 @@
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.AttributeCache;
-import com.android.server.BackgroundDexOptJobService;
import com.android.server.DeviceIdleController;
import com.android.server.EventLogTags;
import com.android.server.FgThread;
@@ -272,6 +271,7 @@
import com.android.server.SystemServerInitThreadPool;
import com.android.server.Watchdog;
import com.android.server.net.NetworkPolicyManagerInternal;
+import com.android.server.pm.BackgroundDexOptService;
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.PermissionsState.PermissionState;
import com.android.server.pm.Settings.DatabaseVersion;
@@ -2038,12 +2038,15 @@
final boolean supportsRuntimePermissions = pkg.applicationInfo.targetSdkVersion
>= Build.VERSION_CODES.M;
+ final boolean instantApp = isInstantApp(pkg.packageName, userId);
+
for (String permission : pkg.requestedPermissions) {
final BasePermission bp;
synchronized (mPackages) {
bp = mSettings.mPermissions.get(permission);
}
if (bp != null && (bp.isRuntime() || bp.isDevelopment())
+ && (!instantApp || bp.isInstant())
&& (grantedPermissions == null
|| ArrayUtils.contains(grantedPermissions, permission))) {
final int flags = permissionsState.getPermissionFlags(permission, userId);
@@ -3348,7 +3351,7 @@
// * The system/shell/root can see metadata for any app
// * An installed app can see metadata for 1) other installed apps
// and 2) ephemeral apps that have explicitly interacted with it
- // * Ephemeral apps can only see their own metadata
+ // * Ephemeral apps can only see their own data and exposed installed apps
// * Holding a signature permission allows seeing instant apps
final int callingAppId = UserHandle.getAppId(Binder.getCallingUid());
if (callingAppId != Process.SYSTEM_UID
@@ -3358,8 +3361,10 @@
Binder.getCallingUid()) != PackageManager.PERMISSION_GRANTED) {
final String instantAppPackageName = getInstantAppPackageName(Binder.getCallingUid());
if (instantAppPackageName != null) {
- // ephemeral apps can only get information on themselves
- if (!instantAppPackageName.equals(p.packageName)) {
+ // ephemeral apps can only get information on themselves or
+ // installed apps that are exposed.
+ if (!instantAppPackageName.equals(p.packageName)
+ && (ps.getInstantApp(userId) || !p.visibleToInstantApps)) {
return null;
}
} else {
@@ -16850,11 +16855,11 @@
mDexManager.isUsedByOtherApps(pkg.packageName));
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- // Notify BackgroundDexOptJobService that the package has been changed.
+ // Notify BackgroundDexOptService that the package has been changed.
// If this is an update of a package which used to fail to compile,
// BDOS will remove it from its blacklist.
// TODO: Layering violation
- BackgroundDexOptJobService.notifyPackageChanged(pkg.packageName);
+ BackgroundDexOptService.notifyPackageChanged(pkg.packageName);
}
if (!args.doRename(res.returnCode, pkg, oldCodePath)) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index a7349fc..751d9af 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -147,6 +147,8 @@
return runSetHomeActivity();
case "get-privapp-permissions":
return runGetPrivappPermissions();
+ case "has-feature":
+ return runHasFeature();
default:
return handleDefaultCommands(cmd);
}
@@ -1268,6 +1270,28 @@
return 0;
}
+ private int runHasFeature() {
+ final PrintWriter err = getErrPrintWriter();
+ final String featureName = getNextArg();
+ if (featureName == null) {
+ err.println("Error: expected FEATURE name");
+ return 1;
+ }
+ final String versionString = getNextArg();
+ try {
+ final int version = (versionString == null) ? 0 : Integer.parseInt(versionString);
+ final boolean hasFeature = mInterface.hasSystemFeature(featureName, version);
+ getOutPrintWriter().println(hasFeature);
+ return hasFeature ? 0 : 1;
+ } catch (NumberFormatException e) {
+ err.println("Error: illegal version number " + versionString);
+ return 1;
+ } catch (RemoteException e) {
+ err.println(e.toString());
+ return 1;
+ }
+ }
+
private static String checkAbiArgument(String abi) {
if (TextUtils.isEmpty(abi)) {
throw new IllegalArgumentException("Missing ABI argument");
@@ -1649,6 +1673,9 @@
pw.println(" Unsuspends the specified package (as user).");
pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT");
pw.println(" set the default home activity (aka launcher).");
+ pw.println(" has-feature FEATURE_NAME [version]");
+ pw.println(" prints true and returns exit status 0 when system has a FEATURE_NAME,");
+ pw.println(" otherwise prints false and returns exit status 1");
pw.println();
Intent.printIntentArgsHelp(pw , "");
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index b9fcf4e..a31258c3 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1493,6 +1493,10 @@
listeners[i].onUserRestrictionsChanged(userId,
newRestrictionsFinal, prevRestrictionsFinal);
}
+
+ final Intent broadcast = new Intent(UserManager.ACTION_USER_RESTRICTIONS_CHANGED)
+ .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ mContext.sendBroadcastAsUser(broadcast, UserHandle.of(userId));
}
});
}
@@ -1810,8 +1814,8 @@
if (type == XmlPullParser.START_TAG) {
if (parser.getName().equals(TAG_RESTRICTIONS)) {
synchronized (mGuestRestrictions) {
- mGuestRestrictions.putAll(
- UserRestrictionsUtils.readRestrictions(parser));
+ UserRestrictionsUtils
+ .readRestrictions(parser, mGuestRestrictions);
}
}
break;
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 36eba8e..cb2ed6e 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -207,6 +207,7 @@
}
public static void readRestrictions(XmlPullParser parser, Bundle restrictions) {
+ restrictions.clear();
for (String key : USER_RESTRICTIONS) {
final String value = parser.getAttributeValue(null, key);
if (value != null) {
diff --git a/services/core/java/com/android/server/vr/CompatibilityDisplay.java b/services/core/java/com/android/server/vr/CompatibilityDisplay.java
index 5e17daa..8f95cc7 100644
--- a/services/core/java/com/android/server/vr/CompatibilityDisplay.java
+++ b/services/core/java/com/android/server/vr/CompatibilityDisplay.java
@@ -1,6 +1,8 @@
package com.android.server.vr;
+import static android.view.Display.INVALID_DISPLAY;
+
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -86,10 +88,8 @@
startVirtualDisplay();
}
} else {
- // TODO: Remove conditional when launching apps 2D doesn't force VrMode to stop.
- if (!DEBUG) {
- stopVirtualDisplay();
- }
+ // Stop virtual display to test exit condition
+ stopVirtualDisplay();
}
}
@@ -138,6 +138,19 @@
}
}
+ public int getVirtualDisplayId() {
+ synchronized(vdLock) {
+ if (mVirtualDisplay != null) {
+ int virtualDisplayId = mVirtualDisplay.getDisplay().getDisplayId();
+ if (DEBUG) {
+ Log.e(TAG, "VD id: " + virtualDisplayId);
+ }
+ return virtualDisplayId;
+ }
+ }
+ return INVALID_DISPLAY;
+ }
+
private void startVirtualDisplay() {
if (DEBUG) {
Log.d(TAG, "Request to start VD, DM:" + mDisplayManager);
diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java
index 58e4bdc..210aa44 100644
--- a/services/core/java/com/android/server/vr/VrManagerInternal.java
+++ b/services/core/java/com/android/server/vr/VrManagerInternal.java
@@ -90,6 +90,15 @@
public abstract void setPersistentVrModeEnabled(boolean enabled);
/**
+ * Return {@link android.view.Display.INVALID_DISPLAY} if there exists no virtual display
+ * currently or the display id of the current virtual display.
+ *
+ * @return {@link android.view.Display.INVALID_DISPLAY} if there is no virtual display
+ * currently, else return the display id of the virtual display
+ */
+ public abstract int getCompatibilityDisplayId();
+
+ /**
* Adds listener that reports state changes to persistent VR mode.
*/
public abstract void addPersistentVrModeStateListener(PersistentVrStateListener listener);
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 8a23173..a00115c 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -15,6 +15,8 @@
*/
package com.android.server.vr;
+import static android.view.Display.INVALID_DISPLAY;
+
import android.Manifest;
import android.app.ActivityManager;
import android.app.AppOpsManager;
@@ -392,6 +394,11 @@
}
@Override
+ public int getCompatibilityDisplayId() {
+ return VrManagerService.this.getCompatibilityDisplayId();
+ }
+
+ @Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
@@ -495,6 +502,11 @@
}
@Override
+ public int getCompatibilityDisplayId() {
+ return VrManagerService.this.getCompatibilityDisplayId();
+ }
+
+ @Override
public void addPersistentVrModeStateListener(PersistentVrStateListener listener) {
VrManagerService.this.addPersistentVrModeStateListener(listener);
}
@@ -1054,6 +1066,14 @@
}
}
+ private int getCompatibilityDisplayId() {
+ if (mCompatibilityDisplay != null) {
+ return mCompatibilityDisplay.getVirtualDisplayId();
+ }
+ Slog.w(TAG, "CompatibilityDisplay is null!");
+ return INVALID_DISPLAY;
+ }
+
private void setPersistentModeAndNotifyListenersLocked(boolean enabled) {
if (mPersistentVrModeEnabled == enabled) {
return;
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 4df513e..30e0ded 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -28,7 +28,6 @@
import android.content.ClipData;
import android.content.Context;
-import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Binder;
@@ -39,6 +38,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.util.MergedConfiguration;
import android.util.Slog;
import android.view.Display;
import android.view.IWindow;
@@ -216,13 +216,13 @@
int requestedWidth, int requestedHeight, int viewFlags,
int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Rect outBackdropFrame,
- Configuration outConfig, Surface outSurface) {
+ MergedConfiguration mergedConfiguration, Surface outSurface) {
if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "
+ Binder.getCallingPid());
int res = mService.relayoutWindow(this, window, seq, attrs,
requestedWidth, requestedHeight, viewFlags, flags,
outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
- outStableInsets, outsets, outBackdropFrame, outConfig, outSurface);
+ outStableInsets, outsets, outBackdropFrame, mergedConfiguration, outSurface);
if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
+ Binder.getCallingPid());
return res;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index c0598ca..04403e2 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -27,7 +27,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.app.ActivityManager.TaskDescription;
-import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -38,6 +37,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.util.MergedConfiguration;
import android.util.Slog;
import android.view.IWindowSession;
import android.view.Surface;
@@ -78,7 +78,7 @@
final Surface surface = new Surface();
final Rect tmpRect = new Rect();
final Rect tmpFrame = new Rect();
- final Configuration tmpConfiguration = new Configuration();
+ final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
int fillBackgroundColor = Color.WHITE;
synchronized (service.mWindowMap) {
layoutParams.type = TYPE_APPLICATION_STARTING;
@@ -122,7 +122,7 @@
window.setOuter(snapshotSurface);
try {
session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, tmpFrame,
- tmpRect, tmpRect, tmpRect, tmpRect, tmpRect, tmpRect, tmpConfiguration,
+ tmpRect, tmpRect, tmpRect, tmpRect, tmpRect, tmpRect, tmpMergedConfiguration,
surface);
} catch (RemoteException e) {
// Local call.
@@ -221,9 +221,9 @@
@Override
public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets,
- Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig,
- Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeNavBar,
- int displayId) {
+ Rect stableInsets, Rect outsets, boolean reportDraw,
+ MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout,
+ boolean alwaysConsumeNavBar, int displayId) {
if (reportDraw) {
sHandler.obtainMessage(MSG_REPORT_DRAW, mOuter).sendToTarget();
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 5551afe..7539cd4 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -150,6 +150,7 @@
import android.os.WorkSource;
import android.provider.Settings;
import android.util.ArraySet;
+import android.util.MergedConfiguration;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
@@ -1813,7 +1814,7 @@
int requestedHeight, int viewVisibility, int flags,
Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
- Configuration outConfig, Surface outSurface) {
+ MergedConfiguration mergedConfiguration, Surface outSurface) {
int result = 0;
boolean configChanged;
boolean hasStatusBarPermission =
@@ -1925,7 +1926,7 @@
if (viewVisibility == View.VISIBLE &&
(win.mAppToken == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
|| !win.mAppToken.clientHidden)) {
- result = win.relayoutVisibleWindow(outConfig, result, attrChanges,
+ result = win.relayoutVisibleWindow(mergedConfiguration, result, attrChanges,
oldVisibility);
try {
result = createSurfaceControl(outSurface, result, win, winAnimator);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 4e593d8..ca5d551 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -114,6 +114,7 @@
import android.os.Trace;
import android.os.UserHandle;
import android.os.WorkSource;
+import android.util.MergedConfiguration;
import android.util.DisplayMetrics;
import android.util.Slog;
import android.util.TimeUtils;
@@ -2265,7 +2266,7 @@
}
}
- void prepareWindowToDisplayDuringRelayout(Configuration outConfig) {
+ void prepareWindowToDisplayDuringRelayout(MergedConfiguration mergedConfiguration) {
if ((mAttrs.softInputMode & SOFT_INPUT_MASK_ADJUST)
== SOFT_INPUT_ADJUST_RESIZE) {
mLayoutNeeded = true;
@@ -2278,10 +2279,13 @@
mTurnOnScreen = true;
}
if (isConfigChanged()) {
- outConfig.setTo(getConfiguration());
- if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + this + " visible with new config: "
- + outConfig);
- mLastReportedConfiguration.setTo(outConfig);
+ final Configuration globalConfig = mService.mRoot.getConfiguration();
+ final Configuration overrideConfig = getMergedOverrideConfiguration();
+ mergedConfiguration.setConfiguration(globalConfig, overrideConfig);
+ if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + this
+ + " visible with new global config: " + globalConfig
+ + " merged override config: " + overrideConfig);
+ mLastReportedConfiguration.setTo(getConfiguration());
}
}
@@ -3027,12 +3031,13 @@
try {
if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this
+ ": " + mCompatFrame);
- final Configuration newConfig;
+ final MergedConfiguration mergedConfiguration;
if (isConfigChanged()) {
- newConfig = new Configuration(getConfiguration());
- mLastReportedConfiguration.setTo(newConfig);
+ mergedConfiguration = new MergedConfiguration(mService.mRoot.getConfiguration(),
+ getMergedOverrideConfiguration());
+ mLastReportedConfiguration.setTo(mergedConfiguration.getMergedConfiguration());
} else {
- newConfig = null;
+ mergedConfiguration = null;
}
if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == DRAW_PENDING)
Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING");
@@ -3054,7 +3059,7 @@
public void run() {
try {
dispatchResized(frame, overscanInsets, contentInsets, visibleInsets,
- stableInsets, outsets, reportDraw, newConfig,
+ stableInsets, outsets, reportDraw, mergedConfiguration,
reportOrientation, displayId);
} catch (RemoteException e) {
// Not a remote call, RemoteException won't be raised.
@@ -3063,7 +3068,7 @@
});
} else {
dispatchResized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets,
- outsets, reportDraw, newConfig, reportOrientation, displayId);
+ outsets, reportDraw, mergedConfiguration, reportOrientation, displayId);
}
//TODO (multidisplay): Accessibility supported only for the default display.
@@ -3120,14 +3125,14 @@
private void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
- Configuration newConfig, boolean reportOrientation, int displayId)
+ MergedConfiguration mergedConfiguration, boolean reportOrientation, int displayId)
throws RemoteException {
final boolean forceRelayout = isDragResizeChanged() || mResizedWhileNotDragResizing
|| reportOrientation;
mClient.resized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets, outsets,
- reportDraw, newConfig, getBackdropFrame(frame),
- forceRelayout, mPolicy.isNavBarForcedShownLw(this), displayId);
+ reportDraw, mergedConfiguration, getBackdropFrame(frame), forceRelayout,
+ mPolicy.isNavBarForcedShownLw(this), displayId);
mDragResizingChangeReported = true;
}
@@ -4341,8 +4346,8 @@
return !mLastSurfaceInsets.equals(mAttrs.surfaceInsets);
}
- int relayoutVisibleWindow(Configuration outConfig, int result,
- int attrChanges, int oldVisibility) {
+ int relayoutVisibleWindow(MergedConfiguration mergedConfiguration, int result, int attrChanges,
+ int oldVisibility) {
result |= !isVisibleLw() ? RELAYOUT_RES_FIRST_TIME : 0;
if (mAnimatingExit) {
Slog.d(TAG, "relayoutVisibleWindow: " + this + " mAnimatingExit=true, mRemoveOnExit="
@@ -4363,7 +4368,7 @@
mWinAnimator.mEnteringAnimation = true;
if ((result & RELAYOUT_RES_FIRST_TIME) != 0) {
- prepareWindowToDisplayDuringRelayout(outConfig);
+ prepareWindowToDisplayDuringRelayout(mergedConfiguration);
}
if ((attrChanges & FORMAT_CHANGED) != 0) {
// If the format can't be changed in place, preserve the old surface until the app draws
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index ac95db5..b5ed266 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -65,6 +65,7 @@
libinputflinger \
libinputservice \
libsensorservice \
+ libsensorservicehidl \
libskia \
libgui \
libusbhost \
@@ -88,5 +89,6 @@
android.hardware.tv.input@1.0 \
android.hardware.vibrator@1.0 \
android.hardware.vr@1.0 \
+ android.frameworks.sensorservice@1.0 \
-LOCAL_STATIC_LIBRARIES += libscrypt_static
\ No newline at end of file
+LOCAL_STATIC_LIBRARIES += libscrypt_static
diff --git a/services/core/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp
index 3120af5..8ad88ed 100644
--- a/services/core/jni/com_android_server_SystemServer.cpp
+++ b/services/core/jni/com_android_server_SystemServer.cpp
@@ -17,7 +17,10 @@
#include <jni.h>
#include <JNIHelp.h>
+#include <hidl/HidlTransportSupport.h>
+
#include <sensorservice/SensorService.h>
+#include <sensorservicehidl/SensorManager.h>
#include <cutils/properties.h>
#include <utils/Log.h>
@@ -32,6 +35,21 @@
if (strcmp(propBuf, "1") == 0) {
SensorService::instantiate();
}
+
+}
+
+static void android_server_SystemServer_startHidlServices(JNIEnv* /* env */, jobject /* clazz */) {
+ using ::android::frameworks::sensorservice::V1_0::ISensorManager;
+ using ::android::frameworks::sensorservice::V1_0::implementation::SensorManager;
+ using ::android::hardware::configureRpcThreadpool;
+
+ configureRpcThreadpool(1, false /* callerWillJoin */);
+ sp<ISensorManager> sensorService = new SensorManager();
+ status_t err = sensorService->registerAsService();
+ if (err != OK) {
+ ALOGE("Cannot register ::android::frameworks::sensorservice::V1_0::"
+ "implementation::SensorManager: %d", err);
+ }
}
/*
@@ -40,6 +58,7 @@
static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "startSensorService", "()V", (void*) android_server_SystemServer_startSensorService },
+ { "startHidlServices", "()V", (void*) android_server_SystemServer_startHidlServices },
};
int register_android_server_SystemServer(JNIEnv* env)
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index a8423e2..e6e0242 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -86,6 +86,7 @@
import com.android.server.om.OverlayManagerService;
import com.android.server.os.DeviceIdentifiersPolicyService;
import com.android.server.os.SchedulingPolicyService;
+import com.android.server.pm.BackgroundDexOptService;
import com.android.server.pm.Installer;
import com.android.server.pm.LauncherAppsService;
import com.android.server.pm.OtaDexoptService;
@@ -235,16 +236,24 @@
private final boolean mRuntimeRestart;
private static final String START_SENSOR_SERVICE = "StartSensorService";
+ private static final String START_HIDL_SERVICES = "StartHidlServices";
+
+
private Future<?> mSensorServiceStart;
private Future<?> mZygotePreload;
-
/**
* Start the sensor service. This is a blocking call and can take time.
*/
private static native void startSensorService();
/**
+ * Start all HIDL services that are run inside the system server. This
+ * may take some time.
+ */
+ private static native void startHidlServices();
+
+ /**
* The main entry point from zygote.
*/
public static void main(String[] args) {
@@ -610,6 +619,7 @@
startSensorService();
traceLog.traceEnd();
}, START_SENSOR_SERVICE);
+
}
/**
@@ -637,6 +647,14 @@
traceBeginAndSlog("StartWebViewUpdateService");
mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);
traceEnd();
+
+ // Start receiving calls from HIDL services. Start in in a separate thread
+ // because it need to connect to SensorManager.
+ SystemServerInitThreadPool.get().submit(() -> {
+ traceBeginAndSlog(START_HIDL_SERVICES);
+ startHidlServices();
+ traceEnd();
+ }, START_HIDL_SERVICES);
}
/**
@@ -1428,11 +1446,11 @@
traceEnd();
}
- traceBeginAndSlog("StartBackgroundDexOptJobService");
+ traceBeginAndSlog("StartBackgroundDexOptService");
try {
- BackgroundDexOptJobService.schedule(context);
+ BackgroundDexOptService.schedule(context);
} catch (Throwable e) {
- reportWtf("starting StartBackgroundDexOptJobService", e);
+ reportWtf("starting StartBackgroundDexOptService", e);
}
traceEnd();
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 3e3a19b..c670782 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -16,6 +16,8 @@
package android.net.ip;
+import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH;
+
import com.android.internal.util.MessageUtils;
import com.android.internal.util.WakeupMessage;
@@ -42,6 +44,7 @@
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
import android.os.SystemClock;
+import android.system.OsConstants;
import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Log;
@@ -1028,15 +1031,36 @@
return true;
}
- private boolean startIPv6() {
- // Set privacy extensions.
+ private void enableInterfaceIPv6PrivacyExtensions() {
final String PREFER_TEMPADDRS = "2";
+ NetdService.run((INetd netd) -> {
+ netd.setProcSysNet(
+ INetd.IPV6, INetd.CONF, mInterfaceName, "use_tempaddr", PREFER_TEMPADDRS);
+ });
+ }
+
+ private void setInterfaceIPv6RaRtInfoMaxPlen(int plen) {
+ // Setting RIO max plen is best effort. Catch and ignore most exceptions.
try {
NetdService.run((INetd netd) -> {
- netd.setProcSysNet(
- INetd.IPV6, INetd.CONF, mInterfaceName, "use_tempaddr",
- PREFER_TEMPADDRS);
- });
+ netd.setProcSysNet(
+ INetd.IPV6, INetd.CONF, mInterfaceName, "accept_ra_rt_info_max_plen",
+ Integer.toString(plen));
+ });
+ } catch (ServiceSpecificException e) {
+ // Old kernel versions without support for RIOs do not export accept_ra_rt_info_max_plen
+ // in the /proc filesystem. If the kernel supports RIOs we should never see any other
+ // type of error.
+ if (e.errorCode != OsConstants.ENOENT) {
+ logError("unexpected error setting accept_ra_rt_info_max_plen %s", e);
+ }
+ }
+ }
+
+ private boolean startIPv6() {
+ try {
+ enableInterfaceIPv6PrivacyExtensions();
+ setInterfaceIPv6RaRtInfoMaxPlen(RFC7421_PREFIX_LENGTH);
mNwService.enableIpv6(mInterfaceName);
} catch (IllegalStateException|RemoteException|ServiceSpecificException e) {
logError("Unable to change interface settings: %s", e);
diff --git a/services/net/java/android/net/util/NetworkConstants.java b/services/net/java/android/net/util/NetworkConstants.java
index 362f757..26f3050 100644
--- a/services/net/java/android/net/util/NetworkConstants.java
+++ b/services/net/java/android/net/util/NetworkConstants.java
@@ -97,6 +97,7 @@
public static final int IPV6_SRC_ADDR_OFFSET = 8;
public static final int IPV6_DST_ADDR_OFFSET = 24;
public static final int IPV6_ADDR_LEN = 16;
+ public static final int RFC7421_PREFIX_LENGTH = 64;
/**
* ICMPv6 constants.
diff --git a/services/tests/notification/Android.mk b/services/tests/notification/Android.mk
index de9553a..a5d5570 100644
--- a/services/tests/notification/Android.mk
+++ b/services/tests/notification/Android.mk
@@ -30,6 +30,7 @@
LOCAL_JACK_FLAGS := --multi-dex native
LOCAL_PACKAGE_NAME := FrameworksNotificationTests
+LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_CERTIFICATE := platform
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index b538453..27b9a88 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -854,6 +854,43 @@
}
@Test
+ public void testDeleteGroup() throws Exception {
+ NotificationChannelGroup notDeleted = new NotificationChannelGroup("not", "deleted");
+ NotificationChannelGroup deleted = new NotificationChannelGroup("totally", "deleted");
+ NotificationChannel nonGroupedNonDeletedChannel =
+ new NotificationChannel("no group", "so not deleted", IMPORTANCE_HIGH);
+ NotificationChannel groupedButNotDeleted =
+ new NotificationChannel("not deleted", "belongs to notDeleted", IMPORTANCE_DEFAULT);
+ groupedButNotDeleted.setGroup("not");
+ NotificationChannel groupedAndDeleted =
+ new NotificationChannel("deleted", "belongs to deleted", IMPORTANCE_DEFAULT);
+ groupedAndDeleted.setGroup("totally");
+
+ mHelper.createNotificationChannelGroup(pkg, uid, notDeleted, true);
+ mHelper.createNotificationChannelGroup(pkg, uid, deleted, true);
+ mHelper.createNotificationChannel(pkg, uid, nonGroupedNonDeletedChannel, true);
+ mHelper.createNotificationChannel(pkg, uid, groupedAndDeleted, true);
+ mHelper.createNotificationChannel(pkg, uid, groupedButNotDeleted, true);
+
+ mHelper.deleteNotificationChannelGroup(pkg, uid, deleted.getId());
+
+ assertNull(mHelper.getNotificationChannelGroup(deleted.getId(), pkg, uid));
+ assertNotNull(mHelper.getNotificationChannelGroup(notDeleted.getId(), pkg, uid));
+
+ assertNull(mHelper.getNotificationChannel(pkg, uid, groupedAndDeleted.getId(), false));
+ compareChannels(groupedAndDeleted,
+ mHelper.getNotificationChannel(pkg, uid, groupedAndDeleted.getId(), true));
+
+ compareChannels(groupedButNotDeleted,
+ mHelper.getNotificationChannel(pkg, uid, groupedButNotDeleted.getId(), false));
+ compareChannels(nonGroupedNonDeletedChannel, mHelper.getNotificationChannel(
+ pkg, uid, nonGroupedNonDeletedChannel.getId(), false));
+
+ // notDeleted
+ assertEquals(1, mHelper.getNotificationChannelGroups(pkg, uid).size());
+ }
+
+ @Test
public void testOnPackageChanged_packageRemoval() throws Exception {
// Deleted
NotificationChannel channel1 =
@@ -889,7 +926,7 @@
mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{pkg}, new int[]{uid});
- assertEquals(0, mHelper.getNotificationChannelGroups(pkg, uid, true).getList().size());
+ assertEquals(0, mHelper.getNotificationChannelGroups(pkg, uid).size());
}
@Test
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 15c61f6..2a8f4a3 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -30,6 +30,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_PACKAGE_NAME := FrameworksServicesTests
+LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_CERTIFICATE := platform
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index 9f50a2c..921e0e3 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -126,8 +126,6 @@
}
@Test
- @Ignore
- // TODO(b/35034729): Need to fix before re-enabling
public void testLandscapeSeascapeRotationByPolicy() throws Exception {
// Some plumbing to get the service ready for rotation updates.
sWm.mDisplayReady = true;
@@ -145,15 +143,20 @@
appWindowToken.addWindow(appWindow);
// Set initial orientation and update.
- ((TestWindowManagerPolicy) sWm.mPolicy).rotationToReport = Surface.ROTATION_90;
- sWm.updateRotation(false, false);
+ performRotation(Surface.ROTATION_90);
appWindow.resizeReported = false;
// Update the rotation to perform 180 degree rotation and check that resize was reported.
- ((TestWindowManagerPolicy) sWm.mPolicy).rotationToReport = Surface.ROTATION_270;
- sWm.updateRotation(false, false);
- sWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
+ performRotation(Surface.ROTATION_270);
assertTrue(appWindow.resizeReported);
appWindow.removeImmediately();
}
+
+ private void performRotation(int rotationToReport) {
+ ((TestWindowManagerPolicy) sWm.mPolicy).rotationToReport = rotationToReport;
+ sWm.updateRotation(false, false);
+ // Simulate animator finishing orientation change
+ sWm.mRoot.mOrientationChangeComplete = true;
+ sWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java b/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
index b6dc9a5..0a644b60 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
@@ -18,11 +18,11 @@
import com.android.internal.os.IResultReceiver;
-import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
+import android.util.MergedConfiguration;
import android.view.DragEvent;
import android.view.IWindow;
@@ -36,7 +36,7 @@
@Override
public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets,
- Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig,
+ Rect stableInsets, Rect outsets, boolean reportDraw, MergedConfiguration mergedConfig,
Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeNavBar, int displayId)
throws RemoteException {
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 911050a..65efd9c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -71,7 +71,10 @@
static TestWindowManagerPolicy sPolicy = null;
private final static IWindow sIWindow = new TestIWindow();
private final static Session sMockSession = mock(Session.class);
- private static int sNextDisplayId = Display.DEFAULT_DISPLAY + 1;
+ // The default display is removed in {@link #setUp} and then we iterate over all displays to
+ // make sure we don't collide with any existing display. If we run into no other display, the
+ // added display should be treated as default.
+ private static int sNextDisplayId = Display.DEFAULT_DISPLAY;
static int sNextStackId = FIRST_DYNAMIC_STACK_ID;
private static int sNextTaskId = 0;
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 40bdaa5..03d8241 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -25,8 +25,8 @@
import android.media.AudioSystem;
import android.media.IAudioService;
import android.media.midi.MidiDeviceInfo;
-import android.os.FileObserver;
import android.os.Bundle;
+import android.os.FileObserver;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -41,10 +41,7 @@
import libcore.io.IoUtils;
import java.io.File;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
import java.util.HashMap;
-import java.util.ArrayList;
/**
* UsbAlsaManager manages USB audio and MIDI devices.
@@ -219,23 +216,23 @@
AlsaDevice testDevice = new AlsaDevice(type, card, device);
// This value was empirically determined.
- final int kWaitTime = 2500; // ms
+ final int kWaitTimeMs = 2500;
synchronized(mAlsaDevices) {
- long timeout = SystemClock.elapsedRealtime() + kWaitTime;
+ long timeoutMs = SystemClock.elapsedRealtime() + kWaitTimeMs;
do {
if (mAlsaDevices.values().contains(testDevice)) {
return testDevice;
}
- long waitTime = timeout - SystemClock.elapsedRealtime();
- if (waitTime > 0) {
+ long waitTimeMs = timeoutMs - SystemClock.elapsedRealtime();
+ if (waitTimeMs > 0) {
try {
- mAlsaDevices.wait(waitTime);
+ mAlsaDevices.wait(waitTimeMs);
} catch (InterruptedException e) {
Slog.d(TAG, "usb: InterruptedException while waiting for ALSA file.");
}
}
- } while (timeout > SystemClock.elapsedRealtime());
+ } while (timeoutMs > SystemClock.elapsedRealtime());
}
Slog.e(TAG, "waitForAlsaDevice failed for " + testDevice);
@@ -498,6 +495,7 @@
// Devices List
//
/*
+ //import java.util.ArrayList;
public ArrayList<UsbAudioDevice> getConnectedDevices() {
ArrayList<UsbAudioDevice> devices = new ArrayList<UsbAudioDevice>(mAudioDevices.size());
for (HashMap.Entry<UsbDevice,UsbAudioDevice> entry : mAudioDevices.entrySet()) {
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
index 808b5d3..a7bdabd 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
@@ -138,7 +138,7 @@
mSaturation = saturation;
final ColorMatrixColorFilter filter =
(ColorMatrixColorFilter) mColorMatrixPaint.getColorFilter();
- final ColorMatrix m = filter.getColorMatrix();
+ final ColorMatrix m = new ColorMatrix();
m.setSaturation(saturation);
filter.setColorMatrix(m);
invalidate();
diff --git a/tests/net/Android.mk b/tests/net/Android.mk
index 79f6e4d..504d54e 100644
--- a/tests/net/Android.mk
+++ b/tests/net/Android.mk
@@ -24,6 +24,7 @@
android.test.runner
LOCAL_PACKAGE_NAME := FrameworksNetTests
+LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_CERTIFICATE := platform
diff --git a/tests/testables/Android.mk b/tests/testables/Android.mk
index 58399fd..759bc35 100644
--- a/tests/testables/Android.mk
+++ b/tests/testables/Android.mk
@@ -25,7 +25,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
- mockito-updated-target-minus-junit4 \
+ mockito-target-minus-junit4 \
legacy-android-test
LOCAL_JAVA_LIBRARIES := android.test.runner
diff --git a/tests/testables/tests/Android.mk b/tests/testables/tests/Android.mk
index 752d536..a123d80 100644
--- a/tests/testables/tests/Android.mk
+++ b/tests/testables/tests/Android.mk
@@ -27,7 +27,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
- mockito-updated-target-minus-junit4 \
+ mockito-target-minus-junit4 \
legacy-android-test \
testables
diff --git a/tools/layoutlib/bridge/src/android/graphics/BaseCanvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BaseCanvas_Delegate.java
index b1e71b2..cc71053 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BaseCanvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BaseCanvas_Delegate.java
@@ -24,6 +24,7 @@
import com.android.ninepatch.NinePatchChunk;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+import android.annotation.Nullable;
import android.text.TextUtils;
import java.awt.*;
@@ -31,6 +32,8 @@
import java.awt.geom.Arc2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBuffer;
public class BaseCanvas_Delegate {
// ---- delegate manager ----
@@ -646,9 +649,15 @@
forceSrcMode[0] = false;
// if the bitmap config is alpha_8, then we erase all color value from it
- // before drawing it.
+ // before drawing it or apply the texture from the shader if present.
if (bitmap.getConfig() == Bitmap.Config.ALPHA_8) {
- fixAlpha8Bitmap(image);
+ Shader_Delegate shader = paint.getShader();
+ java.awt.Paint javaPaint = null;
+ if (shader instanceof BitmapShader_Delegate) {
+ javaPaint = shader.getJavaPaint();
+ }
+
+ fixAlpha8Bitmap(image, javaPaint);
} else if (!bitmap.hasAlpha()) {
// hasAlpha is merely a rendering hint. There can in fact be alpha values
// in the bitmap but it should be ignored at drawing time.
@@ -672,16 +681,37 @@
return image;
}
- private static void fixAlpha8Bitmap(final BufferedImage image) {
+ /**
+ * This method will apply the correct color to the passed "only alpha" image. Colors on the
+ * passed image will be destroyed.
+ * If the passed javaPaint is null, the color will be set to 0. If a paint is passed, it will
+ * be used to obtain the color that will be applied.
+ * <p/>
+ * This will destroy the passed image color channel.
+ */
+ private static void fixAlpha8Bitmap(final BufferedImage image,
+ @Nullable java.awt.Paint javaPaint) {
int w = image.getWidth();
int h = image.getHeight();
+
+ DataBuffer texture = null;
+ if (javaPaint != null) {
+ PaintContext context = javaPaint.createContext(ColorModel.getRGBdefault(), null, null,
+ new AffineTransform(), null);
+ texture = context.getRaster(0, 0, w, h).getDataBuffer();
+ }
+
int[] argb = new int[w * h];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth());
final int length = argb.length;
- for (int i = 0 ; i < length; i++) {
+ for (int i = 0; i < length; i++) {
argb[i] &= 0xFF000000;
+ if (texture != null) {
+ argb[i] |= texture.getElem(i) & 0x00FFFFFF;
+ }
}
+
image.setRGB(0, 0, w, h, argb, 0, w);
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java
index bd934d0..cb013b6 100644
--- a/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java
@@ -66,7 +66,7 @@
// ---- native methods ----
@LayoutlibDelegate
- /*package*/ static void destroyFilter(long native_instance) {
+ /*package*/ static void nSafeUnref(long native_instance) {
sManager.removeJavaReferenceFor(native_instance);
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
index ff5a5e9..aaff5d5 100644
--- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
@@ -16,7 +16,6 @@
package android.graphics;
-import android.text.FontConfig;
import com.android.ide.common.rendering.api.AssetRepository;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
@@ -293,12 +292,16 @@
@LayoutlibDelegate
/*package*/ static boolean nAddFontWeightStyle(long builderPtr, ByteBuffer font,
- int ttcIndex, List<FontConfig.Axis> listOfAxis,
- int weight, boolean isItalic) {
+ int ttcIndex, int weight, boolean isItalic) {
assert false : "The only client of this method has been overriden.";
return false;
}
+ @LayoutlibDelegate
+ /*package*/ static void nAddAxisValue(long builderPtr, int tag, float value) {
+ assert false : "The only client of this method has been overriden.";
+ }
+
static boolean addFont(long builderPtr, final String path, final int weight,
final boolean isItalic) {
final FontFamily_Delegate delegate = getDelegate(builderPtr);
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index aa1f00d..1bb56e3 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -964,8 +964,9 @@
}
@LayoutlibDelegate
- /*package*/ static int nGetTextRunCursor(Paint paint, long native_object, char[] text,
- int contextStart, int contextLength, int flags, int offset, int cursorOpt) {
+ /*package*/ static int nGetTextRunCursor(Paint paint, long native_object, long typefacePtr,
+ char[] text, int contextStart, int contextLength, int flags, int offset,
+ int cursorOpt) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Paint.getTextRunCursor is not supported.", null, null /*data*/);
@@ -973,8 +974,8 @@
}
@LayoutlibDelegate
- /*package*/ static int nGetTextRunCursor(Paint paint, long native_object, String text,
- int contextStart, int contextEnd, int flags, int offset, int cursorOpt) {
+ /*package*/ static int nGetTextRunCursor(Paint paint, long native_object, long typefacePtr,
+ String text, int contextStart, int contextEnd, int flags, int offset, int cursorOpt) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Paint.getTextRunCursor is not supported.", null, null /*data*/);
diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/AdaptiveIconDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/AdaptiveIconDrawable_Delegate.java
deleted file mode 100644
index 7e9432d..0000000
--- a/tools/layoutlib/bridge/src/android/graphics/drawable/AdaptiveIconDrawable_Delegate.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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 android.graphics.drawable;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.PorterDuff.Mode;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
-import android.graphics.drawable.AdaptiveIconDrawable.LayerState;
-
-/**
- * Delegate used to provide new implementation of a select few methods of {@link
- * AdaptiveIconDrawable}
- * <p>
- * Through the layoutlib_create tool, the original methods of AdaptiveIconDrawable have been
- * replaced by calls to methods of the same name in this delegate class.
- */
-@SuppressWarnings("unused")
-public class AdaptiveIconDrawable_Delegate {
- @LayoutlibDelegate
- /*package*/ static void draw(AdaptiveIconDrawable thisDrawable, Canvas canvas) {
- // This is a workaround for the broken BitmapShader in layoutlib. This new draw methods
- // avoids the use of the shader.
-
- for (int i = 0; i < LayerState.N_CHILDREN; i++) {
- if (thisDrawable.mLayerState.mChildren[i] == null) {
- continue;
- }
- final Drawable dr = thisDrawable.mLayerState.mChildren[i].mDrawable;
- if (dr != null) {
- dr.draw(canvas);
- }
- }
-
- if (thisDrawable.mMaskBitmap != null) {
- Rect bounds = thisDrawable.getBounds();
- Paint paint = new Paint();
- paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
- canvas.drawBitmap(thisDrawable.mMaskBitmap, bounds.left, bounds.top, paint);
- }
- }
-}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
index 4689491..ffbe7c4 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
@@ -18,12 +18,12 @@
import com.android.internal.os.IResultReceiver;
-import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
+import android.util.MergedConfiguration;
import android.view.DragEvent;
import android.view.IWindow;
@@ -50,7 +50,7 @@
@Override
public void resized(Rect rect, Rect rect2, Rect rect3, Rect rect4, Rect rect5, Rect rect6,
- boolean b, Configuration configuration, Rect rect7, boolean b2, boolean b3, int i0)
+ boolean b, MergedConfiguration mergedConfig, Rect rect7, boolean b2, boolean b3, int i0)
throws RemoteException {
// pass for now.
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
index 4dfe47b..2c88394 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
@@ -17,12 +17,12 @@
package com.android.layoutlib.bridge.android;
import android.content.ClipData;
-import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.MergedConfiguration;
import android.view.IWindow;
import android.view.IWindowId;
import android.view.IWindowSession;
@@ -89,7 +89,7 @@
@Override
public int relayout(IWindow iWindow, int i, LayoutParams layoutParams, int i2,
int i3, int i4, int i5, Rect rect, Rect rect2, Rect rect3, Rect rect4, Rect rect5,
- Rect rect6, Rect rect7, Configuration configuration, Surface surface)
+ Rect rect6, Rect rect7, MergedConfiguration mergedConfig, Surface surface)
throws RemoteException {
// pass for now.
return 0;
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 4f226cb..b0aa3c2 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -163,7 +163,6 @@
"android.content.res.TypedArray#obtain",
"android.graphics.BitmapFactory#finishDecode",
"android.graphics.BitmapFactory#setDensityFromOptions",
- "android.graphics.drawable.AdaptiveIconDrawable#draw",
"android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT#useLastSeenTarget",
"android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT#onDraw",
"android.graphics.drawable.GradientDrawable#buildRing",
@@ -333,8 +332,6 @@
* needed when access from the delegate classes is needed.
*/
private final static String[] PROMOTED_FIELDS = new String[] {
- "android.graphics.drawable.AdaptiveIconDrawable#mMaskBitmap",
- "android.graphics.drawable.AdaptiveIconDrawable#mPaint",
"android.graphics.drawable.VectorDrawable#mVectorState",
"android.view.Choreographer#mLastFrameTimeNanos",
"android.graphics.FontFamily#mBuilderPtr"
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index a1099f8..04f9059 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -281,7 +281,9 @@
public int apChannel = 0;
/**
- * Pre-shared key for use with WPA-PSK.
+ * Pre-shared key for use with WPA-PSK. Either an ASCII string enclosed in
+ * double quotation marks (e.g., {@code "abcdefghij"} for PSK passphrase or
+ * a string of 64 hex digits for raw PSK.
* <p/>
* When the value of this key is read, the actual key is
* not returned, just a "*" if the key has a value, or the null
@@ -305,7 +307,7 @@
/**
* Priority determines the preference given to a network by {@code wpa_supplicant}
* when choosing an access point with which to associate.
- * @deprecated Priority is no longer used.
+ * @deprecated This field does not exist anymore.
*/
@Deprecated
public int priority;
@@ -434,6 +436,13 @@
public int dtimInterval = 0;
/**
+ * Flag indicating if this configuration represents a legacy Passpoint configuration
+ * (Release N or older). This is used for migrating Passpoint configuration from N to O.
+ * This will no longer be needed after O.
+ * @hide
+ */
+ public boolean isLegacyPasspointConfig = false;
+ /**
* @hide
* Uid of app creating the configuration
*/
@@ -1961,6 +1970,7 @@
mCachedConfigKey = null; //force null configKey
selfAdded = source.selfAdded;
validatedInternetAccess = source.validatedInternetAccess;
+ isLegacyPasspointConfig = source.isLegacyPasspointConfig;
ephemeral = source.ephemeral;
meteredHint = source.meteredHint;
meteredOverride = source.meteredOverride;
@@ -2037,6 +2047,7 @@
dest.writeInt(selfAdded ? 1 : 0);
dest.writeInt(didSelfAdd ? 1 : 0);
dest.writeInt(validatedInternetAccess ? 1 : 0);
+ dest.writeInt(isLegacyPasspointConfig ? 1 : 0);
dest.writeInt(ephemeral ? 1 : 0);
dest.writeInt(meteredHint ? 1 : 0);
dest.writeInt(meteredOverride ? 1 : 0);
@@ -2103,6 +2114,7 @@
config.selfAdded = in.readInt() != 0;
config.didSelfAdd = in.readInt() != 0;
config.validatedInternetAccess = in.readInt() != 0;
+ config.isLegacyPasspointConfig = in.readInt() != 0;
config.ephemeral = in.readInt() != 0;
config.meteredHint = in.readInt() != 0;
config.meteredOverride = in.readInt() != 0;
diff --git a/wifi/tests/Android.mk b/wifi/tests/Android.mk
index eac49d2..8dc244f 100644
--- a/wifi/tests/Android.mk
+++ b/wifi/tests/Android.mk
@@ -58,5 +58,6 @@
android.test.runner \
LOCAL_PACKAGE_NAME := FrameworksWifiApiTests
+LOCAL_COMPATIBILITY_SUITE := device-tests
include $(BUILD_PACKAGE)