Merge "Switching Native MIDI API to an "opaque pointers" model."
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 71e6af7..e728897 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -242,7 +242,7 @@
$(call add-clean-step, rm -f $(OUT_DIR)/target/common/obj/APPS/FeatureSplit2_intermediates/src/com/android/test/split/feature/R.java)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/hardware)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/core/java/android/os/storage/*)
-
+$(call add-clean-step, rm -rf $(OUT_DIR)/host/common/obj/JAVA_LIBRARIES/platformprotos_intermediates)
# ******************************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
# ******************************************************************
diff --git a/api/current.txt b/api/current.txt
index d837786..4c900b7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -20,6 +20,7 @@
field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
+ field public static final java.lang.String BIND_AUTOFILL = "android.permission.BIND_AUTOFILL";
field public static final java.lang.String BIND_AUTO_FILL = "android.permission.BIND_AUTO_FILL";
field public static final deprecated java.lang.String BIND_CARRIER_MESSAGING_SERVICE = "android.permission.BIND_CARRIER_MESSAGING_SERVICE";
field public static final java.lang.String BIND_CARRIER_SERVICES = "android.permission.BIND_CARRIER_SERVICES";
@@ -298,8 +299,6 @@
field public static final int authorities = 16842776; // 0x1010018
field public static final int autoAdvanceViewId = 16843535; // 0x101030f
field public static final int autoCompleteTextViewStyle = 16842859; // 0x101006b
- field public static final int autoFillHint = 16844121; // 0x1010559
- field public static final int autoFillMode = 16844116; // 0x1010554
field public static final int autoLink = 16842928; // 0x10100b0
field public static final int autoMirrored = 16843754; // 0x10103ea
field public static final int autoRemoveFromRecents = 16843847; // 0x1010447
@@ -312,6 +311,8 @@
field public static final deprecated int autoText = 16843114; // 0x101016a
field public static final int autoUrlDetect = 16843404; // 0x101028c
field public static final int autoVerify = 16844014; // 0x10104ee
+ field public static final int autofillHint = 16844121; // 0x1010559
+ field public static final int autofillMode = 16844116; // 0x1010554
field public static final int background = 16842964; // 0x10100d4
field public static final int backgroundDimAmount = 16842802; // 0x1010032
field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -1778,6 +1779,7 @@
public static final class R.id {
ctor public R.id();
field public static final int accessibilityActionContextClick = 16908348; // 0x102003c
+ field public static final int accessibilityActionMoveWindow = 16908354; // 0x1020042
field public static final int accessibilityActionScrollDown = 16908346; // 0x102003a
field public static final int accessibilityActionScrollLeft = 16908345; // 0x1020039
field public static final int accessibilityActionScrollRight = 16908347; // 0x102003b
@@ -6551,9 +6553,12 @@
public class AssistStructure implements android.os.Parcelable {
ctor public AssistStructure();
method public int describeContents();
+ method public long getAcquisitionEndTime();
+ method public long getAcquisitionStartTime();
method public android.content.ComponentName getActivityComponent();
method public android.app.assist.AssistStructure.WindowNode getWindowNodeAt(int);
method public int getWindowNodeCount();
+ method public boolean isHomeActivity();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.assist.AssistStructure> CREATOR;
}
@@ -6561,11 +6566,10 @@
public static class AssistStructure.ViewNode {
method public float getAlpha();
method public int getAutoFillHint();
- method public android.view.autofill.AutoFillId getAutoFillId();
- method public java.lang.String[] getAutoFillOptions();
- method public deprecated android.view.autofill.AutoFillType getAutoFillType();
- method public android.view.autofill.AutoFillValue getAutoFillValue();
+ method public android.view.autofill.AutofillId getAutofillId();
+ method public java.lang.String[] getAutofillOptions();
method public int getAutofillType();
+ method public android.view.autofill.AutofillValue getAutofillValue();
method public android.app.assist.AssistStructure.ViewNode getChildAt(int);
method public int getChildCount();
method public java.lang.String getClassName();
@@ -6607,6 +6611,7 @@
method public boolean isFocusable();
method public boolean isFocused();
method public boolean isLongClickable();
+ method public boolean isOpaque();
method public boolean isSelected();
field public static final int TEXT_COLOR_UNDEFINED = 1; // 0x1
field public static final int TEXT_STYLE_BOLD = 1; // 0x1
@@ -7986,7 +7991,7 @@
public static final class AdvertisingSetParameters.Builder {
ctor public AdvertisingSetParameters.Builder();
method public android.bluetooth.le.AdvertisingSetParameters build();
- method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymouus(boolean);
+ method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymous(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setConnectable(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setIncludeTxPower(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setInterval(int);
@@ -8183,18 +8188,17 @@
package android.companion {
- public final class AssociationRequest<F extends android.companion.DeviceFilter> implements android.os.Parcelable {
+ public final class AssociationRequest implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.companion.AssociationRequest> CREATOR;
}
- public static final class AssociationRequest.Builder<F extends android.companion.DeviceFilter> {
- method public android.companion.AssociationRequest<F> build();
- method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothDeviceFilter> createForBluetoothDevice();
- method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothLEDeviceFilter> createForBluetoothLEDevice();
- method public android.companion.AssociationRequest.Builder<F> setDeviceFilter(F);
- method public android.companion.AssociationRequest.Builder<F> setSingleDevice(boolean);
+ public static final class AssociationRequest.Builder {
+ ctor public AssociationRequest.Builder();
+ method public android.companion.AssociationRequest.Builder addDeviceFilter(android.companion.DeviceFilter<?>);
+ method public android.companion.AssociationRequest build();
+ method public android.companion.AssociationRequest.Builder setSingleDevice(boolean);
}
public final class BluetoothDeviceFilter implements android.companion.DeviceFilter {
@@ -8213,6 +8217,7 @@
public final class BluetoothLEDeviceFilter implements android.companion.DeviceFilter {
method public int describeContents();
+ method public static int getRenamePrefixLengthLimit();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.companion.BluetoothLEDeviceFilter> CREATOR;
}
@@ -8221,11 +8226,13 @@
ctor public BluetoothLEDeviceFilter.Builder();
method public android.companion.BluetoothLEDeviceFilter build();
method public android.companion.BluetoothLEDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+ method public android.companion.BluetoothLEDeviceFilter.Builder setRawDataFilter(byte[], byte[]);
+ method public android.companion.BluetoothLEDeviceFilter.Builder setRename(java.lang.String, java.lang.String, int, int, boolean);
method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter);
}
public final class CompanionDeviceManager {
- method public void associate(android.companion.AssociationRequest<?>, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
+ method public void associate(android.companion.AssociationRequest, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
method public void disassociate(java.lang.String);
method public java.util.List<java.lang.String> getAssociations();
field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
@@ -8240,6 +8247,18 @@
public abstract interface DeviceFilter<D extends android.os.Parcelable> implements android.os.Parcelable {
}
+ public final class WifiDeviceFilter implements android.companion.DeviceFilter {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.companion.WifiDeviceFilter> CREATOR;
+ }
+
+ public static final class WifiDeviceFilter.Builder {
+ ctor public WifiDeviceFilter.Builder();
+ method public android.companion.WifiDeviceFilter build();
+ method public android.companion.WifiDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+ }
+
}
package android.content {
@@ -12504,6 +12523,7 @@
public class BitmapShader extends android.graphics.Shader {
ctor public BitmapShader(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
+ method public void set(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
}
public class BlurMaskFilter extends android.graphics.MaskFilter {
@@ -12905,6 +12925,8 @@
public class ComposeShader extends android.graphics.Shader {
ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
+ method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
+ method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
}
public class CornerPathEffect extends android.graphics.PathEffect {
@@ -12980,6 +13002,8 @@
public class LinearGradient extends android.graphics.Shader {
ctor public LinearGradient(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
ctor public LinearGradient(float, float, float, float, int, int, android.graphics.Shader.TileMode);
+ method public void set(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
+ method public void set(float, float, float, float, int, int, android.graphics.Shader.TileMode);
}
public class MaskFilter {
@@ -13498,6 +13522,8 @@
public class RadialGradient extends android.graphics.Shader {
ctor public RadialGradient(float, float, float, int[], float[], android.graphics.Shader.TileMode);
ctor public RadialGradient(float, float, float, int, int, android.graphics.Shader.TileMode);
+ method public void set(float, float, float, int[], float[], android.graphics.Shader.TileMode);
+ method public void set(float, float, float, int, int, android.graphics.Shader.TileMode);
}
public final class Rect implements android.os.Parcelable {
@@ -13637,7 +13663,7 @@
}
public class Shader {
- ctor public Shader();
+ ctor public deprecated Shader();
method public boolean getLocalMatrix(android.graphics.Matrix);
method public void setLocalMatrix(android.graphics.Matrix);
}
@@ -13682,6 +13708,8 @@
public class SweepGradient extends android.graphics.Shader {
ctor public SweepGradient(float, float, int[], float[]);
ctor public SweepGradient(float, float, int, int);
+ method public void set(float, float, int[], float[]);
+ method public void set(float, float, int, int);
}
public class Typeface {
@@ -13709,9 +13737,12 @@
public static abstract interface Typeface.FontRequestCallback {
method public abstract void onTypefaceRequestFailed(int);
method public abstract void onTypefaceRetrieved(android.graphics.Typeface);
- field public static final int FAIL_REASON_FONT_LOAD_ERROR = 1; // 0x1
- field public static final int FAIL_REASON_FONT_NOT_FOUND = 2; // 0x2
- field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = 0; // 0x0
+ field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
+ field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
+ field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
+ field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
+ field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
+ field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
}
public class Xfermode {
@@ -20986,7 +21017,7 @@
}
public class AudioManager {
- method public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener);
+ method public deprecated int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener);
method public int abandonAudioFocusRequest(android.media.AudioFocusRequest);
method public void adjustStreamVolume(int, int, int);
method public void adjustSuggestedStreamVolume(int, int, int);
@@ -21023,7 +21054,7 @@
method public deprecated void registerMediaButtonEventReceiver(android.app.PendingIntent);
method public deprecated void registerRemoteControlClient(android.media.RemoteControlClient);
method public deprecated boolean registerRemoteController(android.media.RemoteController);
- method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int);
+ method public deprecated int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int);
method public int requestAudioFocus(android.media.AudioFocusRequest);
method public deprecated void setBluetoothA2dpOn(boolean);
method public void setBluetoothScoOn(boolean);
@@ -26479,7 +26510,8 @@
}
public class DiscoverySession {
- method public java.lang.String createNetworkSpecifier(android.net.wifi.aware.PeerHandle, byte[]);
+ method public java.lang.String createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
+ method public java.lang.String createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
method public void destroy();
method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
}
@@ -26567,7 +26599,8 @@
}
public class WifiAwareSession {
- method public java.lang.String createNetworkSpecifier(int, byte[], byte[]);
+ method public java.lang.String createNetworkSpecifierOpen(int, byte[]);
+ method public java.lang.String createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
method public void destroy();
method public void publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
method public void subscribe(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
@@ -34090,7 +34123,7 @@
method public static android.net.Uri createDocument(android.content.ContentResolver, android.net.Uri, java.lang.String, java.lang.String);
method public static android.content.IntentSender createWebLinkIntent(android.content.ContentResolver, android.net.Uri, android.os.Bundle);
method public static boolean deleteDocument(android.content.ContentResolver, android.net.Uri);
- method public static java.util.List<java.lang.String> findDocumentPath(android.content.ContentResolver, android.net.Uri);
+ method public static android.provider.DocumentsContract.Path findDocumentPath(android.content.ContentResolver, android.net.Uri);
method public static java.lang.String getDocumentId(android.net.Uri);
method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal);
method public static java.lang.String getRootId(android.net.Uri);
@@ -34206,6 +34239,11 @@
public static final class FontsContract.Columns implements android.provider.BaseColumns {
ctor public FontsContract.Columns();
+ field public static final java.lang.String RESULT_CODE = "result_code";
+ field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
+ field public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; // 0x2
+ field public static final int RESULT_CODE_MALFORMED_QUERY = 3; // 0x3
+ field public static final int RESULT_CODE_OK = 0; // 0x0
field public static final java.lang.String STYLE = "font_style";
field public static final java.lang.String TTC_INDEX = "font_ttc_index";
field public static final java.lang.String VARIATION_SETTINGS = "font_variation_settings";
@@ -36688,15 +36726,15 @@
package android.service.autofill {
- public abstract class AutoFillService extends android.app.Service {
- ctor public AutoFillService();
+ public abstract class AutofillService extends android.app.Service {
+ ctor public AutofillService();
method public final void disableSelf();
method public final android.os.IBinder onBind(android.content.Intent);
method public void onConnected();
method public void onDisconnected();
method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback);
method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
- field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
+ field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillService";
field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
}
@@ -36710,7 +36748,7 @@
ctor public Dataset.Builder(android.widget.RemoteViews);
method public android.service.autofill.Dataset build();
method public android.service.autofill.Dataset.Builder setAuthentication(android.content.IntentSender);
- method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutoFillId, android.view.autofill.AutoFillValue);
+ method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue);
}
public final class FillCallback {
@@ -36750,7 +36788,7 @@
public static final class SaveInfo.Builder {
ctor public SaveInfo.Builder(int);
- method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
+ method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutofillId...);
method public android.service.autofill.SaveInfo build();
method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
method public android.service.autofill.SaveInfo.Builder setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
@@ -39788,7 +39826,7 @@
method public int getSimState();
method public int getSimState(int);
method public java.lang.String getSubscriberId();
- method public java.lang.String getVisualVoicemailPackageName(android.telecom.PhoneAccountHandle);
+ method public java.lang.String getVisualVoicemailPackageName();
method public java.lang.String getVoiceMailAlphaTag();
method public java.lang.String getVoiceMailNumber();
method public int getVoiceNetworkType();
@@ -39928,9 +39966,6 @@
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.telephony.VisualVoicemailSmsFilterSettings> CREATOR;
- field public static final java.lang.String DEFAULT_CLIENT_PREFIX = "//VVM";
- field public static final int DEFAULT_DESTINATION_PORT = -1; // 0xffffffff
- field public static final java.util.List<java.lang.String> DEFAULT_ORIGINATING_NUMBERS;
field public static final int DESTINATION_PORT_ANY = -1; // 0xffffffff
field public static final int DESTINATION_PORT_DATA_SMS = -2; // 0xfffffffe
field public final java.lang.String clientPrefix;
@@ -44961,8 +44996,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 void autofill(android.view.autofill.AutofillValue);
+ method public void autofillVirtual(int, android.view.autofill.AutofillValue);
method protected boolean awakenScrollBars();
method protected boolean awakenScrollBars(int);
method protected boolean awakenScrollBars(int, boolean);
@@ -45016,7 +45051,7 @@
method public boolean dispatchNestedScroll(int, int, int, int, int[]);
method public void dispatchPointerCaptureChanged(boolean);
method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
- method public void dispatchProvideAutoFillStructure(android.view.ViewStructure, int);
+ method public void dispatchProvideAutofillStructure(android.view.ViewStructure, int);
method public void dispatchProvideStructure(android.view.ViewStructure);
method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>);
method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>);
@@ -45052,11 +45087,10 @@
method public float getAlpha();
method public android.view.animation.Animation getAnimation();
method public android.os.IBinder getApplicationWindowToken();
- method public int getAutoFillHint();
- method public int getAutoFillMode();
- method public final deprecated android.view.autofill.AutoFillType getAutoFillType();
- method public android.view.autofill.AutoFillValue getAutoFillValue();
+ method public int getAutofillHint();
+ method public int getAutofillMode();
method public int getAutofillType();
+ method public android.view.autofill.AutofillValue getAutofillValue();
method public android.graphics.drawable.Drawable getBackground();
method public android.content.res.ColorStateList getBackgroundTintList();
method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -45142,7 +45176,7 @@
method public float getPivotX();
method public float getPivotY();
method public android.view.PointerIcon getPointerIcon();
- method public int getResolvedAutoFillMode();
+ method public int getResolvedAutofillMode();
method public android.content.res.Resources getResources();
method public final boolean getRevealOnFocusHint();
method public final int getRight();
@@ -45301,8 +45335,8 @@
method protected void onOverScrolled(int, int, boolean, boolean);
method public void onPointerCaptureChange(boolean);
method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
- method public void onProvideAutoFillStructure(android.view.ViewStructure, int);
- method public void onProvideAutoFillVirtualStructure(android.view.ViewStructure, int);
+ method public void onProvideAutofillStructure(android.view.ViewStructure, int);
+ method public void onProvideAutofillVirtualStructure(android.view.ViewStructure, int);
method public void onProvideStructure(android.view.ViewStructure);
method public void onProvideVirtualStructure(android.view.ViewStructure);
method public android.view.PointerIcon onResolvePointerIcon(android.view.MotionEvent, int);
@@ -45374,8 +45408,8 @@
method public void setActivated(boolean);
method public void setAlpha(float);
method public void setAnimation(android.view.animation.Animation);
- method public void setAutoFillHint(int);
- method public void setAutoFillMode(int);
+ method public void setAutofillHint(int);
+ method public void setAutofillMode(int);
method public void setBackground(android.graphics.drawable.Drawable);
method public void setBackgroundColor(int);
method public deprecated void setBackgroundDrawable(android.graphics.drawable.Drawable);
@@ -45517,28 +45551,28 @@
field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
+ field public static final int AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE = 512; // 0x200
+ field public static final int AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = 4096; // 0x1000
+ field public static final int AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = 1024; // 0x400
+ field public static final int AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR = 2048; // 0x800
+ field public static final int AUTOFILL_HINT_CREDIT_CARD_NUMBER = 128; // 0x80
+ field public static final int AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = 256; // 0x100
+ field public static final int AUTOFILL_HINT_EMAIL_ADDRESS = 1; // 0x1
+ field public static final int AUTOFILL_HINT_NAME = 2; // 0x2
+ field public static final int AUTOFILL_HINT_NONE = 0; // 0x0
+ field public static final int AUTOFILL_HINT_PASSWORD = 8; // 0x8
+ field public static final int AUTOFILL_HINT_PHONE = 16; // 0x10
+ field public static final int AUTOFILL_HINT_POSTAL_ADDRESS = 32; // 0x20
+ field public static final int AUTOFILL_HINT_POSTAL_CODE = 64; // 0x40
+ field public static final int AUTOFILL_HINT_USERNAME = 4; // 0x4
+ field public static final int AUTOFILL_MODE_AUTO = 1; // 0x1
+ field public static final int AUTOFILL_MODE_INHERIT = 0; // 0x0
+ field public static final int AUTOFILL_MODE_MANUAL = 2; // 0x2
field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
field public static final int AUTOFILL_TYPE_TEXT = 1; // 0x1
field public static final int AUTOFILL_TYPE_TOGGLE = 2; // 0x2
- field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DATE = 512; // 0x200
- field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DAY = 4096; // 0x1000
- field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = 1024; // 0x400
- field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_YEAR = 2048; // 0x800
- field public static final int AUTO_FILL_HINT_CREDIT_CARD_NUMBER = 128; // 0x80
- field public static final int AUTO_FILL_HINT_CREDIT_CARD_SECURITY_CODE = 256; // 0x100
- field public static final int AUTO_FILL_HINT_EMAIL_ADDRESS = 1; // 0x1
- field public static final int AUTO_FILL_HINT_NAME = 2; // 0x2
- field public static final int AUTO_FILL_HINT_NONE = 0; // 0x0
- field public static final int AUTO_FILL_HINT_PASSWORD = 8; // 0x8
- field public static final int AUTO_FILL_HINT_PHONE = 16; // 0x10
- field public static final int AUTO_FILL_HINT_POSTAL_ADDRESS = 32; // 0x20
- field public static final int AUTO_FILL_HINT_POSTAL_CODE = 64; // 0x40
- field public static final int AUTO_FILL_HINT_USERNAME = 4; // 0x4
- field public static final int AUTO_FILL_MODE_AUTO = 1; // 0x1
- field public static final int AUTO_FILL_MODE_INHERIT = 0; // 0x0
- field public static final int AUTO_FILL_MODE_MANUAL = 2; // 0x2
field public static final int DRAG_FLAG_GLOBAL = 256; // 0x100
field public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION = 64; // 0x40
field public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION = 128; // 0x80
@@ -46100,7 +46134,7 @@
method public abstract int getLayoutDirection();
method public abstract android.view.ViewParent getParent();
method public abstract android.view.ViewParent getParentForAccessibility();
- method public default int getResolvedAutoFillMode();
+ method public default int getResolvedAutofillMode();
method public abstract int getTextAlignment();
method public abstract int getTextDirection();
method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect);
@@ -46179,7 +46213,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 asyncNewChildForAutofill(int, int, int);
method public abstract int getChildCount();
method public abstract android.os.Bundle getExtras();
method public abstract java.lang.CharSequence getHint();
@@ -46188,15 +46222,14 @@
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 newChildForAutofill(int, int, int);
method public abstract void setAccessibilityFocused(boolean);
method public abstract void setActivated(boolean);
method public abstract void setAlpha(float);
- method public abstract void setAutoFillHint(int);
- method public abstract void setAutoFillOptions(java.lang.String[]);
- method public abstract deprecated void setAutoFillType(android.view.autofill.AutoFillType);
- method public abstract void setAutoFillValue(android.view.autofill.AutoFillValue);
+ method public abstract void setAutofillHint(int);
+ method public abstract void setAutofillOptions(java.lang.String[]);
method public abstract void setAutofillType(int);
+ method public abstract void setAutofillValue(android.view.autofill.AutofillValue);
method public abstract void setCheckable(boolean);
method public abstract void setChecked(boolean);
method public abstract void setChildCount(int);
@@ -46213,6 +46246,7 @@
method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
method public abstract void setInputType(int);
method public abstract void setLongClickable(boolean);
+ method public abstract void setOpaque(boolean);
method public abstract void setSanitized(boolean);
method public abstract void setSelected(boolean);
method public abstract void setText(java.lang.CharSequence);
@@ -46930,6 +46964,8 @@
field public static final java.lang.String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
field public static final java.lang.String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT = "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
+ field public static final java.lang.String ACTION_ARGUMENT_MOVE_WINDOW_X = "android.view.accessibility.action.ARGUMENT_MOVE_WINDOW_X";
+ field public static final java.lang.String ACTION_ARGUMENT_MOVE_WINDOW_Y = "android.view.accessibility.action.ARGUMENT_MOVE_WINDOW_Y";
field public static final java.lang.String ACTION_ARGUMENT_PROGRESS_VALUE = "android.view.accessibility.action.ARGUMENT_PROGRESS_VALUE";
field public static final java.lang.String ACTION_ARGUMENT_ROW_INT = "android.view.accessibility.action.ARGUMENT_ROW_INT";
field public static final java.lang.String ACTION_ARGUMENT_SELECTION_END_INT = "ACTION_ARGUMENT_SELECTION_END_INT";
@@ -46986,6 +47022,7 @@
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_EXPAND;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_FOCUS;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_LONG_CLICK;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_MOVE_WINDOW;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_NEXT_AT_MOVEMENT_GRANULARITY;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_NEXT_HTML_ELEMENT;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PASTE;
@@ -47110,6 +47147,7 @@
method public android.view.accessibility.AccessibilityNodeInfo getRoot();
method public java.lang.CharSequence getTitle();
method public int getType();
+ method public boolean inPictureInPicture();
method public boolean isAccessibilityFocused();
method public boolean isActive();
method public boolean isFocused();
@@ -47445,60 +47483,46 @@
package android.view.autofill {
- public final class AutoFillId implements android.os.Parcelable {
+ public final class AutofillId implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.view.autofill.AutoFillId> CREATOR;
+ field public static final android.os.Parcelable.Creator<android.view.autofill.AutofillId> CREATOR;
}
- public final class AutoFillManager {
- method public void registerCallback(android.view.autofill.AutoFillManager.AutofillCallback);
+ public final class AutofillManager {
+ method public void registerCallback(android.view.autofill.AutofillManager.AutofillCallback);
method public void reset();
- method public void startAutoFillRequest(android.view.View);
- method public void startAutoFillRequestOnVirtualView(android.view.View, int, android.graphics.Rect);
- method public void stopAutoFillRequest(android.view.View);
- method public void stopAutoFillRequestOnVirtualView(android.view.View, int);
- method public void unregisterCallback(android.view.autofill.AutoFillManager.AutofillCallback);
+ method public void startAutofillRequest(android.view.View);
+ method public void startAutofillRequestOnVirtualView(android.view.View, int, android.graphics.Rect);
+ method public void stopAutofillRequest(android.view.View);
+ method public void stopAutofillRequestOnVirtualView(android.view.View, int);
+ method public void unregisterCallback(android.view.autofill.AutofillManager.AutofillCallback);
method public void valueChanged(android.view.View);
- method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue);
+ method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutofillValue);
field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
}
- public static abstract class AutoFillManager.AutofillCallback {
- ctor public AutoFillManager.AutofillCallback();
+ public static abstract class AutofillManager.AutofillCallback {
+ ctor public AutofillManager.AutofillCallback();
method public void onAutofillEvent(android.view.View, int);
method public void onAutofillEventVirtual(android.view.View, int, int);
field public static final int EVENT_INPUT_HIDDEN = 2; // 0x2
field public static final int EVENT_INPUT_SHOWN = 1; // 0x1
}
- public final class AutoFillType implements android.os.Parcelable {
+ public final class AutofillValue implements android.os.Parcelable {
method public int describeContents();
- method public static android.view.autofill.AutoFillType forDate();
- method public static android.view.autofill.AutoFillType forList();
- method public static android.view.autofill.AutoFillType forText();
- method public static android.view.autofill.AutoFillType forToggle();
- method public boolean isDate();
- method public boolean isList();
- method public boolean isText();
- method public boolean isToggle();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.view.autofill.AutoFillType> CREATOR;
- }
-
- public final class AutoFillValue implements android.os.Parcelable {
- method public int describeContents();
- method public static android.view.autofill.AutoFillValue forDate(long);
- method public static android.view.autofill.AutoFillValue forList(int);
- method public static android.view.autofill.AutoFillValue forText(java.lang.CharSequence);
- method public static android.view.autofill.AutoFillValue forToggle(boolean);
+ method public static android.view.autofill.AutofillValue forDate(long);
+ method public static android.view.autofill.AutofillValue forList(int);
+ method public static android.view.autofill.AutofillValue forText(java.lang.CharSequence);
+ method public static android.view.autofill.AutofillValue forToggle(boolean);
method public long getDateValue();
method public int getListValue();
method public java.lang.CharSequence getTextValue();
method public boolean getToggleValue();
method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.view.autofill.AutoFillValue> CREATOR;
+ field public static final android.os.Parcelable.Creator<android.view.autofill.AutofillValue> CREATOR;
}
}
diff --git a/api/system-current.txt b/api/system-current.txt
index e9af523..959adf58 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -30,6 +30,7 @@
field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
+ field public static final java.lang.String BIND_AUTOFILL = "android.permission.BIND_AUTOFILL";
field public static final java.lang.String BIND_AUTO_FILL = "android.permission.BIND_AUTO_FILL";
field public static final deprecated java.lang.String BIND_CARRIER_MESSAGING_SERVICE = "android.permission.BIND_CARRIER_MESSAGING_SERVICE";
field public static final java.lang.String BIND_CARRIER_SERVICES = "android.permission.BIND_CARRIER_SERVICES";
@@ -159,6 +160,7 @@
field public static final java.lang.String MOUNT_UNMOUNT_FILESYSTEMS = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS";
field public static final java.lang.String MOVE_PACKAGE = "android.permission.MOVE_PACKAGE";
field public static final java.lang.String NFC = "android.permission.NFC";
+ field public static final java.lang.String NOTIFICATION_DURING_SETUP = "android.permission.NOTIFICATION_DURING_SETUP";
field public static final java.lang.String OVERRIDE_WIFI_CONFIG = "android.permission.OVERRIDE_WIFI_CONFIG";
field public static final java.lang.String PACKAGE_USAGE_STATS = "android.permission.PACKAGE_USAGE_STATS";
field public static final java.lang.String PACKAGE_VERIFICATION_AGENT = "android.permission.PACKAGE_VERIFICATION_AGENT";
@@ -410,8 +412,6 @@
field public static final int authorities = 16842776; // 0x1010018
field public static final int autoAdvanceViewId = 16843535; // 0x101030f
field public static final int autoCompleteTextViewStyle = 16842859; // 0x101006b
- field public static final int autoFillHint = 16844121; // 0x1010559
- field public static final int autoFillMode = 16844116; // 0x1010554
field public static final int autoLink = 16842928; // 0x10100b0
field public static final int autoMirrored = 16843754; // 0x10103ea
field public static final int autoRemoveFromRecents = 16843847; // 0x1010447
@@ -424,6 +424,8 @@
field public static final deprecated int autoText = 16843114; // 0x101016a
field public static final int autoUrlDetect = 16843404; // 0x101028c
field public static final int autoVerify = 16844014; // 0x10104ee
+ field public static final int autofillHint = 16844121; // 0x1010559
+ field public static final int autofillMode = 16844116; // 0x1010554
field public static final int background = 16842964; // 0x10100d4
field public static final int backgroundDimAmount = 16842802; // 0x1010032
field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -1894,6 +1896,7 @@
public static final class R.id {
ctor public R.id();
field public static final int accessibilityActionContextClick = 16908348; // 0x102003c
+ field public static final int accessibilityActionMoveWindow = 16908354; // 0x1020042
field public static final int accessibilityActionScrollDown = 16908346; // 0x102003a
field public static final int accessibilityActionScrollLeft = 16908345; // 0x1020039
field public static final int accessibilityActionScrollRight = 16908347; // 0x102003b
@@ -6800,9 +6803,12 @@
public class AssistStructure implements android.os.Parcelable {
ctor public AssistStructure();
method public int describeContents();
+ method public long getAcquisitionEndTime();
+ method public long getAcquisitionStartTime();
method public android.content.ComponentName getActivityComponent();
method public android.app.assist.AssistStructure.WindowNode getWindowNodeAt(int);
method public int getWindowNodeCount();
+ method public boolean isHomeActivity();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.assist.AssistStructure> CREATOR;
}
@@ -6810,11 +6816,10 @@
public static class AssistStructure.ViewNode {
method public float getAlpha();
method public int getAutoFillHint();
- method public android.view.autofill.AutoFillId getAutoFillId();
- method public java.lang.String[] getAutoFillOptions();
- method public deprecated android.view.autofill.AutoFillType getAutoFillType();
- method public android.view.autofill.AutoFillValue getAutoFillValue();
+ method public android.view.autofill.AutofillId getAutofillId();
+ method public java.lang.String[] getAutofillOptions();
method public int getAutofillType();
+ method public android.view.autofill.AutofillValue getAutofillValue();
method public android.app.assist.AssistStructure.ViewNode getChildAt(int);
method public int getChildCount();
method public java.lang.String getClassName();
@@ -6856,6 +6861,7 @@
method public boolean isFocusable();
method public boolean isFocused();
method public boolean isLongClickable();
+ method public boolean isOpaque();
method public boolean isSelected();
field public static final int TEXT_COLOR_UNDEFINED = 1; // 0x1
field public static final int TEXT_STYLE_BOLD = 1; // 0x1
@@ -8464,7 +8470,7 @@
public static final class AdvertisingSetParameters.Builder {
ctor public AdvertisingSetParameters.Builder();
method public android.bluetooth.le.AdvertisingSetParameters build();
- method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymouus(boolean);
+ method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymous(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setConnectable(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setIncludeTxPower(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setInterval(int);
@@ -8683,18 +8689,17 @@
package android.companion {
- public final class AssociationRequest<F extends android.companion.DeviceFilter> implements android.os.Parcelable {
+ public final class AssociationRequest implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.companion.AssociationRequest> CREATOR;
}
- public static final class AssociationRequest.Builder<F extends android.companion.DeviceFilter> {
- method public android.companion.AssociationRequest<F> build();
- method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothDeviceFilter> createForBluetoothDevice();
- method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothLEDeviceFilter> createForBluetoothLEDevice();
- method public android.companion.AssociationRequest.Builder<F> setDeviceFilter(F);
- method public android.companion.AssociationRequest.Builder<F> setSingleDevice(boolean);
+ public static final class AssociationRequest.Builder {
+ ctor public AssociationRequest.Builder();
+ method public android.companion.AssociationRequest.Builder addDeviceFilter(android.companion.DeviceFilter<?>);
+ method public android.companion.AssociationRequest build();
+ method public android.companion.AssociationRequest.Builder setSingleDevice(boolean);
}
public final class BluetoothDeviceFilter implements android.companion.DeviceFilter {
@@ -8713,6 +8718,7 @@
public final class BluetoothLEDeviceFilter implements android.companion.DeviceFilter {
method public int describeContents();
+ method public static int getRenamePrefixLengthLimit();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.companion.BluetoothLEDeviceFilter> CREATOR;
}
@@ -8721,11 +8727,13 @@
ctor public BluetoothLEDeviceFilter.Builder();
method public android.companion.BluetoothLEDeviceFilter build();
method public android.companion.BluetoothLEDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+ method public android.companion.BluetoothLEDeviceFilter.Builder setRawDataFilter(byte[], byte[]);
+ method public android.companion.BluetoothLEDeviceFilter.Builder setRename(java.lang.String, java.lang.String, int, int, boolean);
method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter);
}
public final class CompanionDeviceManager {
- method public void associate(android.companion.AssociationRequest<?>, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
+ method public void associate(android.companion.AssociationRequest, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
method public void disassociate(java.lang.String);
method public java.util.List<java.lang.String> getAssociations();
field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
@@ -8740,6 +8748,18 @@
public abstract interface DeviceFilter<D extends android.os.Parcelable> implements android.os.Parcelable {
}
+ public final class WifiDeviceFilter implements android.companion.DeviceFilter {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.companion.WifiDeviceFilter> CREATOR;
+ }
+
+ public static final class WifiDeviceFilter.Builder {
+ ctor public WifiDeviceFilter.Builder();
+ method public android.companion.WifiDeviceFilter build();
+ method public android.companion.WifiDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+ }
+
}
package android.content {
@@ -13240,6 +13260,7 @@
public class BitmapShader extends android.graphics.Shader {
ctor public BitmapShader(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
+ method public void set(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
}
public class BlurMaskFilter extends android.graphics.MaskFilter {
@@ -13641,6 +13662,8 @@
public class ComposeShader extends android.graphics.Shader {
ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
+ method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
+ method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
}
public class CornerPathEffect extends android.graphics.PathEffect {
@@ -13716,6 +13739,8 @@
public class LinearGradient extends android.graphics.Shader {
ctor public LinearGradient(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
ctor public LinearGradient(float, float, float, float, int, int, android.graphics.Shader.TileMode);
+ method public void set(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
+ method public void set(float, float, float, float, int, int, android.graphics.Shader.TileMode);
}
public class MaskFilter {
@@ -14234,6 +14259,8 @@
public class RadialGradient extends android.graphics.Shader {
ctor public RadialGradient(float, float, float, int[], float[], android.graphics.Shader.TileMode);
ctor public RadialGradient(float, float, float, int, int, android.graphics.Shader.TileMode);
+ method public void set(float, float, float, int[], float[], android.graphics.Shader.TileMode);
+ method public void set(float, float, float, int, int, android.graphics.Shader.TileMode);
}
public final class Rect implements android.os.Parcelable {
@@ -14373,7 +14400,7 @@
}
public class Shader {
- ctor public Shader();
+ ctor public deprecated Shader();
method public boolean getLocalMatrix(android.graphics.Matrix);
method public void setLocalMatrix(android.graphics.Matrix);
}
@@ -14418,6 +14445,8 @@
public class SweepGradient extends android.graphics.Shader {
ctor public SweepGradient(float, float, int[], float[]);
ctor public SweepGradient(float, float, int, int);
+ method public void set(float, float, int[], float[]);
+ method public void set(float, float, int, int);
}
public class Typeface {
@@ -14445,9 +14474,12 @@
public static abstract interface Typeface.FontRequestCallback {
method public abstract void onTypefaceRequestFailed(int);
method public abstract void onTypefaceRetrieved(android.graphics.Typeface);
- field public static final int FAIL_REASON_FONT_LOAD_ERROR = 1; // 0x1
- field public static final int FAIL_REASON_FONT_NOT_FOUND = 2; // 0x2
- field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = 0; // 0x0
+ field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
+ field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
+ field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
+ field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
+ field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
+ field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
}
public class Xfermode {
@@ -22750,7 +22782,7 @@
}
public class AudioManager {
- method public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener);
+ method public deprecated int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener);
method public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes);
method public int abandonAudioFocusRequest(android.media.AudioFocusRequest);
method public void adjustStreamVolume(int, int, int);
@@ -22790,7 +22822,7 @@
method public deprecated void registerMediaButtonEventReceiver(android.app.PendingIntent);
method public deprecated void registerRemoteControlClient(android.media.RemoteControlClient);
method public deprecated boolean registerRemoteController(android.media.RemoteController);
- method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int);
+ method public deprecated int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int);
method public int requestAudioFocus(android.media.AudioFocusRequest);
method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int) throws java.lang.IllegalArgumentException;
method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int, android.media.audiopolicy.AudioPolicy) throws java.lang.IllegalArgumentException;
@@ -26957,7 +26989,6 @@
method public android.metrics.LogMaker clearPackageName();
method public android.metrics.LogMaker clearSubtype();
method public android.metrics.LogMaker clearTaggedData(int);
- method public android.metrics.LogMaker clearTimestamp();
method public android.metrics.LogMaker clearType();
method public void deserialize(java.lang.Object[]);
method public int getCategory();
@@ -26965,6 +26996,7 @@
method public java.lang.String getCounterName();
method public int getCounterValue();
method public java.lang.String getPackageName();
+ method public int getProcessId();
method public int getSubtype();
method public java.lang.Object getTaggedData(int);
method public long getTimestamp();
@@ -26974,13 +27006,8 @@
method public boolean isValidValue(java.lang.Object);
method public java.lang.Object[] serialize();
method public android.metrics.LogMaker setCategory(int);
- method public android.metrics.LogMaker setCounterBucket(int);
- method public android.metrics.LogMaker setCounterBucket(long);
- method public android.metrics.LogMaker setCounterName(java.lang.String);
- method public android.metrics.LogMaker setCounterValue(int);
method public android.metrics.LogMaker setPackageName(java.lang.String);
method public android.metrics.LogMaker setSubtype(int);
- method public android.metrics.LogMaker setTimestamp(long);
method public android.metrics.LogMaker setType(int);
}
@@ -29179,7 +29206,9 @@
}
public class DiscoverySession {
- method public java.lang.String createNetworkSpecifier(android.net.wifi.aware.PeerHandle, byte[]);
+ method public java.lang.String createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
+ method public java.lang.String createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
+ method public java.lang.String createNetworkSpecifierPmk(android.net.wifi.aware.PeerHandle, byte[]);
method public void destroy();
method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
}
@@ -29267,7 +29296,9 @@
}
public class WifiAwareSession {
- method public java.lang.String createNetworkSpecifier(int, byte[], byte[]);
+ method public java.lang.String createNetworkSpecifierOpen(int, byte[]);
+ method public java.lang.String createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
+ method public java.lang.String createNetworkSpecifierPmk(int, byte[], byte[]);
method public void destroy();
method public void publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
method public void subscribe(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
@@ -36997,7 +37028,7 @@
method public static android.net.Uri createDocument(android.content.ContentResolver, android.net.Uri, java.lang.String, java.lang.String);
method public static android.content.IntentSender createWebLinkIntent(android.content.ContentResolver, android.net.Uri, android.os.Bundle);
method public static boolean deleteDocument(android.content.ContentResolver, android.net.Uri);
- method public static java.util.List<java.lang.String> findDocumentPath(android.content.ContentResolver, android.net.Uri);
+ method public static android.provider.DocumentsContract.Path findDocumentPath(android.content.ContentResolver, android.net.Uri);
method public static java.lang.String getDocumentId(android.net.Uri);
method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal);
method public static java.lang.String getRootId(android.net.Uri);
@@ -37113,6 +37144,11 @@
public static final class FontsContract.Columns implements android.provider.BaseColumns {
ctor public FontsContract.Columns();
+ field public static final java.lang.String RESULT_CODE = "result_code";
+ field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
+ field public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; // 0x2
+ field public static final int RESULT_CODE_MALFORMED_QUERY = 3; // 0x3
+ field public static final int RESULT_CODE_OK = 0; // 0x0
field public static final java.lang.String STYLE = "font_style";
field public static final java.lang.String TTC_INDEX = "font_ttc_index";
field public static final java.lang.String VARIATION_SETTINGS = "font_variation_settings";
@@ -39723,15 +39759,15 @@
package android.service.autofill {
- public abstract class AutoFillService extends android.app.Service {
- ctor public AutoFillService();
+ public abstract class AutofillService extends android.app.Service {
+ ctor public AutofillService();
method public final void disableSelf();
method public final android.os.IBinder onBind(android.content.Intent);
method public void onConnected();
method public void onDisconnected();
method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback);
method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
- field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
+ field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillService";
field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
}
@@ -39745,7 +39781,7 @@
ctor public Dataset.Builder(android.widget.RemoteViews);
method public android.service.autofill.Dataset build();
method public android.service.autofill.Dataset.Builder setAuthentication(android.content.IntentSender);
- method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutoFillId, android.view.autofill.AutoFillValue);
+ method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue);
}
public final class FillCallback {
@@ -39785,7 +39821,7 @@
public static final class SaveInfo.Builder {
ctor public SaveInfo.Builder(int);
- method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
+ method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutofillId...);
method public android.service.autofill.SaveInfo build();
method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
method public android.service.autofill.SaveInfo.Builder setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
@@ -43193,7 +43229,7 @@
method public int getSimState(int);
method public java.lang.String getSubscriberId();
method public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
- method public java.lang.String getVisualVoicemailPackageName(android.telecom.PhoneAccountHandle);
+ method public java.lang.String getVisualVoicemailPackageName();
method public java.lang.String getVoiceMailAlphaTag();
method public java.lang.String getVoiceMailNumber();
method public int getVoiceNetworkType();
@@ -43359,9 +43395,6 @@
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.telephony.VisualVoicemailSmsFilterSettings> CREATOR;
- field public static final java.lang.String DEFAULT_CLIENT_PREFIX = "//VVM";
- field public static final int DEFAULT_DESTINATION_PORT = -1; // 0xffffffff
- field public static final java.util.List<java.lang.String> DEFAULT_ORIGINATING_NUMBERS;
field public static final int DESTINATION_PORT_ANY = -1; // 0xffffffff
field public static final int DESTINATION_PORT_DATA_SMS = -2; // 0xfffffffe
field public final java.lang.String clientPrefix;
@@ -48423,8 +48456,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 void autofill(android.view.autofill.AutofillValue);
+ method public void autofillVirtual(int, android.view.autofill.AutofillValue);
method protected boolean awakenScrollBars();
method protected boolean awakenScrollBars(int);
method protected boolean awakenScrollBars(int, boolean);
@@ -48478,7 +48511,7 @@
method public boolean dispatchNestedScroll(int, int, int, int, int[]);
method public void dispatchPointerCaptureChanged(boolean);
method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
- method public void dispatchProvideAutoFillStructure(android.view.ViewStructure, int);
+ method public void dispatchProvideAutofillStructure(android.view.ViewStructure, int);
method public void dispatchProvideStructure(android.view.ViewStructure);
method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>);
method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>);
@@ -48514,11 +48547,10 @@
method public float getAlpha();
method public android.view.animation.Animation getAnimation();
method public android.os.IBinder getApplicationWindowToken();
- method public int getAutoFillHint();
- method public int getAutoFillMode();
- method public final deprecated android.view.autofill.AutoFillType getAutoFillType();
- method public android.view.autofill.AutoFillValue getAutoFillValue();
+ method public int getAutofillHint();
+ method public int getAutofillMode();
method public int getAutofillType();
+ method public android.view.autofill.AutofillValue getAutofillValue();
method public android.graphics.drawable.Drawable getBackground();
method public android.content.res.ColorStateList getBackgroundTintList();
method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -48604,7 +48636,7 @@
method public float getPivotX();
method public float getPivotY();
method public android.view.PointerIcon getPointerIcon();
- method public int getResolvedAutoFillMode();
+ method public int getResolvedAutofillMode();
method public android.content.res.Resources getResources();
method public final boolean getRevealOnFocusHint();
method public final int getRight();
@@ -48763,8 +48795,8 @@
method protected void onOverScrolled(int, int, boolean, boolean);
method public void onPointerCaptureChange(boolean);
method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
- method public void onProvideAutoFillStructure(android.view.ViewStructure, int);
- method public void onProvideAutoFillVirtualStructure(android.view.ViewStructure, int);
+ method public void onProvideAutofillStructure(android.view.ViewStructure, int);
+ method public void onProvideAutofillVirtualStructure(android.view.ViewStructure, int);
method public void onProvideStructure(android.view.ViewStructure);
method public void onProvideVirtualStructure(android.view.ViewStructure);
method public android.view.PointerIcon onResolvePointerIcon(android.view.MotionEvent, int);
@@ -48836,8 +48868,8 @@
method public void setActivated(boolean);
method public void setAlpha(float);
method public void setAnimation(android.view.animation.Animation);
- method public void setAutoFillHint(int);
- method public void setAutoFillMode(int);
+ method public void setAutofillHint(int);
+ method public void setAutofillMode(int);
method public void setBackground(android.graphics.drawable.Drawable);
method public void setBackgroundColor(int);
method public deprecated void setBackgroundDrawable(android.graphics.drawable.Drawable);
@@ -48979,28 +49011,28 @@
field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
+ field public static final int AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE = 512; // 0x200
+ field public static final int AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = 4096; // 0x1000
+ field public static final int AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = 1024; // 0x400
+ field public static final int AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR = 2048; // 0x800
+ field public static final int AUTOFILL_HINT_CREDIT_CARD_NUMBER = 128; // 0x80
+ field public static final int AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = 256; // 0x100
+ field public static final int AUTOFILL_HINT_EMAIL_ADDRESS = 1; // 0x1
+ field public static final int AUTOFILL_HINT_NAME = 2; // 0x2
+ field public static final int AUTOFILL_HINT_NONE = 0; // 0x0
+ field public static final int AUTOFILL_HINT_PASSWORD = 8; // 0x8
+ field public static final int AUTOFILL_HINT_PHONE = 16; // 0x10
+ field public static final int AUTOFILL_HINT_POSTAL_ADDRESS = 32; // 0x20
+ field public static final int AUTOFILL_HINT_POSTAL_CODE = 64; // 0x40
+ field public static final int AUTOFILL_HINT_USERNAME = 4; // 0x4
+ field public static final int AUTOFILL_MODE_AUTO = 1; // 0x1
+ field public static final int AUTOFILL_MODE_INHERIT = 0; // 0x0
+ field public static final int AUTOFILL_MODE_MANUAL = 2; // 0x2
field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
field public static final int AUTOFILL_TYPE_TEXT = 1; // 0x1
field public static final int AUTOFILL_TYPE_TOGGLE = 2; // 0x2
- field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DATE = 512; // 0x200
- field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DAY = 4096; // 0x1000
- field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = 1024; // 0x400
- field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_YEAR = 2048; // 0x800
- field public static final int AUTO_FILL_HINT_CREDIT_CARD_NUMBER = 128; // 0x80
- field public static final int AUTO_FILL_HINT_CREDIT_CARD_SECURITY_CODE = 256; // 0x100
- field public static final int AUTO_FILL_HINT_EMAIL_ADDRESS = 1; // 0x1
- field public static final int AUTO_FILL_HINT_NAME = 2; // 0x2
- field public static final int AUTO_FILL_HINT_NONE = 0; // 0x0
- field public static final int AUTO_FILL_HINT_PASSWORD = 8; // 0x8
- field public static final int AUTO_FILL_HINT_PHONE = 16; // 0x10
- field public static final int AUTO_FILL_HINT_POSTAL_ADDRESS = 32; // 0x20
- field public static final int AUTO_FILL_HINT_POSTAL_CODE = 64; // 0x40
- field public static final int AUTO_FILL_HINT_USERNAME = 4; // 0x4
- field public static final int AUTO_FILL_MODE_AUTO = 1; // 0x1
- field public static final int AUTO_FILL_MODE_INHERIT = 0; // 0x0
- field public static final int AUTO_FILL_MODE_MANUAL = 2; // 0x2
field public static final int DRAG_FLAG_GLOBAL = 256; // 0x100
field public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION = 64; // 0x40
field public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION = 128; // 0x80
@@ -49562,7 +49594,7 @@
method public abstract int getLayoutDirection();
method public abstract android.view.ViewParent getParent();
method public abstract android.view.ViewParent getParentForAccessibility();
- method public default int getResolvedAutoFillMode();
+ method public default int getResolvedAutofillMode();
method public abstract int getTextAlignment();
method public abstract int getTextDirection();
method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect);
@@ -49641,7 +49673,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 asyncNewChildForAutofill(int, int, int);
method public abstract int getChildCount();
method public abstract android.os.Bundle getExtras();
method public abstract java.lang.CharSequence getHint();
@@ -49650,15 +49682,14 @@
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 newChildForAutofill(int, int, int);
method public abstract void setAccessibilityFocused(boolean);
method public abstract void setActivated(boolean);
method public abstract void setAlpha(float);
- method public abstract void setAutoFillHint(int);
- method public abstract void setAutoFillOptions(java.lang.String[]);
- method public abstract deprecated void setAutoFillType(android.view.autofill.AutoFillType);
- method public abstract void setAutoFillValue(android.view.autofill.AutoFillValue);
+ method public abstract void setAutofillHint(int);
+ method public abstract void setAutofillOptions(java.lang.String[]);
method public abstract void setAutofillType(int);
+ method public abstract void setAutofillValue(android.view.autofill.AutofillValue);
method public abstract void setCheckable(boolean);
method public abstract void setChecked(boolean);
method public abstract void setChildCount(int);
@@ -49675,6 +49706,7 @@
method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
method public abstract void setInputType(int);
method public abstract void setLongClickable(boolean);
+ method public abstract void setOpaque(boolean);
method public abstract void setSanitized(boolean);
method public abstract void setSelected(boolean);
method public abstract void setText(java.lang.CharSequence);
@@ -50395,6 +50427,8 @@
field public static final java.lang.String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
field public static final java.lang.String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT = "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
+ field public static final java.lang.String ACTION_ARGUMENT_MOVE_WINDOW_X = "android.view.accessibility.action.ARGUMENT_MOVE_WINDOW_X";
+ field public static final java.lang.String ACTION_ARGUMENT_MOVE_WINDOW_Y = "android.view.accessibility.action.ARGUMENT_MOVE_WINDOW_Y";
field public static final java.lang.String ACTION_ARGUMENT_PROGRESS_VALUE = "android.view.accessibility.action.ARGUMENT_PROGRESS_VALUE";
field public static final java.lang.String ACTION_ARGUMENT_ROW_INT = "android.view.accessibility.action.ARGUMENT_ROW_INT";
field public static final java.lang.String ACTION_ARGUMENT_SELECTION_END_INT = "ACTION_ARGUMENT_SELECTION_END_INT";
@@ -50451,6 +50485,7 @@
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_EXPAND;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_FOCUS;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_LONG_CLICK;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_MOVE_WINDOW;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_NEXT_AT_MOVEMENT_GRANULARITY;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_NEXT_HTML_ELEMENT;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PASTE;
@@ -50575,6 +50610,7 @@
method public android.view.accessibility.AccessibilityNodeInfo getRoot();
method public java.lang.CharSequence getTitle();
method public int getType();
+ method public boolean inPictureInPicture();
method public boolean isAccessibilityFocused();
method public boolean isActive();
method public boolean isFocused();
@@ -50910,60 +50946,46 @@
package android.view.autofill {
- public final class AutoFillId implements android.os.Parcelable {
+ public final class AutofillId implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.view.autofill.AutoFillId> CREATOR;
+ field public static final android.os.Parcelable.Creator<android.view.autofill.AutofillId> CREATOR;
}
- public final class AutoFillManager {
- method public void registerCallback(android.view.autofill.AutoFillManager.AutofillCallback);
+ public final class AutofillManager {
+ method public void registerCallback(android.view.autofill.AutofillManager.AutofillCallback);
method public void reset();
- method public void startAutoFillRequest(android.view.View);
- method public void startAutoFillRequestOnVirtualView(android.view.View, int, android.graphics.Rect);
- method public void stopAutoFillRequest(android.view.View);
- method public void stopAutoFillRequestOnVirtualView(android.view.View, int);
- method public void unregisterCallback(android.view.autofill.AutoFillManager.AutofillCallback);
+ method public void startAutofillRequest(android.view.View);
+ method public void startAutofillRequestOnVirtualView(android.view.View, int, android.graphics.Rect);
+ method public void stopAutofillRequest(android.view.View);
+ method public void stopAutofillRequestOnVirtualView(android.view.View, int);
+ method public void unregisterCallback(android.view.autofill.AutofillManager.AutofillCallback);
method public void valueChanged(android.view.View);
- method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue);
+ method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutofillValue);
field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
}
- public static abstract class AutoFillManager.AutofillCallback {
- ctor public AutoFillManager.AutofillCallback();
+ public static abstract class AutofillManager.AutofillCallback {
+ ctor public AutofillManager.AutofillCallback();
method public void onAutofillEvent(android.view.View, int);
method public void onAutofillEventVirtual(android.view.View, int, int);
field public static final int EVENT_INPUT_HIDDEN = 2; // 0x2
field public static final int EVENT_INPUT_SHOWN = 1; // 0x1
}
- public final class AutoFillType implements android.os.Parcelable {
+ public final class AutofillValue implements android.os.Parcelable {
method public int describeContents();
- method public static android.view.autofill.AutoFillType forDate();
- method public static android.view.autofill.AutoFillType forList();
- method public static android.view.autofill.AutoFillType forText();
- method public static android.view.autofill.AutoFillType forToggle();
- method public boolean isDate();
- method public boolean isList();
- method public boolean isText();
- method public boolean isToggle();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.view.autofill.AutoFillType> CREATOR;
- }
-
- public final class AutoFillValue implements android.os.Parcelable {
- method public int describeContents();
- method public static android.view.autofill.AutoFillValue forDate(long);
- method public static android.view.autofill.AutoFillValue forList(int);
- method public static android.view.autofill.AutoFillValue forText(java.lang.CharSequence);
- method public static android.view.autofill.AutoFillValue forToggle(boolean);
+ method public static android.view.autofill.AutofillValue forDate(long);
+ method public static android.view.autofill.AutofillValue forList(int);
+ method public static android.view.autofill.AutofillValue forText(java.lang.CharSequence);
+ method public static android.view.autofill.AutofillValue forToggle(boolean);
method public long getDateValue();
method public int getListValue();
method public java.lang.CharSequence getTextValue();
method public boolean getToggleValue();
method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.view.autofill.AutoFillValue> CREATOR;
+ field public static final android.os.Parcelable.Creator<android.view.autofill.AutofillValue> CREATOR;
}
}
@@ -52573,7 +52595,7 @@
method public abstract boolean onKeyUp(int, android.view.KeyEvent);
method public abstract void onMeasure(int, int);
method public abstract void onOverScrolled(int, int, boolean, boolean);
- method public default void onProvideAutoFillVirtualStructure(android.view.ViewStructure, int);
+ method public default void onProvideAutofillVirtualStructure(android.view.ViewStructure, int);
method public abstract void onProvideVirtualStructure(android.view.ViewStructure);
method public abstract void onScrollChanged(int, int, int, int);
method public abstract void onSizeChanged(int, int, int, int);
diff --git a/api/test-current.txt b/api/test-current.txt
index 51ff912..80b6379 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -20,6 +20,7 @@
field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
+ field public static final java.lang.String BIND_AUTOFILL = "android.permission.BIND_AUTOFILL";
field public static final java.lang.String BIND_AUTO_FILL = "android.permission.BIND_AUTO_FILL";
field public static final deprecated java.lang.String BIND_CARRIER_MESSAGING_SERVICE = "android.permission.BIND_CARRIER_MESSAGING_SERVICE";
field public static final java.lang.String BIND_CARRIER_SERVICES = "android.permission.BIND_CARRIER_SERVICES";
@@ -298,8 +299,6 @@
field public static final int authorities = 16842776; // 0x1010018
field public static final int autoAdvanceViewId = 16843535; // 0x101030f
field public static final int autoCompleteTextViewStyle = 16842859; // 0x101006b
- field public static final int autoFillHint = 16844121; // 0x1010559
- field public static final int autoFillMode = 16844116; // 0x1010554
field public static final int autoLink = 16842928; // 0x10100b0
field public static final int autoMirrored = 16843754; // 0x10103ea
field public static final int autoRemoveFromRecents = 16843847; // 0x1010447
@@ -312,6 +311,8 @@
field public static final deprecated int autoText = 16843114; // 0x101016a
field public static final int autoUrlDetect = 16843404; // 0x101028c
field public static final int autoVerify = 16844014; // 0x10104ee
+ field public static final int autofillHint = 16844121; // 0x1010559
+ field public static final int autofillMode = 16844116; // 0x1010554
field public static final int background = 16842964; // 0x10100d4
field public static final int backgroundDimAmount = 16842802; // 0x1010032
field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -1778,6 +1779,7 @@
public static final class R.id {
ctor public R.id();
field public static final int accessibilityActionContextClick = 16908348; // 0x102003c
+ field public static final int accessibilityActionMoveWindow = 16908354; // 0x1020042
field public static final int accessibilityActionScrollDown = 16908346; // 0x102003a
field public static final int accessibilityActionScrollLeft = 16908345; // 0x1020039
field public static final int accessibilityActionScrollRight = 16908347; // 0x102003b
@@ -6578,9 +6580,12 @@
public class AssistStructure implements android.os.Parcelable {
ctor public AssistStructure();
method public int describeContents();
+ method public long getAcquisitionEndTime();
+ method public long getAcquisitionStartTime();
method public android.content.ComponentName getActivityComponent();
method public android.app.assist.AssistStructure.WindowNode getWindowNodeAt(int);
method public int getWindowNodeCount();
+ method public boolean isHomeActivity();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.assist.AssistStructure> CREATOR;
}
@@ -6588,11 +6593,10 @@
public static class AssistStructure.ViewNode {
method public float getAlpha();
method public int getAutoFillHint();
- method public android.view.autofill.AutoFillId getAutoFillId();
- method public java.lang.String[] getAutoFillOptions();
- method public deprecated android.view.autofill.AutoFillType getAutoFillType();
- method public android.view.autofill.AutoFillValue getAutoFillValue();
+ method public android.view.autofill.AutofillId getAutofillId();
+ method public java.lang.String[] getAutofillOptions();
method public int getAutofillType();
+ method public android.view.autofill.AutofillValue getAutofillValue();
method public android.app.assist.AssistStructure.ViewNode getChildAt(int);
method public int getChildCount();
method public java.lang.String getClassName();
@@ -6634,6 +6638,7 @@
method public boolean isFocusable();
method public boolean isFocused();
method public boolean isLongClickable();
+ method public boolean isOpaque();
method public boolean isSelected();
field public static final int TEXT_COLOR_UNDEFINED = 1; // 0x1
field public static final int TEXT_STYLE_BOLD = 1; // 0x1
@@ -8013,7 +8018,7 @@
public static final class AdvertisingSetParameters.Builder {
ctor public AdvertisingSetParameters.Builder();
method public android.bluetooth.le.AdvertisingSetParameters build();
- method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymouus(boolean);
+ method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymous(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setConnectable(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setIncludeTxPower(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setInterval(int);
@@ -8210,18 +8215,17 @@
package android.companion {
- public final class AssociationRequest<F extends android.companion.DeviceFilter> implements android.os.Parcelable {
+ public final class AssociationRequest implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.companion.AssociationRequest> CREATOR;
}
- public static final class AssociationRequest.Builder<F extends android.companion.DeviceFilter> {
- method public android.companion.AssociationRequest<F> build();
- method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothDeviceFilter> createForBluetoothDevice();
- method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothLEDeviceFilter> createForBluetoothLEDevice();
- method public android.companion.AssociationRequest.Builder<F> setDeviceFilter(F);
- method public android.companion.AssociationRequest.Builder<F> setSingleDevice(boolean);
+ public static final class AssociationRequest.Builder {
+ ctor public AssociationRequest.Builder();
+ method public android.companion.AssociationRequest.Builder addDeviceFilter(android.companion.DeviceFilter<?>);
+ method public android.companion.AssociationRequest build();
+ method public android.companion.AssociationRequest.Builder setSingleDevice(boolean);
}
public final class BluetoothDeviceFilter implements android.companion.DeviceFilter {
@@ -8240,6 +8244,7 @@
public final class BluetoothLEDeviceFilter implements android.companion.DeviceFilter {
method public int describeContents();
+ method public static int getRenamePrefixLengthLimit();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.companion.BluetoothLEDeviceFilter> CREATOR;
}
@@ -8248,11 +8253,13 @@
ctor public BluetoothLEDeviceFilter.Builder();
method public android.companion.BluetoothLEDeviceFilter build();
method public android.companion.BluetoothLEDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+ method public android.companion.BluetoothLEDeviceFilter.Builder setRawDataFilter(byte[], byte[]);
+ method public android.companion.BluetoothLEDeviceFilter.Builder setRename(java.lang.String, java.lang.String, int, int, boolean);
method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter);
}
public final class CompanionDeviceManager {
- method public void associate(android.companion.AssociationRequest<?>, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
+ method public void associate(android.companion.AssociationRequest, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
method public void disassociate(java.lang.String);
method public java.util.List<java.lang.String> getAssociations();
field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
@@ -8267,6 +8274,18 @@
public abstract interface DeviceFilter<D extends android.os.Parcelable> implements android.os.Parcelable {
}
+ public final class WifiDeviceFilter implements android.companion.DeviceFilter {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.companion.WifiDeviceFilter> CREATOR;
+ }
+
+ public static final class WifiDeviceFilter.Builder {
+ ctor public WifiDeviceFilter.Builder();
+ method public android.companion.WifiDeviceFilter build();
+ method public android.companion.WifiDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+ }
+
}
package android.content {
@@ -12542,6 +12561,7 @@
public class BitmapShader extends android.graphics.Shader {
ctor public BitmapShader(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
+ method public void set(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
}
public class BlurMaskFilter extends android.graphics.MaskFilter {
@@ -12943,6 +12963,8 @@
public class ComposeShader extends android.graphics.Shader {
ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
+ method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
+ method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
}
public class CornerPathEffect extends android.graphics.PathEffect {
@@ -13018,6 +13040,8 @@
public class LinearGradient extends android.graphics.Shader {
ctor public LinearGradient(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
ctor public LinearGradient(float, float, float, float, int, int, android.graphics.Shader.TileMode);
+ method public void set(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
+ method public void set(float, float, float, float, int, int, android.graphics.Shader.TileMode);
}
public class MaskFilter {
@@ -13536,6 +13560,8 @@
public class RadialGradient extends android.graphics.Shader {
ctor public RadialGradient(float, float, float, int[], float[], android.graphics.Shader.TileMode);
ctor public RadialGradient(float, float, float, int, int, android.graphics.Shader.TileMode);
+ method public void set(float, float, float, int[], float[], android.graphics.Shader.TileMode);
+ method public void set(float, float, float, int, int, android.graphics.Shader.TileMode);
}
public final class Rect implements android.os.Parcelable {
@@ -13675,7 +13701,7 @@
}
public class Shader {
- ctor public Shader();
+ ctor public deprecated Shader();
method public boolean getLocalMatrix(android.graphics.Matrix);
method public void setLocalMatrix(android.graphics.Matrix);
}
@@ -13720,6 +13746,8 @@
public class SweepGradient extends android.graphics.Shader {
ctor public SweepGradient(float, float, int[], float[]);
ctor public SweepGradient(float, float, int, int);
+ method public void set(float, float, int[], float[]);
+ method public void set(float, float, int, int);
}
public class Typeface {
@@ -13747,9 +13775,12 @@
public static abstract interface Typeface.FontRequestCallback {
method public abstract void onTypefaceRequestFailed(int);
method public abstract void onTypefaceRetrieved(android.graphics.Typeface);
- field public static final int FAIL_REASON_FONT_LOAD_ERROR = 1; // 0x1
- field public static final int FAIL_REASON_FONT_NOT_FOUND = 2; // 0x2
- field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = 0; // 0x0
+ field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
+ field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
+ field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
+ field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
+ field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
+ field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
}
public class Xfermode {
@@ -21087,7 +21118,7 @@
}
public class AudioManager {
- method public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener);
+ method public deprecated int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener);
method public int abandonAudioFocusRequest(android.media.AudioFocusRequest);
method public void adjustStreamVolume(int, int, int);
method public void adjustSuggestedStreamVolume(int, int, int);
@@ -21124,7 +21155,7 @@
method public deprecated void registerMediaButtonEventReceiver(android.app.PendingIntent);
method public deprecated void registerRemoteControlClient(android.media.RemoteControlClient);
method public deprecated boolean registerRemoteController(android.media.RemoteController);
- method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int);
+ method public deprecated int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int);
method public int requestAudioFocus(android.media.AudioFocusRequest);
method public deprecated void setBluetoothA2dpOn(boolean);
method public void setBluetoothScoOn(boolean);
@@ -26580,7 +26611,8 @@
}
public class DiscoverySession {
- method public java.lang.String createNetworkSpecifier(android.net.wifi.aware.PeerHandle, byte[]);
+ method public java.lang.String createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
+ method public java.lang.String createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
method public void destroy();
method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
}
@@ -26668,7 +26700,8 @@
}
public class WifiAwareSession {
- method public java.lang.String createNetworkSpecifier(int, byte[], byte[]);
+ method public java.lang.String createNetworkSpecifierOpen(int, byte[]);
+ method public java.lang.String createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
method public void destroy();
method public void publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
method public void subscribe(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
@@ -34217,7 +34250,7 @@
method public static android.net.Uri createDocument(android.content.ContentResolver, android.net.Uri, java.lang.String, java.lang.String);
method public static android.content.IntentSender createWebLinkIntent(android.content.ContentResolver, android.net.Uri, android.os.Bundle);
method public static boolean deleteDocument(android.content.ContentResolver, android.net.Uri);
- method public static java.util.List<java.lang.String> findDocumentPath(android.content.ContentResolver, android.net.Uri);
+ method public static android.provider.DocumentsContract.Path findDocumentPath(android.content.ContentResolver, android.net.Uri);
method public static java.lang.String getDocumentId(android.net.Uri);
method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal);
method public static java.lang.String getRootId(android.net.Uri);
@@ -34333,6 +34366,11 @@
public static final class FontsContract.Columns implements android.provider.BaseColumns {
ctor public FontsContract.Columns();
+ field public static final java.lang.String RESULT_CODE = "result_code";
+ field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
+ field public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; // 0x2
+ field public static final int RESULT_CODE_MALFORMED_QUERY = 3; // 0x3
+ field public static final int RESULT_CODE_OK = 0; // 0x0
field public static final java.lang.String STYLE = "font_style";
field public static final java.lang.String TTC_INDEX = "font_ttc_index";
field public static final java.lang.String VARIATION_SETTINGS = "font_variation_settings";
@@ -34860,7 +34898,7 @@
field public static final java.lang.String ALLOWED_GEOLOCATION_ORIGINS = "allowed_geolocation_origins";
field public static final deprecated java.lang.String ALLOW_MOCK_LOCATION = "mock_location";
field public static final java.lang.String ANDROID_ID = "android_id";
- field public static final java.lang.String AUTO_FILL_SERVICE = "auto_fill_service";
+ field public static final java.lang.String AUTOFILL_SERVICE = "autofill_service";
field public static final deprecated java.lang.String BACKGROUND_DATA = "background_data";
field public static final deprecated java.lang.String BLUETOOTH_ON = "bluetooth_on";
field public static final android.net.Uri CONTENT_URI;
@@ -36832,15 +36870,15 @@
package android.service.autofill {
- public abstract class AutoFillService extends android.app.Service {
- ctor public AutoFillService();
+ public abstract class AutofillService extends android.app.Service {
+ ctor public AutofillService();
method public final void disableSelf();
method public final android.os.IBinder onBind(android.content.Intent);
method public void onConnected();
method public void onDisconnected();
method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback);
method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
- field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
+ field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillService";
field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
}
@@ -36854,7 +36892,7 @@
ctor public Dataset.Builder(android.widget.RemoteViews);
method public android.service.autofill.Dataset build();
method public android.service.autofill.Dataset.Builder setAuthentication(android.content.IntentSender);
- method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutoFillId, android.view.autofill.AutoFillValue);
+ method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue);
}
public final class FillCallback {
@@ -36894,7 +36932,7 @@
public static final class SaveInfo.Builder {
ctor public SaveInfo.Builder(int);
- method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
+ method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutofillId...);
method public android.service.autofill.SaveInfo build();
method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
method public android.service.autofill.SaveInfo.Builder setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
@@ -39977,7 +40015,7 @@
method public int getSimState();
method public int getSimState(int);
method public java.lang.String getSubscriberId();
- method public java.lang.String getVisualVoicemailPackageName(android.telecom.PhoneAccountHandle);
+ method public java.lang.String getVisualVoicemailPackageName();
method public java.lang.String getVoiceMailAlphaTag();
method public java.lang.String getVoiceMailNumber();
method public int getVoiceNetworkType();
@@ -40117,9 +40155,6 @@
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.telephony.VisualVoicemailSmsFilterSettings> CREATOR;
- field public static final java.lang.String DEFAULT_CLIENT_PREFIX = "//VVM";
- field public static final int DEFAULT_DESTINATION_PORT = -1; // 0xffffffff
- field public static final java.util.List<java.lang.String> DEFAULT_ORIGINATING_NUMBERS;
field public static final int DESTINATION_PORT_ANY = -1; // 0xffffffff
field public static final int DESTINATION_PORT_DATA_SMS = -2; // 0xfffffffe
field public final java.lang.String clientPrefix;
@@ -45321,8 +45356,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 void autofill(android.view.autofill.AutofillValue);
+ method public void autofillVirtual(int, android.view.autofill.AutofillValue);
method protected boolean awakenScrollBars();
method protected boolean awakenScrollBars(int);
method protected boolean awakenScrollBars(int, boolean);
@@ -45376,7 +45411,7 @@
method public boolean dispatchNestedScroll(int, int, int, int, int[]);
method public void dispatchPointerCaptureChanged(boolean);
method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
- method public void dispatchProvideAutoFillStructure(android.view.ViewStructure, int);
+ method public void dispatchProvideAutofillStructure(android.view.ViewStructure, int);
method public void dispatchProvideStructure(android.view.ViewStructure);
method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>);
method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>);
@@ -45412,11 +45447,10 @@
method public float getAlpha();
method public android.view.animation.Animation getAnimation();
method public android.os.IBinder getApplicationWindowToken();
- method public int getAutoFillHint();
- method public int getAutoFillMode();
- method public final deprecated android.view.autofill.AutoFillType getAutoFillType();
- method public android.view.autofill.AutoFillValue getAutoFillValue();
+ method public int getAutofillHint();
+ method public int getAutofillMode();
method public int getAutofillType();
+ method public android.view.autofill.AutofillValue getAutofillValue();
method public android.graphics.drawable.Drawable getBackground();
method public android.content.res.ColorStateList getBackgroundTintList();
method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -45502,7 +45536,7 @@
method public float getPivotX();
method public float getPivotY();
method public android.view.PointerIcon getPointerIcon();
- method public int getResolvedAutoFillMode();
+ method public int getResolvedAutofillMode();
method public android.content.res.Resources getResources();
method public final boolean getRevealOnFocusHint();
method public final int getRight();
@@ -45662,8 +45696,8 @@
method protected void onOverScrolled(int, int, boolean, boolean);
method public void onPointerCaptureChange(boolean);
method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
- method public void onProvideAutoFillStructure(android.view.ViewStructure, int);
- method public void onProvideAutoFillVirtualStructure(android.view.ViewStructure, int);
+ method public void onProvideAutofillStructure(android.view.ViewStructure, int);
+ method public void onProvideAutofillVirtualStructure(android.view.ViewStructure, int);
method public void onProvideStructure(android.view.ViewStructure);
method public void onProvideVirtualStructure(android.view.ViewStructure);
method public android.view.PointerIcon onResolvePointerIcon(android.view.MotionEvent, int);
@@ -45737,8 +45771,8 @@
method public void setActivated(boolean);
method public void setAlpha(float);
method public void setAnimation(android.view.animation.Animation);
- method public void setAutoFillHint(int);
- method public void setAutoFillMode(int);
+ method public void setAutofillHint(int);
+ method public void setAutofillMode(int);
method public void setBackground(android.graphics.drawable.Drawable);
method public void setBackgroundColor(int);
method public deprecated void setBackgroundDrawable(android.graphics.drawable.Drawable);
@@ -45880,28 +45914,28 @@
field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
+ field public static final int AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE = 512; // 0x200
+ field public static final int AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = 4096; // 0x1000
+ field public static final int AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = 1024; // 0x400
+ field public static final int AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR = 2048; // 0x800
+ field public static final int AUTOFILL_HINT_CREDIT_CARD_NUMBER = 128; // 0x80
+ field public static final int AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = 256; // 0x100
+ field public static final int AUTOFILL_HINT_EMAIL_ADDRESS = 1; // 0x1
+ field public static final int AUTOFILL_HINT_NAME = 2; // 0x2
+ field public static final int AUTOFILL_HINT_NONE = 0; // 0x0
+ field public static final int AUTOFILL_HINT_PASSWORD = 8; // 0x8
+ field public static final int AUTOFILL_HINT_PHONE = 16; // 0x10
+ field public static final int AUTOFILL_HINT_POSTAL_ADDRESS = 32; // 0x20
+ field public static final int AUTOFILL_HINT_POSTAL_CODE = 64; // 0x40
+ field public static final int AUTOFILL_HINT_USERNAME = 4; // 0x4
+ field public static final int AUTOFILL_MODE_AUTO = 1; // 0x1
+ field public static final int AUTOFILL_MODE_INHERIT = 0; // 0x0
+ field public static final int AUTOFILL_MODE_MANUAL = 2; // 0x2
field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
field public static final int AUTOFILL_TYPE_TEXT = 1; // 0x1
field public static final int AUTOFILL_TYPE_TOGGLE = 2; // 0x2
- field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DATE = 512; // 0x200
- field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DAY = 4096; // 0x1000
- field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = 1024; // 0x400
- field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_YEAR = 2048; // 0x800
- field public static final int AUTO_FILL_HINT_CREDIT_CARD_NUMBER = 128; // 0x80
- field public static final int AUTO_FILL_HINT_CREDIT_CARD_SECURITY_CODE = 256; // 0x100
- field public static final int AUTO_FILL_HINT_EMAIL_ADDRESS = 1; // 0x1
- field public static final int AUTO_FILL_HINT_NAME = 2; // 0x2
- field public static final int AUTO_FILL_HINT_NONE = 0; // 0x0
- field public static final int AUTO_FILL_HINT_PASSWORD = 8; // 0x8
- field public static final int AUTO_FILL_HINT_PHONE = 16; // 0x10
- field public static final int AUTO_FILL_HINT_POSTAL_ADDRESS = 32; // 0x20
- field public static final int AUTO_FILL_HINT_POSTAL_CODE = 64; // 0x40
- field public static final int AUTO_FILL_HINT_USERNAME = 4; // 0x4
- field public static final int AUTO_FILL_MODE_AUTO = 1; // 0x1
- field public static final int AUTO_FILL_MODE_INHERIT = 0; // 0x0
- field public static final int AUTO_FILL_MODE_MANUAL = 2; // 0x2
field public static final int DRAG_FLAG_GLOBAL = 256; // 0x100
field public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION = 64; // 0x40
field public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION = 128; // 0x80
@@ -46467,7 +46501,7 @@
method public abstract int getLayoutDirection();
method public abstract android.view.ViewParent getParent();
method public abstract android.view.ViewParent getParentForAccessibility();
- method public default int getResolvedAutoFillMode();
+ method public default int getResolvedAutofillMode();
method public abstract int getTextAlignment();
method public abstract int getTextDirection();
method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect);
@@ -46546,7 +46580,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 asyncNewChildForAutofill(int, int, int);
method public abstract int getChildCount();
method public abstract android.os.Bundle getExtras();
method public abstract java.lang.CharSequence getHint();
@@ -46555,15 +46589,14 @@
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 newChildForAutofill(int, int, int);
method public abstract void setAccessibilityFocused(boolean);
method public abstract void setActivated(boolean);
method public abstract void setAlpha(float);
- method public abstract void setAutoFillHint(int);
- method public abstract void setAutoFillOptions(java.lang.String[]);
- method public abstract deprecated void setAutoFillType(android.view.autofill.AutoFillType);
- method public abstract void setAutoFillValue(android.view.autofill.AutoFillValue);
+ method public abstract void setAutofillHint(int);
+ method public abstract void setAutofillOptions(java.lang.String[]);
method public abstract void setAutofillType(int);
+ method public abstract void setAutofillValue(android.view.autofill.AutofillValue);
method public abstract void setCheckable(boolean);
method public abstract void setChecked(boolean);
method public abstract void setChildCount(int);
@@ -46580,6 +46613,7 @@
method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
method public abstract void setInputType(int);
method public abstract void setLongClickable(boolean);
+ method public abstract void setOpaque(boolean);
method public abstract void setSanitized(boolean);
method public abstract void setSelected(boolean);
method public abstract void setText(java.lang.CharSequence);
@@ -47298,6 +47332,8 @@
field public static final java.lang.String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
field public static final java.lang.String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT = "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
+ field public static final java.lang.String ACTION_ARGUMENT_MOVE_WINDOW_X = "android.view.accessibility.action.ARGUMENT_MOVE_WINDOW_X";
+ field public static final java.lang.String ACTION_ARGUMENT_MOVE_WINDOW_Y = "android.view.accessibility.action.ARGUMENT_MOVE_WINDOW_Y";
field public static final java.lang.String ACTION_ARGUMENT_PROGRESS_VALUE = "android.view.accessibility.action.ARGUMENT_PROGRESS_VALUE";
field public static final java.lang.String ACTION_ARGUMENT_ROW_INT = "android.view.accessibility.action.ARGUMENT_ROW_INT";
field public static final java.lang.String ACTION_ARGUMENT_SELECTION_END_INT = "ACTION_ARGUMENT_SELECTION_END_INT";
@@ -47354,6 +47390,7 @@
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_EXPAND;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_FOCUS;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_LONG_CLICK;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_MOVE_WINDOW;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_NEXT_AT_MOVEMENT_GRANULARITY;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_NEXT_HTML_ELEMENT;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PASTE;
@@ -47478,6 +47515,7 @@
method public android.view.accessibility.AccessibilityNodeInfo getRoot();
method public java.lang.CharSequence getTitle();
method public int getType();
+ method public boolean inPictureInPicture();
method public boolean isAccessibilityFocused();
method public boolean isActive();
method public boolean isFocused();
@@ -47814,60 +47852,46 @@
package android.view.autofill {
- public final class AutoFillId implements android.os.Parcelable {
+ public final class AutofillId implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.view.autofill.AutoFillId> CREATOR;
+ field public static final android.os.Parcelable.Creator<android.view.autofill.AutofillId> CREATOR;
}
- public final class AutoFillManager {
- method public void registerCallback(android.view.autofill.AutoFillManager.AutofillCallback);
+ public final class AutofillManager {
+ method public void registerCallback(android.view.autofill.AutofillManager.AutofillCallback);
method public void reset();
- method public void startAutoFillRequest(android.view.View);
- method public void startAutoFillRequestOnVirtualView(android.view.View, int, android.graphics.Rect);
- method public void stopAutoFillRequest(android.view.View);
- method public void stopAutoFillRequestOnVirtualView(android.view.View, int);
- method public void unregisterCallback(android.view.autofill.AutoFillManager.AutofillCallback);
+ method public void startAutofillRequest(android.view.View);
+ method public void startAutofillRequestOnVirtualView(android.view.View, int, android.graphics.Rect);
+ method public void stopAutofillRequest(android.view.View);
+ method public void stopAutofillRequestOnVirtualView(android.view.View, int);
+ method public void unregisterCallback(android.view.autofill.AutofillManager.AutofillCallback);
method public void valueChanged(android.view.View);
- method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue);
+ method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutofillValue);
field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
}
- public static abstract class AutoFillManager.AutofillCallback {
- ctor public AutoFillManager.AutofillCallback();
+ public static abstract class AutofillManager.AutofillCallback {
+ ctor public AutofillManager.AutofillCallback();
method public void onAutofillEvent(android.view.View, int);
method public void onAutofillEventVirtual(android.view.View, int, int);
field public static final int EVENT_INPUT_HIDDEN = 2; // 0x2
field public static final int EVENT_INPUT_SHOWN = 1; // 0x1
}
- public final class AutoFillType implements android.os.Parcelable {
+ public final class AutofillValue implements android.os.Parcelable {
method public int describeContents();
- method public static android.view.autofill.AutoFillType forDate();
- method public static android.view.autofill.AutoFillType forList();
- method public static android.view.autofill.AutoFillType forText();
- method public static android.view.autofill.AutoFillType forToggle();
- method public boolean isDate();
- method public boolean isList();
- method public boolean isText();
- method public boolean isToggle();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.view.autofill.AutoFillType> CREATOR;
- }
-
- public final class AutoFillValue implements android.os.Parcelable {
- method public int describeContents();
- method public static android.view.autofill.AutoFillValue forDate(long);
- method public static android.view.autofill.AutoFillValue forList(int);
- method public static android.view.autofill.AutoFillValue forText(java.lang.CharSequence);
- method public static android.view.autofill.AutoFillValue forToggle(boolean);
+ method public static android.view.autofill.AutofillValue forDate(long);
+ method public static android.view.autofill.AutofillValue forList(int);
+ method public static android.view.autofill.AutofillValue forText(java.lang.CharSequence);
+ method public static android.view.autofill.AutofillValue forToggle(boolean);
method public long getDateValue();
method public int getListValue();
method public java.lang.CharSequence getTextValue();
method public boolean getToggleValue();
method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.view.autofill.AutoFillValue> CREATOR;
+ field public static final android.os.Parcelable.Creator<android.view.autofill.AutofillValue> CREATOR;
}
}
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index b4e119e..64d7d4c 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -1438,7 +1438,7 @@
*/
public AccessibilityNodeInfo findFocus(int focus) {
return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId,
- AccessibilityNodeInfo.ANY_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID, focus);
+ AccessibilityWindowInfo.ANY_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID, focus);
}
/**
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 0193c5f..1969f8b 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -16,9 +16,9 @@
package android.app;
-import android.view.autofill.AutoFillId;
-import android.view.autofill.AutoFillManager;
-import android.view.autofill.AutoFillValue;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillManager;
+import android.view.autofill.AutofillValue;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.app.ToolbarActionBar;
@@ -690,7 +690,7 @@
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks2,
Window.OnWindowDismissedCallback, WindowControllerCallback,
- AutoFillManager.AutoFillClient {
+ AutofillManager.AutofillClient {
private static final String TAG = "Activity";
private static final boolean DEBUG_LIFECYCLE = false;
@@ -1783,7 +1783,7 @@
mTranslucentCallback = null;
mCalled = true;
if (isFinishing() && mAutoFillResetNeeded) {
- getSystemService(AutoFillManager.class).reset();
+ getSystemService(AutofillManager.class).reset();
}
}
@@ -7042,7 +7042,7 @@
}
} else if (who.startsWith(AUTO_FILL_AUTH_WHO_PREFIX)) {
Intent resultData = (resultCode == Activity.RESULT_OK) ? data : null;
- getSystemService(AutoFillManager.class).onAuthenticationResult(resultData);
+ getSystemService(AutofillManager.class).onAuthenticationResult(resultData);
} else {
Fragment frag = mFragments.findFragmentByWho(who);
if (frag != null) {
@@ -7185,22 +7185,22 @@
/** @hide */
@Override
- public void autoFill(List<AutoFillId> ids, List<AutoFillValue> values) {
+ public void autofill(List<AutofillId> ids, List<AutofillValue> values) {
final View root = getWindow().getDecorView();
final int itemCount = ids.size();
for (int i = 0; i < itemCount; i++) {
- final AutoFillId id = ids.get(i);
- final AutoFillValue value = values.get(i);
+ final AutofillId id = ids.get(i);
+ final AutofillValue value = values.get(i);
final int viewId = id.getViewId();
final View view = root.findViewByAccessibilityIdTraversal(viewId);
if (view == null) {
- Log.w(TAG, "autoFill(): no View with id " + viewId);
+ Log.w(TAG, "autofill(): no View with id " + viewId);
continue;
}
if (id.isVirtual()) {
- view.autoFillVirtual(id.getVirtualChildId(), value);
+ view.autofillVirtual(id.getVirtualChildId(), value);
} else {
- view.autoFill(value);
+ view.autofill(value);
}
}
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index cae37c6..043e0ab 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -133,7 +133,7 @@
public final static boolean ENABLE_TASK_SNAPSHOTS;
static {
- ENABLE_TASK_SNAPSHOTS = SystemProperties.getBoolean("persist.enable_task_snapshots", false);
+ ENABLE_TASK_SNAPSHOTS = SystemProperties.getBoolean("persist.enable_task_snapshots", true);
}
static final class UidObserver extends IUidObserver.Stub {
@@ -144,7 +144,7 @@
}
@Override
- public void onUidStateChanged(int uid, int procState) {
+ public void onUidStateChanged(int uid, int procState, long procStateSeq) {
mListener.onUidImportance(uid, RunningAppProcessInfo.procStateToImportance(procState));
}
@@ -502,8 +502,8 @@
/** @hide requestType for assist context: generate full AssistStructure. */
public static final int ASSIST_CONTEXT_FULL = 1;
- /** @hide requestType for assist context: generate full AssistStructure for auto-fill. */
- public static final int ASSIST_CONTEXT_AUTO_FILL = 2;
+ /** @hide requestType for assist context: generate full AssistStructure for autofill. */
+ public static final int ASSIST_CONTEXT_AUTOFILL = 2;
/** @hide Flag for registerUidObserver: report changes in process state. */
public static final int UID_OBSERVER_PROCSTATE = 1<<0;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index ce9d91f..44cc5b4 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2913,13 +2913,13 @@
}
public void handleRequestAssistContextExtras(RequestAssistContextExtras cmd) {
- // Filling for auto-fill has a few differences:
+ // Filling for autofill has a few differences:
// - it does not need an AssistContent
// - it does not call onProvideAssistData()
// - it needs an IAutoFillCallback
- boolean forAutoFill = cmd.requestType == ActivityManager.ASSIST_CONTEXT_AUTO_FILL;
+ boolean forAutofill = cmd.requestType == ActivityManager.ASSIST_CONTEXT_AUTOFILL;
- // TODO(b/33197203): decide if lastSessionId logic applies to auto-fill sessions
+ // TODO(b/33197203): decide if lastSessionId logic applies to autofill sessions
if (mLastSessionId != cmd.sessionId) {
// Clear the existing structures
mLastSessionId = cmd.sessionId;
@@ -2934,25 +2934,26 @@
Bundle data = new Bundle();
AssistStructure structure = null;
- AssistContent content = forAutoFill ? null : new AssistContent();
+ AssistContent content = forAutofill ? null : new AssistContent();
+ final long startTime = SystemClock.uptimeMillis();
ActivityClientRecord r = mActivities.get(cmd.activityToken);
Uri referrer = null;
if (r != null) {
- if (!forAutoFill) {
+ if (!forAutofill) {
r.activity.getApplication().dispatchOnProvideAssistData(r.activity, data);
r.activity.onProvideAssistData(data);
referrer = r.activity.onProvideReferrer();
}
- if (cmd.requestType == ActivityManager.ASSIST_CONTEXT_FULL || forAutoFill) {
- structure = new AssistStructure(r.activity, forAutoFill);
+ if (cmd.requestType == ActivityManager.ASSIST_CONTEXT_FULL || forAutofill) {
+ structure = new AssistStructure(r.activity, forAutofill);
Intent activityIntent = r.activity.getIntent();
- // TODO(b/33197203): re-evaluate conditions below for auto-fill. In particular,
+ // TODO(b/33197203): re-evaluate conditions below for autofill. In particular,
// FLAG_SECURE might be allowed on AUTO_FILL but not on AUTO_FILL_SAVE)
boolean notSecure = r.window == null ||
(r.window.getAttributes().flags
& WindowManager.LayoutParams.FLAG_SECURE) == 0;
if (activityIntent != null && notSecure) {
- if (!forAutoFill) {
+ if (!forAutofill) {
Intent intent = new Intent(activityIntent);
intent.setFlags(intent.getFlags() & ~(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION));
@@ -2960,11 +2961,11 @@
content.setDefaultIntent(intent);
}
} else {
- if (!forAutoFill) {
+ if (!forAutofill) {
content.setDefaultIntent(new Intent());
}
}
- if (!forAutoFill) {
+ if (!forAutofill) {
r.activity.onProvideAssistContent(content);
}
}
@@ -2973,7 +2974,11 @@
structure = new AssistStructure();
}
- // TODO(b/33197203): decide if lastSessionId logic applies to auto-fill sessions
+ // TODO(b/33197203): decide if lastSessionId logic applies to autofill sessions
+
+ structure.setAcquisitionStartTime(startTime);
+ structure.setAcquisitionEndTime(SystemClock.uptimeMillis());
+
mLastAssistStructures.add(new WeakReference<>(structure));
IActivityManager mgr = ActivityManager.getService();
try {
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 152d514..081dae2 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -588,7 +588,7 @@
boolean updateDisplayOverrideConfiguration(in Configuration values, int displayId);
void unregisterTaskStackListener(ITaskStackListener listener);
void moveStackToDisplay(int stackId, int displayId);
- boolean requestAutoFillData(in IResultReceiver receiver, in Bundle receiverExtras,
+ boolean requestAutofillData(in IResultReceiver receiver, in Bundle receiverExtras,
in IBinder activityToken);
void dismissKeyguard(in IBinder token, in IKeyguardDismissCallback callback);
int restartUserInBackground(int userId);
diff --git a/core/java/android/app/IUidObserver.aidl b/core/java/android/app/IUidObserver.aidl
index 64cb9b1..ae64875 100644
--- a/core/java/android/app/IUidObserver.aidl
+++ b/core/java/android/app/IUidObserver.aidl
@@ -20,8 +20,13 @@
oneway interface IUidObserver {
/**
* General report of a state change of an uid.
+ *
+ * @param uid The uid for which the state change is being reported.
+ * @param procState The updated process state for the uid.
+ * @param procStateSeq The sequence no. associated with process state change of the uid,
+ * see UidRecord.procStateSeq for details.
*/
- void onUidStateChanged(int uid, int procState);
+ void onUidStateChanged(int uid, int procState, long procStateSeq);
/**
* Report that there are no longer any processes running for a uid.
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index f330a4b..4ae0617 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -114,7 +114,7 @@
import android.os.storage.StorageManager;
import android.print.IPrintManager;
import android.print.PrintManager;
-import android.view.autofill.AutoFillManager;
+import android.view.autofill.AutofillManager;
import android.view.autofill.IAutoFillManager;
import android.service.persistentdata.IPersistentDataBlockService;
import android.service.persistentdata.PersistentDataBlockManager;
@@ -821,13 +821,13 @@
IBinder b = ServiceManager.getServiceOrThrow(Context.FONT_SERVICE);
return new FontManager(IFontManager.Stub.asInterface(b));
}});
- registerService(Context.AUTO_FILL_MANAGER_SERVICE, AutoFillManager.class,
- new CachedServiceFetcher<AutoFillManager>() {
+ registerService(Context.AUTOFILL_MANAGER_SERVICE, AutofillManager.class,
+ new CachedServiceFetcher<AutofillManager>() {
@Override
- public AutoFillManager createService(ContextImpl ctx) throws ServiceNotFoundException {
- IBinder b = ServiceManager.getServiceOrThrow(Context.AUTO_FILL_MANAGER_SERVICE);
+ public AutofillManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.AUTOFILL_MANAGER_SERVICE);
IAutoFillManager service = IAutoFillManager.Stub.asInterface(b);
- return new AutoFillManager(ctx.getOuterContext(), service);
+ return new AutofillManager(ctx.getOuterContext(), service);
}});
registerService(Context.VR_SERVICE, VrManager.class, new CachedServiceFetcher<VrManager>() {
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 1d6f42e..18e7599 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -381,7 +381,7 @@
*/
public AccessibilityNodeInfo findFocus(int focus) {
return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId,
- AccessibilityNodeInfo.ANY_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID, focus);
+ AccessibilityWindowInfo.ANY_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID, focus);
}
/**
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 2e0ca02..1f2ed00 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -24,6 +24,8 @@
import android.view.autofill.AutoFillId;
import android.view.autofill.AutoFillType;
import android.view.autofill.AutoFillValue;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
import java.util.ArrayList;
import java.util.Arrays;
@@ -45,6 +47,7 @@
boolean mHaveData;
ComponentName mActivityComponent;
+ private boolean mIsHomeActivity;
final ArrayList<WindowNode> mWindowNodes = new ArrayList<>();
@@ -56,10 +59,54 @@
Rect mTmpRect = new Rect();
boolean mSanitizeOnWrite = false;
+ private long mAcquisitionStartTime;
+ private long mAcquisitionEndTime;
static final int TRANSACTION_XFER = Binder.FIRST_CALL_TRANSACTION+1;
static final String DESCRIPTOR = "android.app.AssistStructure";
+ /** @hide */
+ public void setAcquisitionStartTime(long acquisitionStartTime) {
+ mAcquisitionStartTime = acquisitionStartTime;
+ }
+
+ /** @hide */
+ public void setAcquisitionEndTime(long acquisitionEndTime) {
+ mAcquisitionEndTime = acquisitionEndTime;
+ }
+
+ /**
+ * @hide
+ * Set the home activity flag.
+ */
+ public void setHomeActivity(boolean isHomeActivity) {
+ mIsHomeActivity = isHomeActivity;
+ }
+
+ /**
+ * Returns the time when the activity started generating assist data to build the
+ * AssistStructure. The time is as specified by {@link SystemClock#uptimeMillis()}.
+ *
+ * @see #getAcquisitionEndTime()
+ * @return Returns the acquisition start time of the assist data, in milliseconds.
+ */
+ public long getAcquisitionStartTime() {
+ ensureData();
+ return mAcquisitionStartTime;
+ }
+
+ /**
+ * Returns the time when the activity finished generating assist data to build the
+ * AssistStructure. The time is as specified by {@link SystemClock#uptimeMillis()}.
+ *
+ * @see #getAcquisitionStartTime()
+ * @return Returns the acquisition end time of the assist data, in milliseconds.
+ */
+ public long getAcquisitionEndTime() {
+ ensureData();
+ return mAcquisitionEndTime;
+ }
+
final static class SendChannel extends Binder {
volatile AssistStructure mAssistStructure;
@@ -123,6 +170,8 @@
mSanitizeOnWrite = as.mSanitizeOnWrite;
mWriteStructure = as.waitForReady();
ComponentName.writeToParcel(as.mActivityComponent, out);
+ out.writeLong(as.mAcquisitionStartTime);
+ out.writeLong(as.mAcquisitionEndTime);
mNumWindows = as.mWindowNodes.size();
if (mWriteStructure && mNumWindows > 0) {
out.writeInt(mNumWindows);
@@ -275,6 +324,8 @@
void go() {
fetchData();
mActivityComponent = ComponentName.readFromParcel(mCurParcel);
+ mAcquisitionStartTime = mCurParcel.readLong();
+ mAcquisitionEndTime = mCurParcel.readLong();
final int N = mCurParcel.readInt();
if (N > 0) {
if (DEBUG_PARCEL) Log.d(TAG, "Creating PooledStringReader @ "
@@ -424,7 +475,7 @@
if ((root.getWindowFlags() & WindowManager.LayoutParams.FLAG_SECURE) != 0) {
if (forAutoFill) {
// NOTE: flags are currently not supported, hence 0
- view.onProvideAutoFillStructure(builder, 0);
+ view.onProvideAutofillStructure(builder, 0);
} else {
// This is a secure window, so it doesn't want a screenshot, and that
// means we should also not copy out its view hierarchy for Assist
@@ -435,7 +486,7 @@
}
if (forAutoFill) {
// NOTE: flags are currently not supported, hence 0
- view.dispatchProvideAutoFillStructure(builder, 0);
+ view.dispatchProvideAutofillStructure(builder, 0);
} else {
view.dispatchProvideStructure(builder);
}
@@ -537,11 +588,11 @@
// TODO(b/33197203): once we have more flags, it might be better to store the individual
// fields (viewId and childId) of the field.
- AutoFillId mAutoFillId;
+ AutofillId mAutofillId;
@View.AutofillType int mAutofillType;
- @View.AutoFillHint int mAutoFillHint;
- AutoFillValue mAutoFillValue;
- String[] mAutoFillOptions;
+ @View.AutofillHint int mAutofillHint;
+ AutofillValue mAutofillValue;
+ String[] mAutofillOptions;
boolean mSanitized;
int mX;
@@ -567,12 +618,13 @@
static final int FLAGS_ACCESSIBILITY_FOCUSED = 0x00001000;
static final int FLAGS_ACTIVATED = 0x00002000;
static final int FLAGS_CONTEXT_CLICKABLE = 0x00004000;
+ static final int FLAGS_OPAQUE = 0x00008000;
- // TODO(b/33197203): auto-fill data is made of many fields and ideally we should verify
+ // TODO(b/33197203): autofill data is made of many fields and ideally we should verify
// one-by-one to optimize what's sent over, but there isn't enough flag bits for that, we'd
// need to create a 'flags2' or 'autoFillFlags' field and add these flags there.
// So, to keep thinkg simpler for now, let's just use on flag for all of them...
- static final int FLAGS_HAS_AUTO_FILL_DATA = 0x80000000;
+ static final int FLAGS_HAS_AUTOFILL_DATA = 0x80000000;
static final int FLAGS_HAS_MATRIX = 0x40000000;
static final int FLAGS_HAS_ALPHA = 0x20000000;
static final int FLAGS_HAS_ELEVATION = 0x10000000;
@@ -620,13 +672,13 @@
}
}
}
- if ((flags&FLAGS_HAS_AUTO_FILL_DATA) != 0) {
+ if ((flags&FLAGS_HAS_AUTOFILL_DATA) != 0) {
mSanitized = in.readInt() == 1;
- mAutoFillId = in.readParcelable(null);
+ mAutofillId = in.readParcelable(null);
mAutofillType = in.readInt();
- mAutoFillHint = in.readInt();
- mAutoFillValue = in.readParcelable(null);
- mAutoFillOptions = in.readStringArray();
+ mAutofillHint = in.readInt();
+ mAutofillValue = in.readParcelable(null);
+ mAutofillOptions = in.readStringArray();
}
if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
mX = in.readInt();
@@ -686,15 +738,15 @@
int writeSelfToParcel(Parcel out, PooledStringWriter pwriter, boolean sanitizeOnWrite,
float[] tmpMatrix) {
- // Guard used to skip non-sanitized data when writing for auto-fill.
+ // Guard used to skip non-sanitized data when writing for autofill.
boolean writeSensitive = true;
int flags = mFlags & ~FLAGS_ALL_CONTROL;
if (mId != View.NO_ID) {
flags |= FLAGS_HAS_ID;
}
- if (mAutoFillId != null) {
- flags |= FLAGS_HAS_AUTO_FILL_DATA;
+ if (mAutofillId != null) {
+ flags |= FLAGS_HAS_AUTOFILL_DATA;
}
if ((mX&~0x7fff) != 0 || (mY&~0x7fff) != 0
|| (mWidth&~0x7fff) != 0 | (mHeight&~0x7fff) != 0) {
@@ -737,8 +789,8 @@
pwriter.writeString(mClassName);
int writtenFlags = flags;
- if ((flags&FLAGS_HAS_AUTO_FILL_DATA) != 0 && (mSanitized || !sanitizeOnWrite)) {
- // Remove 'checked' from sanitized auto-fill request.
+ if ((flags&FLAGS_HAS_AUTOFILL_DATA) != 0 && (mSanitized || !sanitizeOnWrite)) {
+ // Remove 'checked' from sanitized autofill request.
writtenFlags = flags & ~FLAGS_CHECKED;
}
@@ -753,15 +805,15 @@
}
}
}
- if ((flags&FLAGS_HAS_AUTO_FILL_DATA) != 0) {
+ if ((flags&FLAGS_HAS_AUTOFILL_DATA) != 0) {
writeSensitive = mSanitized || !sanitizeOnWrite;
out.writeInt(mSanitized ? 1 : 0);
- out.writeParcelable(mAutoFillId, 0);
+ out.writeParcelable(mAutofillId, 0);
out.writeInt(mAutofillType);
- out.writeInt(mAutoFillHint);
- final AutoFillValue sanitizedValue = writeSensitive ? mAutoFillValue : null;
+ out.writeInt(mAutofillHint);
+ final AutofillValue sanitizedValue = writeSensitive ? mAutofillValue : null;
out.writeParcelable(sanitizedValue, 0);
- out.writeStringArray(mAutoFillOptions);
+ out.writeStringArray(mAutofillOptions);
}
if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
out.writeInt(mX);
@@ -840,17 +892,26 @@
}
/**
- * Gets the id that can be used to auto-fill the view contents.
- *
- * <p>It's only set when the {@link AssistStructure} is used for auto-filling purposes, not
- * for assist.
+ * @hide
+ * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
*/
- // TODO(b/33197203, b/33802548): add CTS/unit test
+ @Deprecated
public AutoFillId getAutoFillId() {
- return mAutoFillId;
+ return AutoFillId.forDaRealId(mAutofillId);
}
/**
+ * Gets the id that can be used to autofill the view contents.
+ *
+ * <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not
+ * for assist.
+ */
+ public AutofillId getAutofillId() {
+ return mAutofillId;
+ }
+
+ /**
+ * @hide
* @deprecated TODO(b/35956626): remove once clients use getAutoFilltype()
*/
@Deprecated
@@ -870,9 +931,9 @@
}
/**
- * Gets the the type of value that can be used to auto-fill the view contents.
+ * Gets the the type of value that can be used to autofill the view contents.
*
- * <p>It's only set when the {@link AssistStructure} is used for auto-filling purposes, not
+ * <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not
* for assist.
*/
public @View.AutofillType int getAutofillType() {
@@ -880,41 +941,48 @@
}
/**
- * Describes the content of a view so that a auto-fill service can fill in the appropriate
+ * Describes the content of a view so that a autofill service can fill in the appropriate
* data.
*
- * <p>It's only set when the {@link AssistStructure} is used for auto-filling purposes, not
+ * <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not
* for assist.</p>
*
* @return The hint for this view
*/
- // TODO(b/35364993): add CTS/unit test
- @View.AutoFillHint public int getAutoFillHint() {
- return mAutoFillHint;
+ @View.AutofillHint public int getAutoFillHint() {
+ return mAutofillHint;
+ }
+
+ /**
+ * @hide
+ * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
+ */
+ @Deprecated
+ public AutoFillValue getAutoFillValue() {
+ return AutoFillValue.forDaRealValue(mAutofillValue);
}
/**
* Gets the the value of this view.
*
- * <p>It's only set when the {@link AssistStructure} is used for auto-filling purposes, not
+ * <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not
* for assist.
*/
- // TODO(b/33197203, b/33802548): add CTS/unit test
- public AutoFillValue getAutoFillValue() {
- return mAutoFillValue;
+ public AutofillValue getAutofillValue() {
+ return mAutofillValue;
}
/**
- * Gets the options that can be used to auto-fill this structure.
+ * Gets the options that can be used to autofill this structure.
*
- * <p>Typically used by nodes whose {@link AutoFillType} is a list to indicate the meaning
- * of each possible value in the list.
+ * <p>Typically used by nodes whose {@link View#getAutofillType()} is a list to indicate
+ * the meaning of each possible value in the list.
*
- * <p>It's only set when the {@link AssistStructure} is used for auto-filling purposes, not
+ * <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not
* for assist.
*/
- public String[] getAutoFillOptions() {
- return mAutoFillOptions;
+ public String[] getAutofillOptions() {
+ return mAutofillOptions;
}
/**
@@ -932,18 +1000,18 @@
}
/**
- * Updates the {@link AutoFillValue} of this structure.
+ * Updates the {@link AutofillValue} of this structure.
*
* <p>Should be used just before sending the structure to the
- * {@link android.service.autofill.AutoFillService} for saving, since it will override the
+ * {@link android.service.autofill.AutofillService} for saving, since it will override the
* initial value.
*
* @hide
*/
- public void updateAutoFillValue(AutoFillValue value) {
- mAutoFillValue = value;
+ public void updateAutofillValue(AutofillValue value) {
+ mAutofillValue = value;
// TODO(b/33197203, b/33802548): decide whether to set text as well (so it would work
- // with "legacy" views) or just the auto-fill value
+ // with "legacy" views) or just the autofill value
final CharSequence text = value.getTextValue();
if (text != null) {
mText.mText = text;
@@ -1102,6 +1170,11 @@
}
/**
+ * Returns true if this node is opaque.
+ */
+ public boolean isOpaque() { return (mFlags&ViewNode.FLAGS_OPAQUE) != 0; }
+
+ /**
* Returns true if this node is something the user can perform a long click/press on.
*/
public boolean isLongClickable() {
@@ -1142,8 +1215,8 @@
* <li>Child nodes that represent hyperlinks (contains the hyperlink URL).
* </ol>
*
- * <strong>WARNING:</strong> a {@link android.service.autofill.AutoFillService} should only
- * use this URL for auto-fill purposes when it trusts the app generating it (i.e., the app
+ * <strong>WARNING:</strong> a {@link android.service.autofill.AutofillService} should only
+ * use this URL for autofill purposes when it trusts the app generating it (i.e., the app
* defined by {@link AssistStructure#getActivityComponent()}).
*/
public String getUrl() {
@@ -1394,6 +1467,12 @@
}
@Override
+ public void setOpaque(boolean opaque) {
+ mNode.mFlags = (mNode.mFlags & ~ViewNode.FLAGS_OPAQUE)
+ | (opaque ? ViewNode.FLAGS_OPAQUE : 0);
+ }
+
+ @Override
public void setClassName(String className) {
mNode.mClassName = className;
}
@@ -1504,15 +1583,15 @@
return mNode.mChildren != null ? mNode.mChildren.length : 0;
}
- private void setAutoFillId(ViewNode child, boolean forAutoFill, int virtualId) {
+ private void setAutofillId(ViewNode child, boolean forAutoFill, int virtualId) {
if (forAutoFill) {
- child.mAutoFillId = new AutoFillId(mNode.mAutoFillId, virtualId);
+ child.mAutofillId = new AutofillId(mNode.mAutofillId, virtualId);
}
}
private ViewStructure newChild(int index, boolean forAutoFill, int virtualId, int flags) {
ViewNode node = new ViewNode();
- setAutoFillId(node, forAutoFill, virtualId);
+ setAutofillId(node, forAutoFill, virtualId);
mNode.mChildren[index] = node;
return new ViewNodeBuilder(mAssist, node, false);
}
@@ -1520,7 +1599,7 @@
private ViewStructure asyncNewChild(int index, boolean forAutoFill, int virtualId) {
synchronized (mAssist) {
ViewNode node = new ViewNode();
- setAutoFillId(node, forAutoFill, virtualId);
+ setAutofillId(node, forAutoFill, virtualId);
mNode.mChildren[index] = node;
ViewNodeBuilder builder = new ViewNodeBuilder(mAssist, node, true);
mAssist.mPendingAsyncChildren.add(builder);
@@ -1535,7 +1614,7 @@
// TODO(b/33197203, b/33802548): add CTS/unit test
@Override
- public ViewStructure newChildForAutoFill(int index, int virtualId, int flags) {
+ public ViewStructure newChildForAutofill(int index, int virtualId, int flags) {
return newChild(index, true, virtualId, flags);
}
@@ -1545,7 +1624,7 @@
}
@Override
- public ViewStructure asyncNewChildForAutoFill(int index, int virtualId, int flags) {
+ public ViewStructure asyncNewChildForAutofill(int index, int virtualId, int flags) {
return asyncNewChild(index, true, virtualId);
}
@@ -1569,28 +1648,13 @@
}
@Override
- public void setAutoFillId(int viewId) {
- mNode.mAutoFillId = new AutoFillId(viewId);
+ public void setAutofillId(int viewId) {
+ mNode.mAutofillId = new AutofillId(viewId);
}
@Override
- public AutoFillId getAutoFillId() {
- return mNode.mAutoFillId;
- }
-
- @Override
- public void setAutoFillType(AutoFillType type) {
- if (type == null) return;
-
- if (type.isText()) {
- mNode.mAutofillType = View.AUTOFILL_TYPE_TEXT;
- } else if (type.isToggle()) {
- mNode.mAutofillType = View.AUTOFILL_TYPE_TOGGLE;
- } else if (type.isList()) {
- mNode.mAutofillType = View.AUTOFILL_TYPE_LIST;
- } else if (type.isDate()) {
- mNode.mAutofillType = View.AUTOFILL_TYPE_DATE;
- }
+ public AutofillId getAutofillId() {
+ return mNode.mAutofillId;
}
@Override
@@ -1599,18 +1663,18 @@
}
@Override
- public void setAutoFillHint(@View.AutoFillHint int hint) {
- mNode.mAutoFillHint = hint;
+ public void setAutofillHint(@View.AutofillHint int hint) {
+ mNode.mAutofillHint = hint;
}
@Override
- public void setAutoFillValue(AutoFillValue value) {
- mNode.mAutoFillValue = value;
+ public void setAutofillValue(AutofillValue value) {
+ mNode.mAutofillValue = value;
}
@Override
- public void setAutoFillOptions(String[] options) {
- mNode.mAutoFillOptions = options;
+ public void setAutofillOptions(String[] options) {
+ mNode.mAutofillOptions = options;
}
@Override
@@ -1648,13 +1712,14 @@
/** @hide */
public AssistStructure(Parcel in) {
+ mIsHomeActivity = in.readInt() == 1;
mReceiveChannel = in.readStrongBinder();
}
/**
* Helper method used to sanitize the structure before it's written to a parcel.
*
- * <p>Used just on auto-fill.
+ * <p>Used just on autofill.
* @hide
*/
public void sanitizeForParceling(boolean sanitize) {
@@ -1739,16 +1804,16 @@
if (node.isAssistBlocked()) {
Log.i(TAG, prefix + " BLOCKED");
}
- AutoFillId autoFillId = node.getAutoFillId();
- if (autoFillId == null) {
- Log.i(TAG, prefix + " NO AUTO-FILL ID");
+ AutofillId autofillId = node.getAutofillId();
+ if (autofillId == null) {
+ Log.i(TAG, prefix + " NO autofill ID");
} else {
- Log.i(TAG, prefix + "AutoFill info: id= " + autoFillId
+ Log.i(TAG, prefix + "Autofill info: id= " + autofillId
+ ", type=" + node.getAutofillType()
- + ", options=" + Arrays.toString(node.getAutoFillOptions())
+ + ", options=" + Arrays.toString(node.getAutofillOptions())
+ ", inputType=" + node.getInputType()
+ ", hint=" + Integer.toHexString(node.getAutoFillHint())
- + ", value=" + node.getAutoFillValue()
+ + ", value=" + node.getAutofillValue()
+ ", sanitized=" + node.isSanitized());
}
@@ -1772,6 +1837,15 @@
}
/**
+ * Returns whether the activity associated with this AssistStructure was the home activity
+ * at the time the assist data was acquired.
+ * @return Whether the activity was the home activity.
+ */
+ public boolean isHomeActivity() {
+ return mIsHomeActivity;
+ }
+
+ /**
* Return the number of window contents that have been collected in this assist data.
*/
public int getWindowNodeCount() {
@@ -1833,6 +1907,7 @@
@Override
public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mIsHomeActivity ? 1 : 0);
if (mHaveData) {
// This object holds its data. We want to write a send channel that the
// other side can use to retrieve that data.
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index d36692a..488511b 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1447,9 +1447,9 @@
}
/**
- * Return true if LE Periodic Advertising feature is supported.
+ * Return true if LE Extended Advertising feature is supported.
*
- * @return true if chipset supports LE Periodic Advertising feature
+ * @return true if chipset supports LE Extended Advertising feature
*/
public boolean isLeExtendedAdvertisingSupported() {
if (!getLeAccess()) return false;
diff --git a/core/java/android/bluetooth/le/AdvertisingSetParameters.java b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
index 03a01e1..453dd70 100644
--- a/core/java/android/bluetooth/le/AdvertisingSetParameters.java
+++ b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
@@ -284,7 +284,7 @@
*
* @param isAnonymous wether anonymous advertising should be used.
*/
- public Builder setAnonymouus(boolean isAnonymous) {
+ public Builder setAnonymous(boolean isAnonymous) {
this.isAnonymous = isAnonymous;
return this;
}
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
index b89c64a..457096b 100644
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ b/core/java/android/bluetooth/le/ScanFilter.java
@@ -23,6 +23,8 @@
import android.os.ParcelUuid;
import android.os.Parcelable;
+import com.android.internal.util.BitUtils;
+
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@@ -345,15 +347,7 @@
// Check if the uuid pattern matches the particular service uuid.
private static boolean matchesServiceUuid(UUID uuid, UUID mask, UUID data) {
- if (mask == null) {
- return uuid.equals(data);
- }
- if ((uuid.getLeastSignificantBits() & mask.getLeastSignificantBits()) !=
- (data.getLeastSignificantBits() & mask.getLeastSignificantBits())) {
- return false;
- }
- return ((uuid.getMostSignificantBits() & mask.getMostSignificantBits()) ==
- (data.getMostSignificantBits() & mask.getMostSignificantBits()));
+ return BitUtils.maskedEquals(data, uuid, mask);
}
// Check whether the data pattern matches the parsed data.
diff --git a/core/java/android/bluetooth/le/ScanResult.java b/core/java/android/bluetooth/le/ScanResult.java
index 583ddd2..745cd16 100644
--- a/core/java/android/bluetooth/le/ScanResult.java
+++ b/core/java/android/bluetooth/le/ScanResult.java
@@ -67,12 +67,12 @@
public static final int SID_NOT_PRESENT = 0xFF;
/**
- * Mask for checking wether event type represents legacy advertisement.
+ * Mask for checking whether event type represents legacy advertisement.
*/
private static final int ET_LEGACY_MASK = 0x10;
/**
- * Mask for checking wether event type represents connectable advertisement.
+ * Mask for checking whether event type represents connectable advertisement.
*/
private static final int ET_CONNECTABLE_MASK = 0x01;
diff --git a/core/java/android/companion/AssociationRequest.java b/core/java/android/companion/AssociationRequest.java
index d477f43..56f5d44 100644
--- a/core/java/android/companion/AssociationRequest.java
+++ b/core/java/android/companion/AssociationRequest.java
@@ -16,20 +16,21 @@
package android.companion;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.OneTimeUseBuilder;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
+import com.android.internal.util.ArrayUtils;
+
+import java.util.ArrayList;
+import java.util.List;
/**
* A request for the user to select a companion device to associate with.
*
- * You can optionally set a {@link Builder#setDeviceFilter filter} for which devices to show to the
+ * You can optionally set {@link Builder#addDeviceFilter filters} for which devices to show to the
* user to select from.
* The exact type and fields of the filter you can set depend on the
* medium type. See {@link Builder}'s static factory methods for specific protocols that are
@@ -37,38 +38,22 @@
*
* You can also set {@link Builder#setSingleDevice single device} to request a popup with single
* device to be shown instead of a list to choose from
- *
- * @param <F> Device filter type
*/
-public final class AssociationRequest<F extends DeviceFilter> implements Parcelable {
-
- /** @hide */
- public static final int MEDIUM_TYPE_BLUETOOTH = 0;
- /** @hide */
- public static final int MEDIUM_TYPE_BLUETOOTH_LE = 1;
- /** @hide */
- public static final int MEDIUM_TYPE_WIFI = 2;
-
- /** @hide */
- @IntDef({MEDIUM_TYPE_BLUETOOTH, MEDIUM_TYPE_BLUETOOTH_LE, MEDIUM_TYPE_WIFI})
- @Retention(RetentionPolicy.SOURCE)
- public @interface MediumType {}
+public final class AssociationRequest implements Parcelable {
private final boolean mSingleDevice;
- private final int mMediumType;
- private final F mDeviceFilter;
+ private final List<DeviceFilter<?>> mDeviceFilters;
- private AssociationRequest(boolean singleDevice, int mMediumType, F deviceFilter) {
+ private AssociationRequest(
+ boolean singleDevice, @Nullable List<DeviceFilter<?>> deviceFilters) {
this.mSingleDevice = singleDevice;
- this.mMediumType = mMediumType;
- this.mDeviceFilter = deviceFilter;
+ this.mDeviceFilters = ArrayUtils.emptyIfNull(deviceFilters);
}
private AssociationRequest(Parcel in) {
this(
in.readByte() != 0,
- in.readInt(),
- in.readParcelable(AssociationRequest.class.getClassLoader()));
+ in.readParcelableList(new ArrayList<>(), AssociationRequest.class.getClassLoader()));
}
/** @hide */
@@ -77,22 +62,15 @@
}
/** @hide */
- @MediumType
- public int getMediumType() {
- return mMediumType;
- }
-
- /** @hide */
- @Nullable
- public F getDeviceFilter() {
- return mDeviceFilter;
+ @NonNull
+ public List<DeviceFilter<?>> getDeviceFilters() {
+ return mDeviceFilters;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeByte((byte) (mSingleDevice ? 1 : 0));
- dest.writeInt(mMediumType);
- dest.writeParcelable(mDeviceFilter, flags);
+ dest.writeParcelableList(mDeviceFilters, flags);
}
@Override
@@ -114,45 +92,19 @@
/**
* A builder for {@link AssociationRequest}
- *
- * @param <F> the type of filter for the request.
*/
- public static final class Builder<F extends DeviceFilter>
- extends OneTimeUseBuilder<AssociationRequest<F>> {
+ public static final class Builder extends OneTimeUseBuilder<AssociationRequest> {
private boolean mSingleDevice = false;
- @MediumType private int mMediumType;
- @Nullable private F mDeviceFilter = null;
+ @Nullable private ArrayList<DeviceFilter<?>> mDeviceFilters = null;
- private Builder() {}
-
- /**
- * Create a new builder for an association request with a Bluetooth LE device
- */
- @NonNull
- public static Builder<BluetoothLEDeviceFilter> createForBluetoothLEDevice() {
- return new Builder<BluetoothLEDeviceFilter>()
- .setMediumType(MEDIUM_TYPE_BLUETOOTH_LE);
- }
-
- /**
- * Create a new builder for an association request with a Bluetooth(non-LE) device
- */
- @NonNull
- public static Builder<BluetoothDeviceFilter> createForBluetoothDevice() {
- return new Builder<BluetoothDeviceFilter>()
- .setMediumType(MEDIUM_TYPE_BLUETOOTH);
- }
-
- //TODO implement, once specific filter classes are available
-// public static Builder<> createForWiFiDevice()
-// public static Builder<> createForNanDevice()
+ public Builder() {}
/**
* @param singleDevice if true, scanning for a device will stop as soon as at least one
* fitting device is found
*/
@NonNull
- public Builder<F> setSingleDevice(boolean singleDevice) {
+ public Builder setSingleDevice(boolean singleDevice) {
checkNotUsed();
this.mSingleDevice = singleDevice;
return this;
@@ -163,29 +115,20 @@
* user
*/
@NonNull
- public Builder<F> setDeviceFilter(@Nullable F deviceFilter) {
+ public Builder addDeviceFilter(@Nullable DeviceFilter<?> deviceFilter) {
checkNotUsed();
- this.mDeviceFilter = deviceFilter;
- return this;
- }
-
- /**
- * @param deviceType A type of medium over which to discover devices
- *
- * @see MediumType
- */
- @NonNull
- private Builder<F> setMediumType(@MediumType int deviceType) {
- mMediumType = deviceType;
+ if (deviceFilter != null) {
+ mDeviceFilters = ArrayUtils.add(mDeviceFilters, deviceFilter);
+ }
return this;
}
/** @inheritDoc */
@NonNull
@Override
- public AssociationRequest<F> build() {
+ public AssociationRequest build() {
markUsed();
- return new AssociationRequest<>(mSingleDevice, mMediumType, mDeviceFilter);
+ return new AssociationRequest(mSingleDevice, mDeviceFilters);
}
}
}
diff --git a/core/java/android/companion/BluetoothDeviceFilter.java b/core/java/android/companion/BluetoothDeviceFilter.java
index 5a69955..0f16b7b 100644
--- a/core/java/android/companion/BluetoothDeviceFilter.java
+++ b/core/java/android/companion/BluetoothDeviceFilter.java
@@ -16,6 +16,7 @@
package android.companion;
+import static android.companion.BluetoothDeviceFilterUtils.getDeviceDisplayNameInternal;
import static android.companion.BluetoothDeviceFilterUtils.matchesAddress;
import static android.companion.BluetoothDeviceFilterUtils.matchesName;
import static android.companion.BluetoothDeviceFilterUtils.matchesServiceUuids;
@@ -40,8 +41,6 @@
*/
public final class BluetoothDeviceFilter implements DeviceFilter<BluetoothDevice> {
- private static BluetoothDeviceFilter NO_OP;
-
private final Pattern mNamePattern;
private final String mAddress;
private final List<ParcelUuid> mServiceUuids;
@@ -67,22 +66,7 @@
}
private static List<ParcelUuid> readUuids(Parcel in) {
- final ArrayList<ParcelUuid> list = new ArrayList<>();
- in.readParcelableList(list, ParcelUuid.class.getClassLoader());
- return list;
- }
-
- /** @hide */
- @NonNull
- public static BluetoothDeviceFilter nullsafe(@Nullable BluetoothDeviceFilter nullable) {
- return nullable != null ? nullable : noOp();
- }
-
- /** @hide */
- @NonNull
- public static BluetoothDeviceFilter noOp() {
- if (NO_OP == null) NO_OP = new Builder().build();
- return NO_OP;
+ return in.readParcelableList(new ArrayList<>(), ParcelUuid.class.getClassLoader());
}
/** @hide */
@@ -94,6 +78,18 @@
}
/** @hide */
+ @Override
+ public String getDeviceDisplayName(BluetoothDevice device) {
+ return getDeviceDisplayNameInternal(device);
+ }
+
+ /** @hide */
+ @Override
+ public int getMediumType() {
+ return DeviceFilter.MEDIUM_TYPE_BLUETOOTH;
+ }
+
+ /** @hide */
@Nullable
public Pattern getNamePattern() {
return mNamePattern;
diff --git a/core/java/android/companion/BluetoothDeviceFilterUtils.java b/core/java/android/companion/BluetoothDeviceFilterUtils.java
index 289f995..8a316f1 100644
--- a/core/java/android/companion/BluetoothDeviceFilterUtils.java
+++ b/core/java/android/companion/BluetoothDeviceFilterUtils.java
@@ -23,7 +23,9 @@
import android.annotation.Nullable;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.ScanFilter;
+import android.net.wifi.ScanResult;
import android.os.ParcelUuid;
+import android.os.Parcelable;
import android.util.Log;
import java.util.Arrays;
@@ -96,12 +98,47 @@
return result;
}
- private static void debugLogMatchResult(
- boolean result, BluetoothDevice device, Object criteria) {
- Log.i(LOG_TAG, getDeviceDisplayName(device) + (result ? " ~ " : " !~ ") + criteria);
+ static boolean matchesName(@Nullable Pattern namePattern, ScanResult device) {
+ boolean result;
+ if (namePattern == null) {
+ result = true;
+ } else if (device == null) {
+ result = false;
+ } else {
+ final String name = device.SSID;
+ result = name != null && namePattern.matcher(name).find();
+ }
+ if (DEBUG) debugLogMatchResult(result, device, namePattern);
+ return result;
}
- public static String getDeviceDisplayName(@NonNull BluetoothDevice device) {
+ private static void debugLogMatchResult(
+ boolean result, BluetoothDevice device, Object criteria) {
+ Log.i(LOG_TAG, getDeviceDisplayNameInternal(device) + (result ? " ~ " : " !~ ") + criteria);
+ }
+
+ private static void debugLogMatchResult(
+ boolean result, ScanResult device, Object criteria) {
+ Log.i(LOG_TAG, getDeviceDisplayNameInternal(device) + (result ? " ~ " : " !~ ") + criteria);
+ }
+
+ public static String getDeviceDisplayNameInternal(@NonNull BluetoothDevice device) {
return firstNotEmpty(device.getAliasName(), device.getAddress());
}
+
+ public static String getDeviceDisplayNameInternal(@NonNull ScanResult device) {
+ return firstNotEmpty(device.SSID, device.BSSID);
+ }
+
+ public static String getDeviceMacAddress(@NonNull Parcelable device) {
+ if (device instanceof BluetoothDevice) {
+ return ((BluetoothDevice) device).getAddress();
+ } else if (device instanceof ScanResult) {
+ return ((ScanResult) device).BSSID;
+ } else if (device instanceof android.bluetooth.le.ScanResult) {
+ return getDeviceMacAddress(((android.bluetooth.le.ScanResult) device).getDevice());
+ } else {
+ throw new IllegalArgumentException("Unknown device type: " + device);
+ }
+ }
}
diff --git a/core/java/android/companion/BluetoothLEDeviceFilter.java b/core/java/android/companion/BluetoothLEDeviceFilter.java
index 4a481ca..e057fbc 100644
--- a/core/java/android/companion/BluetoothLEDeviceFilter.java
+++ b/core/java/android/companion/BluetoothLEDeviceFilter.java
@@ -16,18 +16,25 @@
package android.companion;
+import static android.companion.BluetoothDeviceFilterUtils.getDeviceDisplayNameInternal;
import static android.companion.BluetoothDeviceFilterUtils.patternFromString;
import static android.companion.BluetoothDeviceFilterUtils.patternToString;
+import static com.android.internal.util.Preconditions.checkArgument;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.SuppressLint;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.ScanFilter;
+import android.bluetooth.le.ScanRecord;
+import android.bluetooth.le.ScanResult;
import android.os.Parcel;
import android.provider.OneTimeUseBuilder;
+import android.text.TextUtils;
+import com.android.internal.util.BitUtils;
import com.android.internal.util.ObjectUtils;
+import com.android.internal.util.Preconditions;
import java.util.regex.Pattern;
@@ -36,36 +43,33 @@
*
* @see ScanFilter
*/
-public final class BluetoothLEDeviceFilter implements DeviceFilter<BluetoothDevice> {
+public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> {
- private static BluetoothLEDeviceFilter NO_OP;
+ private static final int RENAME_PREFIX_LENGTH_LIMIT = 10;
private final Pattern mNamePattern;
private final ScanFilter mScanFilter;
+ private final byte[] mRawDataFilter;
+ private final byte[] mRawDataFilterMask;
+ private final String mRenamePrefix;
+ private final String mRenameSuffix;
+ private final int mRenameBytesFrom;
+ private final int mRenameBytesTo;
+ private final boolean mRenameBytesReverseOrder;
- private BluetoothLEDeviceFilter(Pattern namePattern, ScanFilter scanFilter) {
+ private BluetoothLEDeviceFilter(Pattern namePattern, ScanFilter scanFilter,
+ byte[] rawDataFilter, byte[] rawDataFilterMask, String renamePrefix,
+ String renameSuffix, int renameBytesFrom, int renameBytesTo,
+ boolean renameBytesReverseOrder) {
mNamePattern = namePattern;
mScanFilter = ObjectUtils.firstNotNull(scanFilter, ScanFilter.EMPTY);
- }
-
- @SuppressLint("ParcelClassLoader")
- private BluetoothLEDeviceFilter(Parcel in) {
- this(
- patternFromString(in.readString()),
- in.readParcelable(null));
- }
-
- /** @hide */
- @NonNull
- public static BluetoothLEDeviceFilter nullsafe(@Nullable BluetoothLEDeviceFilter nullable) {
- return nullable != null ? nullable : noOp();
- }
-
- /** @hide */
- @NonNull
- public static BluetoothLEDeviceFilter noOp() {
- if (NO_OP == null) NO_OP = new Builder().build();
- return NO_OP;
+ mRawDataFilter = rawDataFilter;
+ mRawDataFilterMask = rawDataFilterMask;
+ mRenamePrefix = renamePrefix;
+ mRenameSuffix = renameSuffix;
+ mRenameBytesFrom = renameBytesFrom;
+ mRenameBytesTo = renameBytesTo;
+ mRenameBytesReverseOrder = renameBytesReverseOrder;
}
/** @hide */
@@ -81,12 +85,80 @@
}
/** @hide */
+ @Nullable
+ public byte[] getRawDataFilter() {
+ return mRawDataFilter;
+ }
+
+ /** @hide */
+ @Nullable
+ public byte[] getRawDataFilterMask() {
+ return mRawDataFilterMask;
+ }
+
+ /** @hide */
+ @Nullable
+ public String getRenamePrefix() {
+ return mRenamePrefix;
+ }
+
+ /** @hide */
+ @Nullable
+ public String getRenameSuffix() {
+ return mRenameSuffix;
+ }
+
+ /** @hide */
+ public int getRenameBytesFrom() {
+ return mRenameBytesFrom;
+ }
+
+ /** @hide */
+ public int getRenameBytesTo() {
+ return mRenameBytesTo;
+ }
+
+ /** @hide */
+ public boolean isRenameBytesReverseOrder() {
+ return mRenameBytesReverseOrder;
+ }
+
+ /** @hide */
@Override
- public boolean matches(BluetoothDevice device) {
+ @Nullable
+ public String getDeviceDisplayName(ScanResult sr) {
+ if (mRenameBytesFrom < 0) return getDeviceDisplayNameInternal(sr.getDevice());
+ final byte[] bytes = sr.getScanRecord().getBytes();
+ final StringBuilder sb = new StringBuilder(TextUtils.emptyIfNull(mRenamePrefix));
+ int startInclusive = mRenameBytesFrom;
+ int endInclusive = mRenameBytesTo - 1;
+ int initial = mRenameBytesReverseOrder ? endInclusive : startInclusive;
+ int step = mRenameBytesReverseOrder ? -1 : 1;
+ for (int i = initial; startInclusive <= i && i <= endInclusive; i+=step) {
+ sb.append(Byte.toHexString(bytes[i], true));
+ }
+ return sb.append(TextUtils.emptyIfNull(mRenameSuffix)).toString();
+ }
+
+ /** @hide */
+ @Override
+ public boolean matches(ScanResult device) {
+ return matches(device.getDevice())
+ && BitUtils.maskedEquals(device.getScanRecord().getBytes(),
+ mRawDataFilter, mRawDataFilterMask);
+ }
+
+ private boolean matches(BluetoothDevice device) {
return BluetoothDeviceFilterUtils.matches(getScanFilter(), device)
&& BluetoothDeviceFilterUtils.matchesName(getNamePattern(), device);
}
+ /** @hide */
+ @Override
+ public int getMediumType() {
+ return DeviceFilter.MEDIUM_TYPE_BLUETOOTH_LE;
+ }
+
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(patternToString(getNamePattern()));
@@ -102,7 +174,13 @@
= new Creator<BluetoothLEDeviceFilter>() {
@Override
public BluetoothLEDeviceFilter createFromParcel(Parcel in) {
- return new BluetoothLEDeviceFilter(in);
+ return new BluetoothLEDeviceFilter.Builder()
+ .setNamePattern(patternFromString(in.readString()))
+ .setScanFilter(in.readParcelable(null))
+ .setRawDataFilter(in.readBlob(), in.readBlob())
+ .setRename(in.readString(), in.readString(),
+ in.readInt(), in.readInt(), in.readBoolean())
+ .build();
}
@Override
@@ -111,16 +189,28 @@
}
};
+ public static int getRenamePrefixLengthLimit() {
+ return RENAME_PREFIX_LENGTH_LIMIT;
+ }
+
/**
* Builder for {@link BluetoothLEDeviceFilter}
*/
public static final class Builder extends OneTimeUseBuilder<BluetoothLEDeviceFilter> {
private ScanFilter mScanFilter;
private Pattern mNamePattern;
+ private byte[] mRawDataFilter;
+ private byte[] mRawDataFilterMask;
+ private String mRenamePrefix;
+ private String mRenameSuffix;
+ private int mRenameBytesFrom = -1;
+ private int mRenameBytesTo;
+ private boolean mRenameBytesReverseOrder = false;
/**
* @param regex if set, only devices with {@link BluetoothDevice#getName name} matching the
* given regular expression will be shown
+ * @return self for chaining
*/
public Builder setNamePattern(@Nullable Pattern regex) {
checkNotUsed();
@@ -131,6 +221,7 @@
/**
* @param scanFilter a {@link ScanFilter} to filter devices by
*
+ * @return self for chaining
* @see ScanFilter for specific details on its various fields
*/
@NonNull
@@ -140,12 +231,66 @@
return this;
}
+ /**
+ * Filter devices by raw advertisement data, as obtained by {@link ScanRecord#getBytes}
+ *
+ * @param rawDataFilter bit values that have to match against advertized data
+ * @param rawDataFilterMask bits that have to be matched
+ * @return self for chaining
+ */
+ @NonNull
+ public Builder setRawDataFilter(@NonNull byte[] rawDataFilter,
+ @NonNull byte[] rawDataFilterMask) {
+ checkNotUsed();
+ checkArgument(rawDataFilter.length == rawDataFilterMask.length,
+ "Mask and filter should be the same length");
+ mRawDataFilter = Preconditions.checkNotNull(rawDataFilter);
+ mRawDataFilterMask = Preconditions.checkNotNull(rawDataFilterMask);
+ return this;
+ }
+
+ /**
+ * Rename the devices shown in the list, using specific bytes from the raw advertisement
+ * data ({@link ScanRecord#getBytes}) in hexadecimal format, as well as a custom
+ * prefix/suffix around them
+ *
+ * Note that the prefix length is limited to {@link #getRenamePrefixLengthLimit} characters
+ * to ensure that there's enough space to display the byte data
+ *
+ * The range of bytes to be displayed cannot be empty
+ *
+ * @param prefix to be displayed before the byte data
+ * @param suffix to be displayed after the byte data
+ * @param bytesFrom the start byte index to be displayed (inclusive)
+ * @param bytesTo the end byte index to be displayed (exclusive)
+ * @param bytesReverseOrder if true, the byte order of the provided range will be flipped
+ * when displaying
+ * @return self for chaining
+ */
+ @NonNull
+ public Builder setRename(@NonNull String prefix, @NonNull String suffix,
+ int bytesFrom, int bytesTo, boolean bytesReverseOrder) {
+ checkNotUsed();
+ checkArgument(TextUtils.length(prefix) >= getRenamePrefixLengthLimit(),
+ "Prefix is too short");
+ mRenamePrefix = prefix;
+ mRenameSuffix = suffix;
+ checkArgument(bytesFrom < bytesTo, "Byte range must be non-empty");
+ mRenameBytesFrom = bytesFrom;
+ mRenameBytesTo = bytesTo;
+ mRenameBytesReverseOrder = bytesReverseOrder;
+ return this;
+ }
+
/** @inheritDoc */
@Override
@NonNull
public BluetoothLEDeviceFilter build() {
markUsed();
- return new BluetoothLEDeviceFilter(mNamePattern, mScanFilter);
+ return new BluetoothLEDeviceFilter(mNamePattern, mScanFilter,
+ mRawDataFilter, mRawDataFilterMask,
+ mRenamePrefix, mRenameSuffix,
+ mRenameBytesFrom, mRenameBytesTo, mRenameBytesReverseOrder);
}
}
}
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index 6fa32b4..5710ad1 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -117,7 +117,7 @@
* @see AssociationRequest
*/
public void associate(
- @NonNull AssociationRequest<?> request,
+ @NonNull AssociationRequest request,
@NonNull Callback callback,
@Nullable Handler handler) {
final Handler finalHandler = handler != null
diff --git a/core/java/android/companion/DeviceFilter.java b/core/java/android/companion/DeviceFilter.java
index 8362b2d..9b4fdfd 100644
--- a/core/java/android/companion/DeviceFilter.java
+++ b/core/java/android/companion/DeviceFilter.java
@@ -17,17 +17,28 @@
package android.companion;
+import android.annotation.IntDef;
import android.annotation.Nullable;
import android.os.Parcelable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* A filter for companion devices of type {@code D}
*
* @param <D> Type of devices, filtered by this filter,
- * e.g. {@link android.bluetooth.BluetoothDevice}, {@link android.net.wifi.WifiInfo}
+ * e.g. {@link android.bluetooth.BluetoothDevice}, {@link android.net.wifi.ScanResult}
*/
public interface DeviceFilter<D extends Parcelable> extends Parcelable {
+ /** @hide */
+ int MEDIUM_TYPE_BLUETOOTH = 0;
+ /** @hide */
+ int MEDIUM_TYPE_BLUETOOTH_LE = 1;
+ /** @hide */
+ int MEDIUM_TYPE_WIFI = 2;
+
/**
* @return whether the given device matches this filter
*
@@ -35,6 +46,12 @@
*/
boolean matches(D device);
+ /** @hide */
+ String getDeviceDisplayName(D device);
+
+ /** @hide */
+ @MediumType int getMediumType();
+
/**
* A nullsafe {@link #matches(Parcelable)}, returning true if the filter is null
*
@@ -43,4 +60,9 @@
static <D extends Parcelable> boolean matches(@Nullable DeviceFilter<D> filter, D device) {
return filter == null || filter.matches(device);
}
+
+ /** @hide */
+ @IntDef({MEDIUM_TYPE_BLUETOOTH, MEDIUM_TYPE_BLUETOOTH_LE, MEDIUM_TYPE_WIFI})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface MediumType {}
}
diff --git a/core/java/android/companion/WifiDeviceFilter.java b/core/java/android/companion/WifiDeviceFilter.java
new file mode 100644
index 0000000..1ab9ce1
--- /dev/null
+++ b/core/java/android/companion/WifiDeviceFilter.java
@@ -0,0 +1,125 @@
+/*
+ * 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.companion;
+
+import static android.companion.BluetoothDeviceFilterUtils.getDeviceDisplayNameInternal;
+import static android.companion.BluetoothDeviceFilterUtils.patternFromString;
+import static android.companion.BluetoothDeviceFilterUtils.patternToString;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.le.ScanFilter;
+import android.net.wifi.ScanResult;
+import android.os.Parcel;
+import android.provider.OneTimeUseBuilder;
+
+import java.util.regex.Pattern;
+
+/**
+ * A filter for Wifi devices
+ *
+ * @see ScanFilter
+ */
+public final class WifiDeviceFilter implements DeviceFilter<ScanResult> {
+
+ private final Pattern mNamePattern;
+
+ private WifiDeviceFilter(Pattern namePattern) {
+ mNamePattern = namePattern;
+ }
+
+ @SuppressLint("ParcelClassLoader")
+ private WifiDeviceFilter(Parcel in) {
+ this(patternFromString(in.readString()));
+ }
+
+ /** @hide */
+ @Nullable
+ public Pattern getNamePattern() {
+ return mNamePattern;
+ }
+
+
+ /** @hide */
+ @Override
+ public boolean matches(ScanResult device) {
+ return BluetoothDeviceFilterUtils.matchesName(getNamePattern(), device);
+ }
+
+ /** @hide */
+ @Override
+ public String getDeviceDisplayName(ScanResult device) {
+ return getDeviceDisplayNameInternal(device);
+ }
+
+ /** @hide */
+ @Override
+ public int getMediumType() {
+ return MEDIUM_TYPE_WIFI;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(patternToString(getNamePattern()));
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<WifiDeviceFilter> CREATOR
+ = new Creator<WifiDeviceFilter>() {
+ @Override
+ public WifiDeviceFilter createFromParcel(Parcel in) {
+ return new WifiDeviceFilter(in);
+ }
+
+ @Override
+ public WifiDeviceFilter[] newArray(int size) {
+ return new WifiDeviceFilter[size];
+ }
+ };
+
+ /**
+ * Builder for {@link WifiDeviceFilter}
+ */
+ public static final class Builder extends OneTimeUseBuilder<WifiDeviceFilter> {
+ private Pattern mNamePattern;
+
+ /**
+ * @param regex if set, only devices with {@link BluetoothDevice#getName name} matching the
+ * given regular expression will be shown
+ * @return self for chaining
+ */
+ public Builder setNamePattern(@Nullable Pattern regex) {
+ checkNotUsed();
+ mNamePattern = regex;
+ return this;
+ }
+
+ /** @inheritDoc */
+ @Override
+ @NonNull
+ public WifiDeviceFilter build() {
+ markUsed();
+ return new WifiDeviceFilter(mNamePattern);
+ }
+ }
+}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index de503c0..3cf96ed 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3401,12 +3401,12 @@
public static final String VOICE_INTERACTION_MANAGER_SERVICE = "voiceinteraction";
/**
- * Official published name of the (internal) auto-fill service.
+ * Official published name of the (internal) autofill service.
*
* @hide
* @see #getSystemService
*/
- public static final String AUTO_FILL_MANAGER_SERVICE = "autofill";
+ public static final String AUTOFILL_MANAGER_SERVICE = "autofill";
/**
* Use with {@link #getSystemService} to access the
diff --git a/core/java/android/metrics/LogMaker.java b/core/java/android/metrics/LogMaker.java
index 612b135..60b27b4 100644
--- a/core/java/android/metrics/LogMaker.java
+++ b/core/java/android/metrics/LogMaker.java
@@ -46,8 +46,9 @@
private SparseArray<Object> entries = new SparseArray();
- public LogMaker(int mainCategory) {
- setCategory(mainCategory);
+ /** @param category for the new LogMaker. */
+ public LogMaker(int category) {
+ setCategory(category);
}
/* Deserialize from the eventlog */
@@ -55,71 +56,133 @@
deserialize(items);
}
+ /** @param category to replace the existing setting. */
public LogMaker setCategory(int category) {
entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_CATEGORY, category);
return this;
}
+ /** Set the category to unknown. */
public LogMaker clearCategory() {
entries.remove(MetricsEvent.RESERVED_FOR_LOGBUILDER_CATEGORY);
return this;
}
+ /** @param type to replace the existing setting. */
public LogMaker setType(int type) {
entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_TYPE, type);
return this;
}
+ /** Set the type to unknown. */
public LogMaker clearType() {
entries.remove(MetricsEvent.RESERVED_FOR_LOGBUILDER_TYPE);
return this;
}
+ /** @param subtype to replace the existing setting. */
public LogMaker setSubtype(int subtype) {
entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_SUBTYPE, subtype);
return this;
}
+ /** Set the subtype to 0. */
public LogMaker clearSubtype() {
entries.remove(MetricsEvent.RESERVED_FOR_LOGBUILDER_SUBTYPE);
return this;
}
+ /**
+ * This will be set by the system when the log is persisted.
+ * Client-supplied values will be ignored.
+ *
+ * @param timestamp to replace the existing settings.
+ * @hide
+ */
public LogMaker setTimestamp(long timestamp) {
entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_TIMESTAMP, timestamp);
return this;
}
+ /** Remove the timestamp property.
+ * @hide
+ */
public LogMaker clearTimestamp() {
entries.remove(MetricsEvent.RESERVED_FOR_LOGBUILDER_TIMESTAMP);
return this;
}
+ /** @param packageName to replace the existing setting. */
public LogMaker setPackageName(String packageName) {
entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_PACKAGENAME, packageName);
return this;
}
+ /** Remove the package name property. */
public LogMaker clearPackageName() {
entries.remove(MetricsEvent.RESERVED_FOR_LOGBUILDER_PACKAGENAME);
return this;
}
+ /**
+ * This will be set by the system when the log is persisted.
+ * Client-supplied values will be ignored.
+ *
+ * @param pid to replace the existing setting.
+ * @hide
+ */
+ public LogMaker setProcessId(int pid) {
+ entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_PID, pid);
+ return this;
+ }
+
+ /** Remove the process ID property.
+ * @hide
+ */
+ public LogMaker clearProcessId() {
+ entries.remove(MetricsEvent.RESERVED_FOR_LOGBUILDER_PID);
+ return this;
+ }
+
+ /**
+ * The name of the counter or histogram.
+ * Only useful for counter or histogram category objects.
+ * @param name to replace the existing setting.
+ * @hide
+ */
public LogMaker setCounterName(String name) {
entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_NAME, name);
return this;
}
+ /**
+ * The bucket label, expressed as an integer.
+ * Only useful for histogram category objects.
+ * @param bucket to replace the existing setting.
+ * @hide
+ */
public LogMaker setCounterBucket(int bucket) {
entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_BUCKET, bucket);
return this;
}
+ /**
+ * The bucket label, expressed as a long integer.
+ * Only useful for histogram category objects.
+ * @param bucket to replace the existing setting.
+ * @hide
+ */
public LogMaker setCounterBucket(long bucket) {
entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_BUCKET, bucket);
return this;
}
+ /**
+ * The value to increment the counter or bucket by.
+ * Only useful for counter and histogram category objects.
+ * @param value to replace the existing setting.
+ * @hide
+ */
public LogMaker setCounterValue(int value) {
entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_VALUE, value);
return this;
@@ -171,6 +234,7 @@
return entries.get(tag);
}
+ /** @return the category of the log, or unknown. */
public int getCategory() {
Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_CATEGORY);
if (obj instanceof Integer) {
@@ -180,6 +244,7 @@
}
}
+ /** @return the type of the log, or unknwon. */
public int getType() {
Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_TYPE);
if (obj instanceof Integer) {
@@ -189,6 +254,7 @@
}
}
+ /** @return the subtype of the log, or 0. */
public int getSubtype() {
Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_SUBTYPE);
if (obj instanceof Integer) {
@@ -198,6 +264,7 @@
}
}
+ /** @return the timestamp of the log.or 0 */
public long getTimestamp() {
Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_TIMESTAMP);
if (obj instanceof Long) {
@@ -207,6 +274,7 @@
}
}
+ /** @return the package name of the log, or null. */
public String getPackageName() {
Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_PACKAGENAME);
if (obj instanceof String) {
@@ -216,6 +284,17 @@
}
}
+ /** @return the process ID of the log, or -1. */
+ public int getProcessId() {
+ Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_PID);
+ if (obj instanceof Integer) {
+ return (Integer) obj;
+ } else {
+ return -1;
+ }
+ }
+
+ /** @return the name of the counter, or null. */
public String getCounterName() {
Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_NAME);
if (obj instanceof String) {
@@ -225,6 +304,7 @@
}
}
+ /** @return the bucket label of the histogram\, or 0. */
public long getCounterBucket() {
Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_BUCKET);
if (obj instanceof Number) {
@@ -234,11 +314,13 @@
}
}
+ /** @return true if the bucket label was specified as a long integer. */
public boolean isLongCounterBucket() {
Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_BUCKET);
return obj instanceof Long;
}
+ /** @return the increment value of the counter, or 0. */
public int getCounterValue() {
Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_VALUE);
if (obj instanceof Integer) {
@@ -249,7 +331,7 @@
}
/**
- * Assemble logs into structure suitable for EventLog.
+ * @return a representation of the log suitable for EventLog.
*/
public Object[] serialize() {
Object[] out = new Object[entries.size() * 2];
diff --git a/core/java/android/metrics/MetricsReader.java b/core/java/android/metrics/MetricsReader.java
index dd8a74d..181e87f 100644
--- a/core/java/android/metrics/MetricsReader.java
+++ b/core/java/android/metrics/MetricsReader.java
@@ -77,7 +77,8 @@
objects[0] = data;
}
mEventQueue.add(new LogMaker(objects)
- .setTimestamp(eventTimestampMs));
+ .setTimestamp(eventTimestampMs)
+ .setProcessId(event.getProcessId()));
mLastEventMs = eventTimestampMs;
}
}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index f94e89a..7a39d23 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -601,6 +601,11 @@
nativeWriteString(mNativePtr, val);
}
+ /** @hide */
+ public final void writeBoolean(boolean val) {
+ writeInt(val ? 1 : 0);
+ }
+
/**
* Write a CharSequence value into the parcel at the current dataPosition(),
* growing dataCapacity() if needed.
@@ -1964,6 +1969,11 @@
return nativeReadString(mNativePtr);
}
+ /** @hide */
+ public final boolean readBoolean() {
+ return readInt() != 0;
+ }
+
/**
* Read a CharSequence value from the parcel at the current dataPosition().
* @hide
@@ -2490,11 +2500,11 @@
* @see #writeParcelableList(List, int)
* @hide
*/
- public final <T extends Parcelable> void readParcelableList(List<T> list, ClassLoader cl) {
+ public final <T extends Parcelable> List<T> readParcelableList(List<T> list, ClassLoader cl) {
final int N = readInt();
if (N == -1) {
list.clear();
- return;
+ return list;
}
final int M = list.size();
@@ -2508,6 +2518,7 @@
for (; i<M; i++) {
list.remove(N);
}
+ return list;
}
/**
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 33b5903..173603d 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -1367,24 +1367,25 @@
}
/**
- * Finds the canonical path to the top of the tree. The return value starts
- * from the top of the tree or the root document to the requested document,
- * both inclusive.
+ * Finds the canonical path from the top of the document tree.
*
- * Document ID should be unique across roots.
+ * The {@link Path#getPath()} of the return value contains the document ID
+ * of all documents along the path from the top the document tree to the
+ * requested document, both inclusive.
+ *
+ * The {@link Path#getRootId()} of the return value returns {@code null}.
*
* @param treeUri treeUri of the document which path is requested.
- * @return a list of documents ID starting from the top of the tree to the
- * requested document, or {@code null} if failed.
+ * @return the path of the document, or {@code null} if failed.
* @see DocumentsProvider#findDocumentPath(String, String)
*/
- public static List<String> findDocumentPath(ContentResolver resolver, Uri treeUri) {
+ public static Path findDocumentPath(ContentResolver resolver, Uri treeUri) {
checkArgument(isTreeUri(treeUri), treeUri + " is not a tree uri.");
final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
treeUri.getAuthority());
try {
- return findDocumentPath(client, treeUri).getPath();
+ return findDocumentPath(client, treeUri);
} catch (Exception e) {
Log.w(TAG, "Failed to find path", e);
return null;
@@ -1394,12 +1395,14 @@
}
/**
- * Finds the canonical path. If uri is a document uri returns path to a root and
- * its associated root id. If uri is a tree uri returns the path to the top of
- * the tree. The {@link Path#getPath()} in the return value starts from the top of
- * the tree or the root document to the requested document, both inclusive.
+ * Finds the canonical path. If uri is a document uri returns path from a root and
+ * its associated root id. If uri is a tree uri returns the path from the top of
+ * the tree. The {@link Path#getPath()} of the return value contains document ID
+ * starts from the top of the tree or the root document to the requested document,
+ * both inclusive.
*
- * Document id should be unique across roots.
+ * Callers can expect the root ID returned from multiple calls to this method is
+ * consistent.
*
* @param uri uri of the document which path is requested. It can be either a
* plain document uri or a tree uri.
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index f5e558a..89a80f0 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -65,6 +65,7 @@
import libcore.io.IoUtils;
import java.io.FileNotFoundException;
+import java.util.LinkedList;
import java.util.Objects;
/**
@@ -352,14 +353,14 @@
* Different roots should use different document ID to refer to the same
* document.
*
- * @param childDocumentId the document which path is requested.
* @param parentDocumentId the document from which the path starts if not null,
* or null to indicate a path from the root is requested.
+ * @param childDocumentId the document which path is requested.
* @return the path of the requested document. If parentDocumentId is null
* returned root ID must not be null. If parentDocumentId is not null
* returned root ID must be null.
*/
- public Path findDocumentPath(String childDocumentId, @Nullable String parentDocumentId)
+ public Path findDocumentPath(@Nullable String parentDocumentId, String childDocumentId)
throws FileNotFoundException {
throw new UnsupportedOperationException("findDocumentPath not supported.");
}
@@ -1048,13 +1049,19 @@
? DocumentsContract.getTreeDocumentId(documentUri)
: null;
- Path path = findDocumentPath(documentId, parentDocumentId);
+ Path path = findDocumentPath(parentDocumentId, documentId);
// Ensure provider doesn't leak information to unprivileged callers.
if (isTreeUri) {
if (!Objects.equals(path.getPath().get(0), parentDocumentId)) {
Log.wtf(TAG, "Provider doesn't return path from the tree root. Expected: "
+ parentDocumentId + " found: " + path.getPath().get(0));
+
+ LinkedList<String> docs = new LinkedList<>(path.getPath());
+ while (docs.size() > 1 && !Objects.equals(docs.getFirst(), parentDocumentId)) {
+ docs.removeFirst();
+ }
+ path = new Path(null, docs);
}
if (path.getRootId() != null) {
diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java
index 96dd76b..9f5d9d4 100644
--- a/core/java/android/provider/FontsContract.java
+++ b/core/java/android/provider/FontsContract.java
@@ -40,6 +40,7 @@
import com.android.internal.annotations.VisibleForTesting;
import java.io.FileNotFoundException;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -78,6 +79,37 @@
* {@link android.graphics.Typeface#BOLD_ITALIC}
*/
public static final String STYLE = "font_style";
+ /**
+ * Constant used to request data from a font provider. The cursor returned from the query
+ * should have this column populated to indicate the result status of the
+ * query. This will be checked before any other data in the cursor. Possible values are
+ * {@link #RESULT_CODE_OK}, {@link #RESULT_CODE_FONT_NOT_FOUND},
+ * {@link #RESULT_CODE_MALFORMED_QUERY} and {@link #RESULT_CODE_FONT_UNAVAILABLE}. If not
+ * present, {@link #RESULT_CODE_OK} will be assumed.
+ */
+ public static final String RESULT_CODE = "result_code";
+
+ /**
+ * Constant used to represent a result was retrieved successfully. The given fonts will be
+ * attempted to retrieve immediately via
+ * {@link android.content.ContentProvider#openFile(Uri, String)}. See {@link #RESULT_CODE}.
+ */
+ public static final int RESULT_CODE_OK = 0;
+ /**
+ * Constant used to represent a result was not found. See {@link #RESULT_CODE}.
+ */
+ public static final int RESULT_CODE_FONT_NOT_FOUND = 1;
+ /**
+ * Constant used to represent a result was found, but cannot be provided at this moment. Use
+ * this to indicate, for example, that a font needs to be fetched from the network. See
+ * {@link #RESULT_CODE}.
+ */
+ public static final int RESULT_CODE_FONT_UNAVAILABLE = 2;
+ /**
+ * Constant used to represent that the query was not in a supported format by the provider.
+ * See {@link #RESULT_CODE}.
+ */
+ public static final int RESULT_CODE_MALFORMED_QUERY = 3;
}
/**
@@ -87,12 +119,13 @@
*/
public static final String PARCEL_FONT_RESULTS = "font_results";
+ // Error codes internal to the system, which can not come from a provider. To keep the number
+ // space open for new provider codes, these should all be negative numbers.
/** @hide */
- public static final int RESULT_CODE_OK = 0;
+ public static final int RESULT_CODE_PROVIDER_NOT_FOUND = -1;
/** @hide */
- public static final int RESULT_CODE_FONT_NOT_FOUND = 1;
- /** @hide */
- public static final int RESULT_CODE_PROVIDER_NOT_FOUND = 2;
+ public static final int RESULT_CODE_WRONG_CERTIFICATES = -2;
+ // Note -3 is used by Typeface to indicate the font failed to load.
private static final int THREAD_RENEWAL_THRESHOLD_MS = 10000;
@@ -136,9 +169,7 @@
}
};
- /**
- * @hide
- */
+ /** @hide */
public void getFont(FontRequest request, ResultReceiver receiver) {
synchronized (mLock) {
if (mHandler == null) {
@@ -147,9 +178,8 @@
mHandler = new Handler(mThread.getLooper());
}
mHandler.post(() -> {
- ProviderInfo providerInfo = getProvider(request);
+ ProviderInfo providerInfo = getProvider(request, receiver);
if (providerInfo == null) {
- receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
return;
}
getFontFromProvider(request, receiver, providerInfo.authority);
@@ -161,17 +191,19 @@
/** @hide */
@VisibleForTesting
- public ProviderInfo getProvider(FontRequest request) {
+ public ProviderInfo getProvider(FontRequest request, ResultReceiver receiver) {
String providerAuthority = request.getProviderAuthority();
ProviderInfo info = mPackageManager.resolveContentProvider(providerAuthority, 0);
if (info == null) {
Log.e(TAG, "Can't find content provider " + providerAuthority);
+ receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
return null;
}
if (!info.packageName.equals(request.getProviderPackage())) {
Log.e(TAG, "Found content provider " + providerAuthority + ", but package was not "
+ request.getProviderPackage());
+ receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
return null;
}
// Trust system apps without signature checks
@@ -186,6 +218,7 @@
signatures = convertToSet(packageInfo.signatures);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "Can't find content provider " + providerAuthority, e);
+ receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
return null;
}
List<List<byte[]>> requestCertificatesList = request.getCertificates();
@@ -196,6 +229,7 @@
}
}
Log.e(TAG, "Certificates don't match for given provider " + providerAuthority);
+ receiver.send(RESULT_CODE_WRONG_CERTIFICATES, null);
return null;
}
@@ -222,17 +256,37 @@
.authority(authority)
.build();
try (Cursor cursor = mContext.getContentResolver().query(uri, new String[] { Columns._ID,
- Columns.TTC_INDEX, Columns.VARIATION_SETTINGS, Columns.STYLE },
+ Columns.TTC_INDEX, Columns.VARIATION_SETTINGS, Columns.STYLE,
+ Columns.RESULT_CODE },
"query = ?", new String[] { request.getQuery() }, null);) {
// TODO: Should we restrict the amount of fonts that can be returned?
// TODO: Write documentation explaining that all results should be from the same family.
if (cursor != null && cursor.getCount() > 0) {
+ final int resultCodeColumnIndex = cursor.getColumnIndex(Columns.RESULT_CODE);
+ int resultCode = -1;
result = new ArrayList<>();
- final int idColumnIndex = cursor.getColumnIndex(Columns._ID);
+ final int idColumnIndex = cursor.getColumnIndexOrThrow(Columns._ID);
final int ttcIndexColumnIndex = cursor.getColumnIndex(Columns.TTC_INDEX);
final int vsColumnIndex = cursor.getColumnIndex(Columns.VARIATION_SETTINGS);
final int styleColumnIndex = cursor.getColumnIndex(Columns.STYLE);
while (cursor.moveToNext()) {
+ resultCode = resultCodeColumnIndex != -1
+ ? cursor.getInt(resultCodeColumnIndex) : Columns.RESULT_CODE_OK;
+ if (resultCode != Columns.RESULT_CODE_OK) {
+ if (resultCode < 0) {
+ // Negative values are reserved for the internal errors.
+ resultCode = Columns.RESULT_CODE_FONT_NOT_FOUND;
+ }
+ for (int i = 0; i < result.size(); ++i) {
+ try {
+ result.get(i).getFileDescriptor().close();
+ } catch (IOException e) {
+ // Ignore, as we are closing fds for cleanup.
+ }
+ }
+ receiver.send(resultCode, null);
+ return;
+ }
long id = cursor.getLong(idColumnIndex);
Uri fileUri = ContentUris.withAppendedId(uri, id);
try {
@@ -255,9 +309,9 @@
if (result != null && !result.isEmpty()) {
Bundle bundle = new Bundle();
bundle.putParcelableArrayList(PARCEL_FONT_RESULTS, result);
- receiver.send(RESULT_CODE_OK, bundle);
+ receiver.send(Columns.RESULT_CODE_OK, bundle);
return;
}
- receiver.send(RESULT_CODE_FONT_NOT_FOUND, null);
+ receiver.send(Columns.RESULT_CODE_FONT_NOT_FOUND, null);
}
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e3a9d80..52aa1d5 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5128,11 +5128,11 @@
public static final String VOICE_INTERACTION_SERVICE = "voice_interaction_service";
/**
- * The currently selected auto-fill service flattened ComponentName.
+ * The currently selected autofill service flattened ComponentName.
* @hide
*/
@TestApi
- public static final String AUTO_FILL_SERVICE = "auto_fill_service";
+ public static final String AUTOFILL_SERVICE = "autofill_service";
/**
* bluetooth HCI snoop log configuration
@@ -6743,6 +6743,13 @@
public static final String ASSIST_GESTURE_ENABLED = "assist_gesture_enabled";
/**
+ * Sensitivity control for the assist gesture.
+ *
+ * @hide
+ */
+ public static final String ASSIST_GESTURE_SENSITIVITY = "assist_gesture_sensitivity";
+
+ /**
* Control whether Night display is currently activated.
* @hide
*/
@@ -7001,6 +7008,7 @@
NFC_PAYMENT_DEFAULT_COMPONENT,
AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
ASSIST_GESTURE_ENABLED,
+ ASSIST_GESTURE_SENSITIVITY,
VR_DISPLAY_MODE
};
diff --git a/core/java/android/service/autofill/AutoFillService.java b/core/java/android/service/autofill/AutoFillService.java
index 3c211eb..c26f679 100644
--- a/core/java/android/service/autofill/AutoFillService.java
+++ b/core/java/android/service/autofill/AutoFillService.java
@@ -15,236 +15,10 @@
*/
package android.service.autofill;
-import android.accessibilityservice.IAccessibilityServiceConnection;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Message;
-import android.os.RemoteException;
-import android.view.accessibility.AccessibilityInteractionClient;
-import com.android.internal.os.HandlerCaller;
-import android.annotation.SdkConstant;
-import android.app.Activity;
-import android.app.Service;
-import android.app.assist.AssistStructure;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.CancellationSignal;
-import android.os.IBinder;
-import android.os.ICancellationSignal;
-import android.os.Looper;
-import android.util.Log;
-
-import com.android.internal.os.SomeArgs;
-
-//TODO(b/33197203): improve javadoc (of both class and methods); in particular, make sure the
-//life-cycle (and how state could be maintained on server-side) is well documented.
-
/**
- * Top-level service of the current auto-fill service for a given user.
- *
- * <p>Apps providing auto-fill capabilities must extend this service.
+ * @hide
+ * @deprecated TODO(b/35956626): remove once clients use AutofillService
*/
-public abstract class AutoFillService extends Service {
- private static final String TAG = "AutoFillService";
-
- /**
- * The {@link Intent} that must be declared as handled by the service.
- * To be supported, the service must also require the
- * {@link android.Manifest.permission#BIND_AUTO_FILL} permission so
- * that other applications can not abuse it.
- */
- @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
- public static final String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
-
- /**
- * Name under which a AutoFillService component publishes information about itself.
- * This meta-data should reference an XML resource containing a
- * <code><{@link
- * android.R.styleable#AutoFillService autofill-service}></code> tag.
- * This is a a sample XML file configuring an AutoFillService:
- * <pre> <autofill-service
- * android:settingsActivity="foo.bar.SettingsActivity"
- * . . .
- * /></pre>
- */
- public static final String SERVICE_META_DATA = "android.autofill";
-
- // Internal extras
- /** @hide */
- public static final String EXTRA_ACTIVITY_TOKEN =
- "android.service.autofill.extra.ACTIVITY_TOKEN";
-
- // Handler messages.
- private static final int MSG_CONNECT = 1;
- private static final int MSG_DISCONNECT = 2;
- private static final int MSG_ON_FILL_REQUEST = 3;
- private static final int MSG_ON_SAVE_REQUEST = 4;
-
- private final IAutoFillService mInterface = new IAutoFillService.Stub() {
- @Override
- public void onInit(IAutoFillServiceConnection connection) {
- if (connection != null) {
- mHandlerCaller.obtainMessageO(MSG_CONNECT, connection).sendToTarget();
- } else {
- mHandlerCaller.obtainMessage(MSG_DISCONNECT).sendToTarget();
- }
- }
-
- @Override
- public void onFillRequest(AssistStructure structure, Bundle extras,
- IFillCallback callback) {
- ICancellationSignal transport = CancellationSignal.createTransport();
- try {
- callback.onCancellable(transport);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- mHandlerCaller.obtainMessageOOOO(MSG_ON_FILL_REQUEST, structure,
- CancellationSignal.fromTransport(transport), extras, callback)
- .sendToTarget();
- }
-
- @Override
- public void onSaveRequest(AssistStructure structure, Bundle extras,
- ISaveCallback callback) {
- mHandlerCaller.obtainMessageOOO(MSG_ON_SAVE_REQUEST, structure,
- extras, callback).sendToTarget();
- }
- };
-
- private final HandlerCaller.Callback mHandlerCallback = (msg) -> {
- switch (msg.what) {
- case MSG_CONNECT: {
- mConnection = (IAutoFillServiceConnection) msg.obj;
- onConnected();
- break;
- } case MSG_ON_FILL_REQUEST: {
- final SomeArgs args = (SomeArgs) msg.obj;
- final AssistStructure structure = (AssistStructure) args.arg1;
- final CancellationSignal cancellation = (CancellationSignal) args.arg2;
- final Bundle extras = (Bundle) args.arg3;
- final IFillCallback callback = (IFillCallback) args.arg4;
- final FillCallback fillCallback = new FillCallback(callback);
- args.recycle();
- onFillRequest(structure, extras, cancellation, fillCallback);
- break;
- } case MSG_ON_SAVE_REQUEST: {
- final SomeArgs args = (SomeArgs) msg.obj;
- final AssistStructure structure = (AssistStructure) args.arg1;
- final Bundle extras = (Bundle) args.arg2;
- final ISaveCallback callback = (ISaveCallback) args.arg3;
- final SaveCallback saveCallback = new SaveCallback(callback);
- args.recycle();
- onSaveRequest(structure, extras, saveCallback);
- break;
- } case MSG_DISCONNECT: {
- onDisconnected();
- mConnection = null;
- break;
- } default: {
- Log.w(TAG, "MyCallbacks received invalid message type: " + msg);
- }
- }
- };
-
- private HandlerCaller mHandlerCaller;
-
- private IAutoFillServiceConnection mConnection;
-
- /**
- * {@inheritDoc}
- *
- * <strong>NOTE: </strong>if overridden, it must call {@code super.onCreate()}.
- */
- @Override
- public void onCreate() {
- super.onCreate();
- mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(), mHandlerCallback, true);
- }
-
- @Override
- public final IBinder onBind(Intent intent) {
- if (SERVICE_INTERFACE.equals(intent.getAction())) {
- return mInterface.asBinder();
- }
- Log.w(TAG, "Tried to bind to wrong intent: " + intent);
- return null;
- }
-
- /**
- * Called when the Android system connects to service.
- *
- * <p>You should generally do initialization here rather than in {@link #onCreate}.
- */
- public void onConnected() {
- //TODO(b/33197203): is not called anymore, fix it!
- }
-
- /**
- * Called by the Android system do decide if an {@link Activity} can be auto-filled by the
- * service.
- *
- * <p>Service must call one of the {@link FillCallback} methods (like
- * {@link FillCallback#onSuccess(FillResponse)}
- * or {@link FillCallback#onFailure(CharSequence)})
- * to notify the result of the request.
- *
- * @param structure {@link Activity}'s view structure.
- * @param data bundle containing data passed by the service on previous calls to fill.
- * This bundle allows your service to keep state between fill and save requests
- * as well as when filling different sections of the UI as the system will try to
- * aggressively unbind from the service to conserve resources. See {@link
- * FillResponse} Javadoc for examples of multiple-sections requests.
- * @param cancellationSignal signal for observing cancellation requests. The system will use
- * this to notify you that the fill result is no longer needed and you should stop
- * handling this fill request in order to save resources.
- * @param callback object used to notify the result of the request.
- */
- public abstract void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
- @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback);
-
- /**
- * Called when user requests service to save the fields of an {@link Activity}.
- *
- * <p>Service must call one of the {@link SaveCallback} methods (like
- * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
- * to notify the result of the request.
- *
- * @param structure {@link Activity}'s view structure.
- * @param data bundle containing data passed by the service on previous calls to fill.
- * This bundle allows your service to keep state between fill and save requests
- * as well as when filling different sections of the UI as the system will try to
- * aggressively unbind from the service to conserve resources. See {@link
- * FillResponse} Javadoc for examples of multiple-sections requests.
- * @param callback object used to notify the result of the request.
- */
- public abstract void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
- @NonNull SaveCallback callback);
-
- /**
- * Called when the Android system disconnects from the service.
- *
- * <p> At this point this service may no longer be an active {@link AutoFillService}.
- */
- public void onDisconnected() {
- //TODO(b/33197203): is not called anymore, fix it!
- }
-
- /**
- * Disables the service. After calling this method, the service will
- * be disabled and settings will show that it is turned off.
- *
- * <p>You should call this method only after a call to {@link #onConnected()}
- * and before the corresponding call to {@link #onDisconnected()}. In other words
- * you can disable your service only while the system is connected to it.</p>
- */
- public final void disableSelf() {
- if (mConnection != null) {
- try {
- mConnection.disableSelf();
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
- }
- }
+@Deprecated
+public abstract class AutoFillService extends AutofillService {
}
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
new file mode 100644
index 0000000..29e2073
--- /dev/null
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -0,0 +1,261 @@
+/*
+ * 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.service.autofill;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.RemoteException;
+import com.android.internal.os.HandlerCaller;
+import android.annotation.SdkConstant;
+import android.app.Activity;
+import android.app.Service;
+import android.app.assist.AssistStructure;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.IBinder;
+import android.os.ICancellationSignal;
+import android.os.Looper;
+import android.util.Log;
+
+import com.android.internal.os.SomeArgs;
+
+//TODO(b/33197203): improve javadoc (of both class and methods); in particular, make sure the
+//life-cycle (and how state could be maintained on server-side) is well documented.
+
+/**
+ * Top-level service of the current autofill service for a given user.
+ *
+ * <p>Apps providing autofill capabilities must extend this service.
+ */
+public abstract class AutofillService extends Service {
+ private static final String TAG = "AutofillService";
+
+ /**
+ * The {@link Intent} that must be declared as handled by the service.
+ * To be supported, the service must also require the
+ * {@link android.Manifest.permission#BIND_AUTO_FILL} permission so
+ * that other applications can not abuse it.
+ *
+ * @hide
+ * @deprecated TODO(b/35956626): remove once clients use AutofillService
+ */
+ @Deprecated
+ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+ public static final String OLD_SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
+
+ /**
+ * The {@link Intent} that must be declared as handled by the service.
+ * To be supported, the service must also require the
+ * {@link android.Manifest.permission#BIND_AUTOFILL} permission so
+ * that other applications can not abuse it.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+ public static final String SERVICE_INTERFACE = "android.service.autofill.AutofillService";
+
+ /**
+ * Name under which a AutoFillService component publishes information about itself.
+ * This meta-data should reference an XML resource containing a
+ * <code><{@link
+ * android.R.styleable#AutoFillService autofill-service}></code> tag.
+ * This is a a sample XML file configuring an AutoFillService:
+ * <pre> <autofill-service
+ * android:settingsActivity="foo.bar.SettingsActivity"
+ * . . .
+ * /></pre>
+ */
+ public static final String SERVICE_META_DATA = "android.autofill";
+
+ // Internal extras
+ /** @hide */
+ public static final String EXTRA_ACTIVITY_TOKEN =
+ "android.service.autofill.extra.ACTIVITY_TOKEN";
+
+ // Handler messages.
+ private static final int MSG_CONNECT = 1;
+ private static final int MSG_DISCONNECT = 2;
+ private static final int MSG_ON_FILL_REQUEST = 3;
+ private static final int MSG_ON_SAVE_REQUEST = 4;
+
+ private final IAutoFillService mInterface = new IAutoFillService.Stub() {
+ @Override
+ public void onInit(IAutoFillServiceConnection connection) {
+ if (connection != null) {
+ mHandlerCaller.obtainMessageO(MSG_CONNECT, connection).sendToTarget();
+ } else {
+ mHandlerCaller.obtainMessage(MSG_DISCONNECT).sendToTarget();
+ }
+ }
+
+ @Override
+ public void onFillRequest(AssistStructure structure, Bundle extras,
+ IFillCallback callback) {
+ ICancellationSignal transport = CancellationSignal.createTransport();
+ try {
+ callback.onCancellable(transport);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ mHandlerCaller.obtainMessageOOOO(MSG_ON_FILL_REQUEST, structure,
+ CancellationSignal.fromTransport(transport), extras, callback)
+ .sendToTarget();
+ }
+
+ @Override
+ public void onSaveRequest(AssistStructure structure, Bundle extras,
+ ISaveCallback callback) {
+ mHandlerCaller.obtainMessageOOO(MSG_ON_SAVE_REQUEST, structure,
+ extras, callback).sendToTarget();
+ }
+ };
+
+ private final HandlerCaller.Callback mHandlerCallback = (msg) -> {
+ switch (msg.what) {
+ case MSG_CONNECT: {
+ mConnection = (IAutoFillServiceConnection) msg.obj;
+ onConnected();
+ break;
+ } case MSG_ON_FILL_REQUEST: {
+ final SomeArgs args = (SomeArgs) msg.obj;
+ final AssistStructure structure = (AssistStructure) args.arg1;
+ final CancellationSignal cancellation = (CancellationSignal) args.arg2;
+ final Bundle extras = (Bundle) args.arg3;
+ final IFillCallback callback = (IFillCallback) args.arg4;
+ final FillCallback fillCallback = new FillCallback(callback);
+ args.recycle();
+ onFillRequest(structure, extras, cancellation, fillCallback);
+ break;
+ } case MSG_ON_SAVE_REQUEST: {
+ final SomeArgs args = (SomeArgs) msg.obj;
+ final AssistStructure structure = (AssistStructure) args.arg1;
+ final Bundle extras = (Bundle) args.arg2;
+ final ISaveCallback callback = (ISaveCallback) args.arg3;
+ final SaveCallback saveCallback = new SaveCallback(callback);
+ args.recycle();
+ onSaveRequest(structure, extras, saveCallback);
+ break;
+ } case MSG_DISCONNECT: {
+ onDisconnected();
+ mConnection = null;
+ break;
+ } default: {
+ Log.w(TAG, "MyCallbacks received invalid message type: " + msg);
+ }
+ }
+ };
+
+ private HandlerCaller mHandlerCaller;
+
+ private IAutoFillServiceConnection mConnection;
+
+ /**
+ * {@inheritDoc}
+ *
+ * <strong>NOTE: </strong>if overridden, it must call {@code super.onCreate()}.
+ */
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(), mHandlerCallback, true);
+ }
+
+ @Override
+ public final IBinder onBind(Intent intent) {
+ if (SERVICE_INTERFACE.equals(intent.getAction())
+ || OLD_SERVICE_INTERFACE.equals(intent.getAction())) {
+ return mInterface.asBinder();
+ }
+ Log.w(TAG, "Tried to bind to wrong intent: " + intent);
+ return null;
+ }
+
+ /**
+ * Called when the Android system connects to service.
+ *
+ * <p>You should generally do initialization here rather than in {@link #onCreate}.
+ */
+ public void onConnected() {
+ //TODO(b/33197203): is not called anymore, fix it!
+ }
+
+ /**
+ * Called by the Android system do decide if an {@link Activity} can be autofilled by the
+ * service.
+ *
+ * <p>Service must call one of the {@link FillCallback} methods (like
+ * {@link FillCallback#onSuccess(FillResponse)}
+ * or {@link FillCallback#onFailure(CharSequence)})
+ * to notify the result of the request.
+ *
+ * @param structure {@link Activity}'s view structure.
+ * @param data bundle containing data passed by the service on previous calls to fill.
+ * This bundle allows your service to keep state between fill and save requests
+ * as well as when filling different sections of the UI as the system will try to
+ * aggressively unbind from the service to conserve resources. See {@link
+ * FillResponse} Javadoc for examples of multiple-sections requests.
+ * @param cancellationSignal signal for observing cancellation requests. The system will use
+ * this to notify you that the fill result is no longer needed and you should stop
+ * handling this fill request in order to save resources.
+ * @param callback object used to notify the result of the request.
+ */
+ public abstract void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
+ @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback);
+
+ /**
+ * Called when user requests service to save the fields of an {@link Activity}.
+ *
+ * <p>Service must call one of the {@link SaveCallback} methods (like
+ * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
+ * to notify the result of the request.
+ *
+ * @param structure {@link Activity}'s view structure.
+ * @param data bundle containing data passed by the service on previous calls to fill.
+ * This bundle allows your service to keep state between fill and save requests
+ * as well as when filling different sections of the UI as the system will try to
+ * aggressively unbind from the service to conserve resources. See {@link
+ * FillResponse} Javadoc for examples of multiple-sections requests.
+ * @param callback object used to notify the result of the request.
+ */
+ public abstract void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
+ @NonNull SaveCallback callback);
+
+ /**
+ * Called when the Android system disconnects from the service.
+ *
+ * <p> At this point this service may no longer be an active {@link AutofillService}.
+ */
+ public void onDisconnected() {
+ //TODO(b/33197203): is not called anymore, fix it!
+ }
+
+ /**
+ * Disables the service. After calling this method, the service will
+ * be disabled and settings will show that it is turned off.
+ *
+ * <p>You should call this method only after a call to {@link #onConnected()}
+ * and before the corresponding call to {@link #onDisconnected()}. In other words
+ * you can disable your service only while the system is connected to it.</p>
+ */
+ public final void disableSelf() {
+ if (mConnection != null) {
+ try {
+ mConnection.disableSelf();
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+ }
+}
diff --git a/core/java/android/service/autofill/AutoFillServiceInfo.java b/core/java/android/service/autofill/AutofillServiceInfo.java
similarity index 73%
rename from core/java/android/service/autofill/AutoFillServiceInfo.java
rename to core/java/android/service/autofill/AutofillServiceInfo.java
index 985e32f..d220052 100644
--- a/core/java/android/service/autofill/AutoFillServiceInfo.java
+++ b/core/java/android/service/autofill/AutofillServiceInfo.java
@@ -38,12 +38,12 @@
// TODO(b/33197203 , b/33802548): add CTS tests
/**
- * {@link ServiceInfo} and meta-data about an {@link AutoFillService}.
+ * {@link ServiceInfo} and meta-data about an {@link AutofillService}.
*
* @hide
*/
-public final class AutoFillServiceInfo {
- private static final String TAG = "AutoFillServiceInfo";
+public final class AutofillServiceInfo {
+ private static final String TAG = "AutofillServiceInfo";
private static ServiceInfo getServiceInfoOrThrow(ComponentName comp, int userHandle)
throws PackageManager.NameNotFoundException {
@@ -66,17 +66,26 @@
@Nullable
private final String mSettingsActivity;
- public AutoFillServiceInfo(PackageManager pm, ComponentName comp, int userHandle)
+ public AutofillServiceInfo(PackageManager pm, ComponentName comp, int userHandle)
throws PackageManager.NameNotFoundException {
this(pm, getServiceInfoOrThrow(comp, userHandle));
}
- public AutoFillServiceInfo(PackageManager pm, ServiceInfo si) {
+ public AutofillServiceInfo(PackageManager pm, ServiceInfo si) {
mServiceInfo = si;
final TypedArray metaDataArray = getMetaDataArray(pm, si);
if (metaDataArray != null) {
- mSettingsActivity =
- metaDataArray.getString(R.styleable.AutoFillService_settingsActivity);
+ // TODO(b/35956626): inline newSettingsActivity once clients migrate
+ final String newSettingsActivity =
+ metaDataArray.getString(R.styleable.AutofillService_settingsActivity);
+ System.out.println(">>> NEW CRAP MAN: " + newSettingsActivity); // TODO(felipeal): tmp
+ if (newSettingsActivity != null) {
+ mSettingsActivity = newSettingsActivity;
+ } else {
+ mSettingsActivity =
+ metaDataArray.getString(R.styleable.AutoFillService_settingsActivity);
+ }
+ System.out.println(">>> FINAL CRAP MAN: " + mSettingsActivity); // TODO(felipeal): tmp
metaDataArray.recycle();
} else {
mSettingsActivity = null;
@@ -89,13 +98,18 @@
@Nullable
private static TypedArray getMetaDataArray(PackageManager pm, ServiceInfo si) {
// Check for permissions.
- if (!Manifest.permission.BIND_AUTO_FILL.equals(si.permission)) {
- Log.e(TAG, "Service does not require permission " + Manifest.permission.BIND_AUTO_FILL);
+ // TODO(b/35956626): remove check for BIND_AUTO_FILL once clients migrate
+ if (!Manifest.permission.BIND_AUTOFILL.equals(si.permission)
+ && !Manifest.permission.BIND_AUTO_FILL.equals(si.permission)) {
+ Log.e(TAG, "Service does not require permission " + Manifest.permission.BIND_AUTOFILL);
return null;
}
+ // TODO(b/35956626): remove once clients migrate
+ final boolean oldStyle = !Manifest.permission.BIND_AUTOFILL.equals(si.permission);
+
// Get the AutoFill metadata, if declared.
- XmlResourceParser parser = si.loadXmlMetaData(pm, AutoFillService.SERVICE_META_DATA);
+ XmlResourceParser parser = si.loadXmlMetaData(pm, AutofillService.SERVICE_META_DATA);
if (parser == null) {
return null;
}
@@ -129,7 +143,8 @@
return null;
}
- return res.obtainAttributes(attrs, R.styleable.AutoFillService);
+ return oldStyle ? res.obtainAttributes(attrs, R.styleable.AutoFillService)
+ : res.obtainAttributes(attrs, R.styleable.AutofillService);
} finally {
parser.close();
}
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index d76d444..2461947 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -25,13 +25,15 @@
import android.os.Parcelable;
import android.view.autofill.AutoFillId;
import android.view.autofill.AutoFillValue;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
import android.widget.RemoteViews;
import com.android.internal.util.Preconditions;
import java.util.ArrayList;
/**
- * A set of data that can be used to auto-fill an {@link android.app.Activity}.
+ * A set of data that can be used to autofill an {@link android.app.Activity}.
*
* <p>It contains:
*
@@ -45,8 +47,8 @@
*/
public final class Dataset implements Parcelable {
- private final ArrayList<AutoFillId> mFieldIds;
- private final ArrayList<AutoFillValue> mFieldValues;
+ private final ArrayList<AutofillId> mFieldIds;
+ private final ArrayList<AutofillValue> mFieldValues;
private final RemoteViews mPresentation;
private final IntentSender mAuthentication;
@@ -58,12 +60,12 @@
}
/** @hide */
- public @Nullable ArrayList<AutoFillId> getFieldIds() {
+ public @Nullable ArrayList<AutofillId> getFieldIds() {
return mFieldIds;
}
/** @hide */
- public @Nullable ArrayList<AutoFillValue> getFieldValues() {
+ public @Nullable ArrayList<AutofillValue> getFieldValues() {
return mFieldValues;
}
@@ -99,8 +101,8 @@
* one value for a field or set an authentication intent.
*/
public static final class Builder {
- private ArrayList<AutoFillId> mFieldIds;
- private ArrayList<AutoFillValue> mFieldValues;
+ private ArrayList<AutofillId> mFieldIds;
+ private ArrayList<AutofillValue> mFieldValues;
private RemoteViews mPresentation;
private IntentSender mAuthentication;
private boolean mDestroyed;
@@ -116,7 +118,7 @@
}
/**
- * Requires a dataset authentication before auto-filling the activity with this dataset.
+ * Requires a dataset authentication before autofilling the activity with this dataset.
*
* <p>This method is called when you need to provide an authentication
* UI for the data set. For example, when a data set contains credit card information
@@ -131,13 +133,13 @@
* the items with these labels is chosen. Note that if you use sensitive data as
* a label, for example an email address, then it should also be encrypted.</p>
*
- * <p>When a user triggers auto-fill, the system launches the provided intent
+ * <p>When a user triggers autofill, the system launches the provided intent
* whose extras will have the {@link
- * android.view.autofill.AutoFillManager#EXTRA_ASSIST_STRUCTURE screen content}. Once
+ * android.view.autofill.AutofillManager#EXTRA_ASSIST_STRUCTURE screen content}. Once
* you complete your authentication flow you should set the activity result to {@link
* android.app.Activity#RESULT_OK} and provide the fully populated {@link Dataset
* dataset} by setting it to the {@link
- * android.view.autofill.AutoFillManager#EXTRA_AUTHENTICATION_RESULT} extra. For example,
+ * android.view.autofill.AutofillManager#EXTRA_AUTHENTICATION_RESULT} extra. For example,
* if you provided credit card information without the CVV for the data set in the
* {@link FillResponse response} then the returned data set should contain the
* CVV entry.</p>
@@ -158,14 +160,22 @@
}
/**
+ * @hide
+ * @deprecated TODO(b/35956626): remove once clients use other setValue()
+ */
+ @Deprecated
+ public @NonNull Builder setValue(@NonNull AutoFillId id, @NonNull AutoFillValue value) {
+ return setValue(id.getDaRealId(), value.getDaRealValue());
+ }
+ /**
* Sets the value of a field.
*
* @param id id returned by {@link
- * android.app.assist.AssistStructure.ViewNode#getAutoFillId()}.
+ * android.app.assist.AssistStructure.ViewNode#getAutofillId()}.
* @param value value to be auto filled.
* @return This builder.
*/
- public @NonNull Builder setValue(@NonNull AutoFillId id, @NonNull AutoFillValue value) {
+ public @NonNull Builder setValue(@NonNull AutofillId id, @NonNull AutofillValue value) {
throwIfDestroyed();
Preconditions.checkNotNull(id, "id cannot be null");
Preconditions.checkNotNull(value, "value cannot be null");
@@ -233,13 +243,13 @@
// the system obeys the contract of the builder to avoid attacks
// using specially crafted parcels.
final Builder builder = new Builder(parcel.readParcelable(null));
- final ArrayList<AutoFillId> ids = parcel.readTypedArrayList(null);
- final ArrayList<AutoFillValue> values = parcel.readTypedArrayList(null);
+ final ArrayList<AutofillId> ids = parcel.readTypedArrayList(null);
+ final ArrayList<AutofillValue> values = parcel.readTypedArrayList(null);
final int idCount = (ids != null) ? ids.size() : 0;
final int valueCount = (values != null) ? values.size() : 0;
for (int i = 0; i < idCount; i++) {
- AutoFillId id = ids.get(i);
- AutoFillValue value = (valueCount > i) ? values.get(i) : null;
+ final AutofillId id = ids.get(i);
+ final AutofillValue value = (valueCount > i) ? values.get(i) : null;
builder.setValue(id, value);
}
builder.setAuthentication(parcel.readParcelable(null));
diff --git a/core/java/android/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java
index 69c9904..00b206c 100644
--- a/core/java/android/service/autofill/FillCallback.java
+++ b/core/java/android/service/autofill/FillCallback.java
@@ -22,8 +22,8 @@
import android.os.RemoteException;
/**
- * Handles auto-fill requests from the {@link AutoFillService} into the {@link Activity} being
- * auto-filled.
+ * Handles autofill requests from the {@link AutofillService} into the {@link Activity} being
+ * autofilled.
*/
public final class FillCallback {
private final IFillCallback mCallback;
@@ -36,11 +36,11 @@
/**
* Notifies the Android System that an
- * {@link AutoFillService#onFillRequest(android.app.assist.AssistStructure, Bundle,
+ * {@link AutofillService#onFillRequest(android.app.assist.AssistStructure, Bundle,
* android.os.CancellationSignal, FillCallback)} was successfully fulfilled by the service.
*
- * @param response auto-fill information for that activity, or {@code null} when the activity
- * cannot be auto-filled (for example, if it only contains read-only fields). See
+ * @param response autofill information for that activity, or {@code null} when the activity
+ * cannot be autofilled (for example, if it only contains read-only fields). See
* {@link FillResponse} for examples.
*/
public void onSuccess(@Nullable FillResponse response) {
@@ -55,7 +55,7 @@
/**
* Notifies the Android System that an
- * {@link AutoFillService#onFillRequest(android.app.assist.AssistStructure,
+ * {@link AutofillService#onFillRequest(android.app.assist.AssistStructure,
* Bundle, android.os.CancellationSignal, FillCallback)}
* could not be fulfilled by the service.
*
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index c457c56..069e83c 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -23,19 +23,18 @@
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
-import android.view.autofill.AutoFillId;
-import android.view.autofill.AutoFillManager;
+import android.view.autofill.AutofillManager;
import android.widget.RemoteViews;
import java.util.ArrayList;
/**
* Response for a {@link
- * AutoFillService#onFillRequest(android.app.assist.AssistStructure,
+ * AutofillService#onFillRequest(android.app.assist.AssistStructure,
* Bundle, android.os.CancellationSignal, FillCallback)}.
*
* <p>The response typically contains one or more {@link Dataset}s, each representing a set of
- * fields that can be auto-filled together, and the Android system displays a dataset picker UI
+ * fields that can be autofilled together, and the Android system displays a dataset picker UI
* affordance that the user must use before the {@link android.app.Activity} is filled with
* the dataset.
*
@@ -125,7 +124,7 @@
* </pre>
*
* <p>Then after the user picks the second dataset and taps the street field to
- * trigger another auto-fill request, the second response could be:
+ * trigger another autofill request, the second response could be:
*
* <pre class="prettyprint">
* new FillResponse.Builder()
@@ -141,7 +140,7 @@
* </pre>
*
* <p>The service could require user authentication at the {@link FillResponse} or the
- * {@link Dataset} level, prior to auto-filling an activity - see
+ * {@link Dataset} level, prior to autofilling an activity - see
* {@link FillResponse.Builder#setAuthentication(IntentSender, RemoteViews)} and
* {@link Dataset.Builder#setAuthentication(IntentSender)}.
*
@@ -169,8 +168,6 @@
private FillResponse(@NonNull Builder builder) {
mDatasets = builder.mDatasets;
- // TODO(b/33197203, 35727295): this is how mSaveInfo will be set once we don't support
- // FillResponse.addSavableIds()
mSaveInfo = builder.mSaveInfo;
if (mSaveInfo != null) {
mSaveInfo.addSavableIds(mDatasets);
@@ -223,7 +220,7 @@
private boolean mDestroyed;
/**
- * Requires a fill response authentication before auto-filling the activity with
+ * Requires a fill response authentication before autofilling the activity with
* any data set in this response.
*
* <p>This is typically useful when a user interaction is required to unlock their
@@ -236,12 +233,12 @@
* intent you also need to specify the presentation view to be shown in the fill UI
* for the user to trigger your authentication flow.</p>
*
- * <p>When a user triggers auto-fill, the system launches the provided intent
- * whose extras will have the {@link AutoFillManager#EXTRA_ASSIST_STRUCTURE screen
+ * <p>When a user triggers autofill, the system launches the provided intent
+ * whose extras will have the {@link AutofillManager#EXTRA_ASSIST_STRUCTURE screen
* content}. Once you complete your authentication flow you should set the activity
* result to {@link android.app.Activity#RESULT_OK} and provide the fully populated
* {@link FillResponse response} by setting it to the {@link
- * AutoFillManager#EXTRA_AUTHENTICATION_RESULT} extra.
+ * AutofillManager#EXTRA_AUTHENTICATION_RESULT} extra.
* For example, if you provided an empty {@link FillResponse resppnse} because the
* user's data was locked and marked that the response needs an authentication then
* in the response returned if authentication succeeds you need to provide all
@@ -309,9 +306,9 @@
/**
* Sets a {@link Bundle} that will be passed to subsequent APIs that
* manipulate this response. For example, they are passed to subsequent
- * calls to {@link AutoFillService#onFillRequest(
+ * calls to {@link AutofillService#onFillRequest(
* android.app.assist.AssistStructure, Bundle, android.os.CancellationSignal,
- * FillCallback)} and {@link AutoFillService#onSaveRequest(
+ * FillCallback)} and {@link AutofillService#onSaveRequest(
* android.app.assist.AssistStructure, Bundle, SaveCallback)}.
*
* @param extras The response extras.
diff --git a/core/java/android/service/autofill/SaveCallback.java b/core/java/android/service/autofill/SaveCallback.java
index c6dd1df..2c4ba6c 100644
--- a/core/java/android/service/autofill/SaveCallback.java
+++ b/core/java/android/service/autofill/SaveCallback.java
@@ -21,8 +21,8 @@
import android.os.RemoteException;
/**
- * Handles save requests from the {@link AutoFillService} into the {@link Activity} being
- * auto-filled.
+ * Handles save requests from the {@link AutofillService} into the {@link Activity} being
+ * autofilled.
*/
public final class SaveCallback {
private final ISaveCallback mCallback;
@@ -35,7 +35,7 @@
/**
* Notifies the Android System that an
- * {@link AutoFillService#onSaveRequest (android.app.assist.AssistStructure, Bundle,
+ * {@link AutofillService#onSaveRequest (android.app.assist.AssistStructure, Bundle,
* SaveCallback)} was successfully fulfilled by the service.
*
* @throws RuntimeException if an error occurred while calling the Android System.
@@ -52,7 +52,7 @@
/**
* Notifies the Android System that an
- * {@link AutoFillService#onSaveRequest(android.app.assist.AssistStructure, Bundle,
+ * {@link AutofillService#onSaveRequest(android.app.assist.AssistStructure, Bundle,
* SaveCallback)} could not be fulfilled by the service.
*
* @param message error message to be displayed to the user.
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index a8f9aee..a8e3ff8 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -27,6 +27,7 @@
import android.os.Parcelable;
import android.util.ArraySet;
import android.view.autofill.AutoFillId;
+import android.view.autofill.AutofillId;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -39,12 +40,12 @@
* <p>A {@link SaveInfo} is always associated with a {@link FillResponse}.
*
* <p>A {@link SaveInfo} must define the type it represents, and contain at least one
- * {@code savableId}. A {@code savableId} is the {@link AutoFillId} of a view the service is
+ * {@code savableId}. A {@code savableId} is the {@link AutofillId} of a view the service is
* interested to save in a {@code onSaveRequest()}; the ids of all {@link Dataset} present in the
* {@link FillResponse} associated with this {@link SaveInfo} are already marked as savable,
- * but additional ids can be added through {@link Builder#addSavableIds(AutoFillId...)}.
+ * but additional ids can be added through {@link Builder#addSavableIds(AutofillId...)}.
*
- * <p>See {@link AutoFillService#onSaveRequest(android.app.assist.AssistStructure, Bundle,
+ * <p>See {@link AutofillService#onSaveRequest(android.app.assist.AssistStructure, Bundle,
* SaveCallback)} and {@link FillResponse} for more info.
*/
public final class SaveInfo implements Parcelable {
@@ -75,7 +76,7 @@
private final @SaveDataType int mType;
private CharSequence mNegativeActionTitle;
private IntentSender mNegativeActionListener;
- private ArraySet<AutoFillId> mSavableIds;
+ private ArraySet<AutofillId> mSavableIds;
private final CharSequence mDescription;
/** @hide */
@@ -108,7 +109,7 @@
}
/** @hide */
- public @Nullable ArraySet<AutoFillId> getSavableIds() {
+ public @Nullable ArraySet<AutofillId> getSavableIds() {
return mSavableIds;
}
@@ -126,11 +127,11 @@
public void addSavableIds(@Nullable ArrayList<Dataset> datasets) {
if (datasets != null) {
for (Dataset dataset : datasets) {
- final ArrayList<AutoFillId> ids = dataset.getFieldIds();
+ final ArrayList<AutofillId> ids = dataset.getFieldIds();
if (ids != null) {
final int fieldCount = ids.size();
for (int i = 0; i < fieldCount; i++) {
- final AutoFillId id = ids.get(i);
+ final AutofillId id = ids.get(i);
if (mSavableIds == null) {
mSavableIds = new ArraySet<>();
}
@@ -149,7 +150,7 @@
private final @SaveDataType int mType;
private CharSequence mNegativeActionTitle;
private IntentSender mNegativeActionListener;
- private ArraySet<AutoFillId> mSavableIds;
+ private ArraySet<AutofillId> mSavableIds;
private CharSequence mDescription;
private boolean mDestroyed;
@@ -182,13 +183,13 @@
*
* @see FillResponse
*/
- public @NonNull Builder addSavableIds(@Nullable AutoFillId... ids) {
+ public @NonNull Builder addSavableIds(@Nullable AutofillId... ids) {
throwIfDestroyed();
if (ids == null) {
return this;
}
- for (AutoFillId id : ids) {
+ for (AutofillId id : ids) {
if (mSavableIds == null) {
mSavableIds = new ArraySet<>();
}
@@ -302,7 +303,7 @@
// using specially crafted parcels.
final Builder builder = new Builder(parcel.readInt());
builder.setNegativeAction(parcel.readCharSequence(), parcel.readParcelable(null));
- final ArraySet<AutoFillId> savableIds = parcel.readTypedArraySet(null);
+ final ArraySet<AutofillId> savableIds = parcel.readTypedArraySet(null);
final int savableIdsCount = (savableIds != null) ? savableIds.size() : 0;
for (int i = 0; i < savableIdsCount; i++) {
builder.addSavableIds(savableIds.valueAt(i));
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index ac9c0d7..ee2b38e 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -474,6 +474,11 @@
return !isEmpty(a) ? a : Preconditions.checkStringNotEmpty(b);
}
+ /** {@hide} */
+ public static int length(@Nullable String s) {
+ return isEmpty(s) ? 0 : s.length();
+ }
+
/**
* Returns the length that the specified CharSequence would have if
* spaces and ASCII control characters were trimmed from the start and end,
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 77e9f0f..1b74c13 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -161,7 +161,7 @@
}
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
View root = null;
- if (accessibilityViewId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+ if (accessibilityViewId == AccessibilityNodeInfo.ROOT_ITEM_ID) {
root = mViewRootImpl.mView;
} else {
root = findViewByAccessibilityId(accessibilityViewId);
@@ -217,7 +217,7 @@
}
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
View root = null;
- if (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+ if (accessibilityViewId != AccessibilityNodeInfo.ROOT_ITEM_ID) {
root = findViewByAccessibilityId(accessibilityViewId);
} else {
root = mViewRootImpl.mView;
@@ -283,7 +283,7 @@
}
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
View root = null;
- if (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+ if (accessibilityViewId != AccessibilityNodeInfo.ROOT_ITEM_ID) {
root = findViewByAccessibilityId(accessibilityViewId);
} else {
root = mViewRootImpl.mView;
@@ -291,14 +291,9 @@
if (root != null && isShown(root)) {
AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider();
if (provider != null) {
- if (virtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
- infos = provider.findAccessibilityNodeInfosByText(text,
- virtualDescendantId);
- } else {
- infos = provider.findAccessibilityNodeInfosByText(text,
- AccessibilityNodeProvider.HOST_VIEW_ID);
- }
- } else if (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+ infos = provider.findAccessibilityNodeInfosByText(text,
+ virtualDescendantId);
+ } else if (virtualDescendantId == AccessibilityNodeProvider.HOST_VIEW_ID) {
ArrayList<View> foundViews = mTempArrayList;
foundViews.clear();
root.findViewsWithText(foundViews, text, View.FIND_VIEWS_WITH_TEXT
@@ -376,7 +371,7 @@
}
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
View root = null;
- if (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+ if (accessibilityViewId != AccessibilityNodeInfo.ROOT_ITEM_ID) {
root = findViewByAccessibilityId(accessibilityViewId);
} else {
root = mViewRootImpl.mView;
@@ -402,7 +397,7 @@
focused = AccessibilityNodeInfo.obtain(
mViewRootImpl.mAccessibilityFocusedVirtualView);
}
- } else if (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+ } else if (virtualDescendantId == AccessibilityNodeProvider.HOST_VIEW_ID) {
focused = host.createAccessibilityNodeInfo();
}
} break;
@@ -471,7 +466,7 @@
}
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
View root = null;
- if (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+ if (accessibilityViewId != AccessibilityNodeInfo.ROOT_ITEM_ID) {
root = findViewByAccessibilityId(accessibilityViewId);
} else {
root = mViewRootImpl.mView;
@@ -531,7 +526,7 @@
}
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
View target = null;
- if (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+ if (accessibilityViewId != AccessibilityNodeInfo.ROOT_ITEM_ID) {
target = findViewByAccessibilityId(accessibilityViewId);
} else {
target = mViewRootImpl.mView;
@@ -544,14 +539,9 @@
} else {
AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
if (provider != null) {
- if (virtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
- succeeded = provider.performAction(virtualDescendantId, action,
- arguments);
- } else {
- succeeded = provider.performAction(
- AccessibilityNodeProvider.HOST_VIEW_ID, action, arguments);
- }
- } else if (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+ succeeded = provider.performAction(virtualDescendantId, action,
+ arguments);
+ } else if (virtualDescendantId == AccessibilityNodeProvider.HOST_VIEW_ID) {
succeeded = target.performAccessibilityAction(action, arguments);
}
}
@@ -711,7 +701,9 @@
applyAppScaleAndMagnificationSpecIfNeeded(infos, spec);
adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
- infos.clear();
+ if (infos != null) {
+ infos.clear();
+ }
} catch (RemoteException re) {
/* ignore - the other side will time out */
} finally {
@@ -761,10 +753,8 @@
AccessibilityNodeInfo infoWithSpan = null;
AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider();
if (provider != null) {
- int idForNode = (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID)
- ? AccessibilityNodeProvider.HOST_VIEW_ID : virtualDescendantId;
- infoWithSpan = provider.createAccessibilityNodeInfo(idForNode);
- } else if (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+ infoWithSpan = provider.createAccessibilityNodeInfo(virtualDescendantId);
+ } else if (virtualDescendantId == AccessibilityNodeProvider.HOST_VIEW_ID) {
infoWithSpan = view.createAccessibilityNodeInfo();
}
if (infoWithSpan == null) {
@@ -817,13 +807,12 @@
}
}
} else {
- final int idForRoot = (virtualViewId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID)
- ? AccessibilityNodeProvider.HOST_VIEW_ID : virtualViewId;
- final AccessibilityNodeInfo root = provider.createAccessibilityNodeInfo(idForRoot);
+ final AccessibilityNodeInfo root =
+ provider.createAccessibilityNodeInfo(virtualViewId);
if (root != null) {
if (extraDataRequested != null) {
provider.addExtraDataToAccessibilityNodeInfo(
- idForRoot, root, extraDataRequested, arguments);
+ virtualViewId, root, extraDataRequested, arguments);
}
outInfos.add(root);
if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) {
@@ -1034,15 +1023,10 @@
}
final int virtualDescendantId =
AccessibilityNodeInfo.getVirtualDescendantId(parentNodeId);
- if (virtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID
+ if (virtualDescendantId != AccessibilityNodeProvider.HOST_VIEW_ID
|| accessibilityViewId == providerHost.getAccessibilityViewId()) {
final AccessibilityNodeInfo parent;
- if (virtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
- parent = provider.createAccessibilityNodeInfo(virtualDescendantId);
- } else {
- parent = provider.createAccessibilityNodeInfo(
- AccessibilityNodeProvider.HOST_VIEW_ID);
- }
+ parent = provider.createAccessibilityNodeInfo(virtualDescendantId);
if (parent == null) {
// Going up the parent relation we found a null predecessor,
// so remove these disconnected nodes form the result.
@@ -1072,15 +1056,10 @@
AccessibilityNodeInfo.getAccessibilityViewId(parentNodeId);
final int parentVirtualDescendantId =
AccessibilityNodeInfo.getVirtualDescendantId(parentNodeId);
- if (parentVirtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID
+ if (parentVirtualDescendantId != AccessibilityNodeProvider.HOST_VIEW_ID
|| parentAccessibilityViewId == providerHost.getAccessibilityViewId()) {
- final AccessibilityNodeInfo parent;
- if (parentVirtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
- parent = provider.createAccessibilityNodeInfo(parentVirtualDescendantId);
- } else {
- parent = provider.createAccessibilityNodeInfo(
- AccessibilityNodeProvider.HOST_VIEW_ID);
- }
+ final AccessibilityNodeInfo parent =
+ provider.createAccessibilityNodeInfo(parentVirtualDescendantId);
if (parent != null) {
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index ecd5e3b..8bb3fa9 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.content.res.CompatibilityInfo.Translator;
import android.graphics.Canvas;
+import android.graphics.GraphicBuffer;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
@@ -72,6 +73,7 @@
private static native int nativeSetScalingMode(long nativeObject, int scalingMode);
private static native void nativeSetBuffersTransform(long nativeObject, long transform);
private static native int nativeForceScopedDisconnect(long nativeObject);
+ private static native int nativeAttachAndQueueBuffer(long nativeObject, GraphicBuffer buffer);
public static final Parcelable.Creator<Surface> CREATOR =
new Parcelable.Creator<Surface>() {
@@ -562,6 +564,21 @@
}
/**
+ * Transfer ownership of buffer and present it on the Surface.
+ * @hide
+ */
+ public void attachAndQueueBuffer(GraphicBuffer buffer) {
+ synchronized (mLock) {
+ checkNotReleasedLocked();
+ int err = nativeAttachAndQueueBuffer(mNativeObject, buffer);
+ if (err != 0) {
+ throw new RuntimeException(
+ "Failed to attach and queue buffer to Surface (bad object?)");
+ }
+ }
+ }
+
+ /**
* Returns whether or not this Surface is backed by a single-buffered SurfaceTexture
* @hide
*/
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index b718696..519c1e2 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -95,6 +95,11 @@
IBinder displayToken, int mode);
private static native void nativeDeferTransactionUntil(long nativeObject,
IBinder handle, long frame);
+ private static native void nativeDeferTransactionUntilSurface(long nativeObject,
+ long surfaceObject, long frame);
+ private static native void nativeReparentChildren(long nativeObject,
+ IBinder handle);
+ private static native void nativeSeverChildren(long nativeObject);
private static native void nativeSetOverrideScalingMode(long nativeObject,
int scalingMode);
private static native IBinder nativeGetHandle(long nativeObject);
@@ -418,7 +423,23 @@
}
public void deferTransactionUntil(IBinder handle, long frame) {
- nativeDeferTransactionUntil(mNativeObject, handle, frame);
+ if (frame > 0) {
+ nativeDeferTransactionUntil(mNativeObject, handle, frame);
+ }
+ }
+
+ public void deferTransactionUntil(Surface barrier, long frame) {
+ if (frame > 0) {
+ nativeDeferTransactionUntilSurface(mNativeObject, barrier.mNativeObject, frame);
+ }
+ }
+
+ public void reparentChildren(IBinder newParentHandle) {
+ nativeReparentChildren(mNativeObject, newParentHandle);
+ }
+
+ public void detachChildren() {
+ nativeSeverChildren(mNativeObject);
}
public void setOverrideScalingMode(int scalingMode) {
diff --git a/core/java/android/view/SurfaceSession.java b/core/java/android/view/SurfaceSession.java
index 3cf5af4..b5912bc 100644
--- a/core/java/android/view/SurfaceSession.java
+++ b/core/java/android/view/SurfaceSession.java
@@ -27,6 +27,7 @@
private long mNativeClient; // SurfaceComposerClient*
private static native long nativeCreate();
+ private static native long nativeCreateScoped(long surfacePtr);
private static native void nativeDestroy(long ptr);
private static native void nativeKill(long ptr);
@@ -35,6 +36,10 @@
mNativeClient = nativeCreate();
}
+ public SurfaceSession(Surface root) {
+ mNativeClient = nativeCreateScoped(root.mNativeObject);
+ }
+
/* no user serviceable parts here ... */
@Override
protected void finalize() throws Throwable {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index d2577d4..61b1247 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -16,6 +16,10 @@
package android.view;
+import static android.view.WindowManagerPolicy.APPLICATION_MEDIA_SUBLAYER;
+import static android.view.WindowManagerPolicy.APPLICATION_MEDIA_OVERLAY_SUBLAYER;
+import static android.view.WindowManagerPolicy.APPLICATION_PANEL_SUBLAYER;
+
import android.content.Context;
import android.content.res.CompatibilityInfo.Translator;
import android.content.res.Configuration;
@@ -26,16 +30,12 @@
import android.graphics.Region;
import android.os.Handler;
import android.os.Message;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
-import com.android.internal.view.BaseIWindow;
import com.android.internal.view.SurfaceCallbackHelper;
-import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.concurrent.locks.ReentrantLock;
@@ -92,8 +92,8 @@
* positioned asynchronously.</p>
*/
public class SurfaceView extends View {
- static private final String TAG = "SurfaceView";
- static private final boolean DEBUG = false;
+ private static final String TAG = "SurfaceView";
+ private static final boolean DEBUG = false;
final ArrayList<SurfaceHolder.Callback> mCallbacks
= new ArrayList<SurfaceHolder.Callback>();
@@ -102,28 +102,23 @@
final ReentrantLock mSurfaceLock = new ReentrantLock();
final Surface mSurface = new Surface(); // Current surface in use
- final Surface mNewSurface = new Surface(); // New surface we are switching to
boolean mDrawingStopped = true;
+ // We use this to track if the application has produced a frame
+ // in to the Surface. Up until that point, we should be careful not to punch
+ // holes.
+ boolean mDrawFinished = false;
- final WindowManager.LayoutParams mLayout
- = new WindowManager.LayoutParams();
- IWindowSession mSession;
- MyWindow mWindow;
- final Rect mVisibleInsets = new Rect();
- final Rect mWinFrame = new Rect();
- final Rect mOverscanInsets = new Rect();
- final Rect mContentInsets = new Rect();
- final Rect mStableInsets = new Rect();
- final Rect mOutsets = new Rect();
- final Rect mBackdropFrame = new Rect();
+ final Rect mScreenRect = new Rect();
+ SurfaceSession mSurfaceSession;
+
+ SurfaceControl mSurfaceControl;
final Rect mTmpRect = new Rect();
final Configuration mConfiguration = new Configuration();
static final int KEEP_SCREEN_ON_MSG = 1;
- static final int GET_NEW_SURFACE_MSG = 2;
- static final int UPDATE_WINDOW_MSG = 3;
+ static final int DRAW_FINISHED_MSG = 2;
- int mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
+ int mSubLayer = APPLICATION_MEDIA_SUBLAYER;
boolean mIsCreating = false;
private volatile boolean mRtHandlingPositionUpdates = false;
@@ -135,11 +130,9 @@
case KEEP_SCREEN_ON_MSG: {
setKeepScreenOn(msg.arg1 != 0);
} break;
- case GET_NEW_SURFACE_MSG: {
- handleGetNewSurface();
- } break;
- case UPDATE_WINDOW_MSG: {
- updateWindow();
+ case DRAW_FINISHED_MSG: {
+ mDrawFinished = true;
+ invalidate();
} break;
}
}
@@ -149,7 +142,7 @@
= new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
- updateWindow();
+ updateSurface();
}
};
@@ -159,13 +152,14 @@
public boolean onPreDraw() {
// reposition ourselves where the surface is
mHaveFrame = getWidth() > 0 && getHeight() > 0;
- updateWindow();
+ updateSurface();
return true;
}
};
boolean mRequestedVisible = false;
boolean mWindowVisibility = false;
+ boolean mLastWindowVisibility = false;
boolean mViewVisibility = false;
int mRequestedWidth = -1;
int mRequestedHeight = -1;
@@ -181,19 +175,17 @@
boolean mVisible = false;
int mWindowSpaceLeft = -1;
int mWindowSpaceTop = -1;
- int mWindowSpaceWidth = -1;
- int mWindowSpaceHeight = -1;
+ int mSurfaceWidth = -1;
+ int mSurfaceHeight = -1;
int mFormat = -1;
final Rect mSurfaceFrame = new Rect();
int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;
- boolean mUpdateWindowNeeded;
- boolean mReportDrawNeeded;
private Translator mTranslator;
- private int mWindowInsetLeft;
- private int mWindowInsetTop;
private boolean mGlobalListenersAdded;
+ private int mSurfaceFlags = SurfaceControl.HIDDEN;
+
public SurfaceView(Context context) {
this(context, null);
}
@@ -227,11 +219,8 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mParent.requestTransparentRegion(this);
- mSession = getWindowSession();
- mLayout.token = getWindowToken();
- mLayout.setTitle("SurfaceView - " + getViewRootImpl().getTitle());
- mLayout.packageName = mContext.getOpPackageName();
mViewVisibility = getVisibility() == VISIBLE;
+ mRequestedVisible = mViewVisibility && mWindowVisibility;
if (!mGlobalListenersAdded) {
ViewTreeObserver observer = getViewTreeObserver();
@@ -246,7 +235,7 @@
super.onWindowVisibilityChanged(visibility);
mWindowVisibility = visibility == VISIBLE;
mRequestedVisible = mWindowVisibility && mViewVisibility;
- updateWindow();
+ updateSurface();
}
@Override
@@ -264,7 +253,7 @@
requestLayout();
}
mRequestedVisible = newRequestedVisible;
- updateWindow();
+ updateSurface();
}
@Override
@@ -277,19 +266,14 @@
}
mRequestedVisible = false;
- updateWindow();
- mHaveFrame = false;
- if (mWindow != null) {
- try {
- mSession.remove(mWindow);
- } catch (RemoteException ex) {
- // Not much we can do here...
- }
- mWindow = null;
- }
- mSession = null;
- mLayout.token = null;
+ updateSurface();
+ if (mSurfaceControl != null) {
+ mSurfaceControl.destroy();
+ }
+ mSurfaceControl = null;
+
+ mHaveFrame = false;
super.onDetachedFromWindow();
}
@@ -308,13 +292,13 @@
@Override
protected boolean setFrame(int left, int top, int right, int bottom) {
boolean result = super.setFrame(left, top, right, bottom);
- updateWindow();
+ updateSurface();
return result;
}
@Override
public boolean gatherTransparentRegion(Region region) {
- if (mWindowType == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
+ if (isAboveParent()) {
return super.gatherTransparentRegion(region);
}
@@ -341,7 +325,7 @@
@Override
public void draw(Canvas canvas) {
- if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
+ if (mDrawFinished && !isAboveParent()) {
// draw() is not called when SKIP_DRAW is set
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
// punch a whole in the view-hierarchy below us
@@ -353,8 +337,8 @@
@Override
protected void dispatchDraw(Canvas canvas) {
- if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
- // if SKIP_DRAW is cleared, draw() has already punched a hole
+ if (mDrawFinished && !isAboveParent()) {
+ // draw() is not called when SKIP_DRAW is set
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
// punch a whole in the view-hierarchy below us
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
@@ -375,9 +359,8 @@
* <p>Calling this overrides any previous call to {@link #setZOrderOnTop}.
*/
public void setZOrderMediaOverlay(boolean isMediaOverlay) {
- mWindowType = isMediaOverlay
- ? WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY
- : WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
+ mSubLayer = isMediaOverlay
+ ? APPLICATION_MEDIA_OVERLAY_SUBLAYER : APPLICATION_MEDIA_SUBLAYER;
}
/**
@@ -395,12 +378,9 @@
*/
public void setZOrderOnTop(boolean onTop) {
if (onTop) {
- mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
- // ensures the surface is placed below the IME
- mLayout.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+ mSubLayer = APPLICATION_PANEL_SUBLAYER;
} else {
- mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
- mLayout.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+ mSubLayer = APPLICATION_MEDIA_SUBLAYER;
}
}
@@ -418,31 +398,32 @@
*/
public void setSecure(boolean isSecure) {
if (isSecure) {
- mLayout.flags |= WindowManager.LayoutParams.FLAG_SECURE;
+ mSurfaceFlags |= SurfaceControl.SECURE;
} else {
- mLayout.flags &= ~WindowManager.LayoutParams.FLAG_SECURE;
+ mSurfaceFlags &= ~SurfaceControl.SECURE;
}
}
- /**
- * Hack to allow special layering of windows. The type is one of the
- * types in WindowManager.LayoutParams. This is a hack so:
- * @hide
- */
- public void setWindowType(int type) {
- mWindowType = type;
+ private Rect getParentSurfaceInsets() {
+ final ViewRootImpl root = getViewRootImpl();
+ if (root == null) {
+ return null;
+ } else {
+ return root.mWindowAttributes.surfaceInsets;
+ }
}
/** @hide */
- protected void updateWindow() {
+ protected void updateSurface() {
if (!mHaveFrame) {
return;
}
ViewRootImpl viewRoot = getViewRootImpl();
- if (viewRoot != null) {
- mTranslator = viewRoot.mTranslator;
+ if (viewRoot == null || viewRoot.mSurface == null || !viewRoot.mSurface.isValid()) {
+ return;
}
+ mTranslator = viewRoot.mTranslator;
if (mTranslator != null) {
mSurface.setCompatibilityTranslator(mTranslator);
}
@@ -452,17 +433,15 @@
int myHeight = mRequestedHeight;
if (myHeight <= 0) myHeight = getHeight();
- final boolean creating = mWindow == null;
final boolean formatChanged = mFormat != mRequestedFormat;
- final boolean sizeChanged = mWindowSpaceWidth != myWidth || mWindowSpaceHeight != myHeight;
+ final boolean creating = (mSurfaceControl == null || formatChanged)
+ && mRequestedVisible;
+ final boolean sizeChanged = mSurfaceWidth != myWidth || mSurfaceHeight != myHeight;
final boolean visibleChanged = mVisible != mRequestedVisible;
- final boolean layoutSizeChanged = getWidth() != mLayout.width
- || getHeight() != mLayout.height;
-
+ final boolean windowVisibleChanged = mWindowVisibility != mLastWindowVisibility;
boolean redrawNeeded = false;
- if (creating || formatChanged || sizeChanged || visibleChanged
- || mUpdateWindowNeeded || mReportDrawNeeded) {
+ if (creating || formatChanged || sizeChanged || visibleChanged || windowVisibleChanged) {
getLocationInWindow(mLocation);
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
@@ -476,93 +455,77 @@
final boolean visible = mVisible = mRequestedVisible;
mWindowSpaceLeft = mLocation[0];
mWindowSpaceTop = mLocation[1];
- mWindowSpaceWidth = myWidth;
- mWindowSpaceHeight = myHeight;
+ mSurfaceWidth = myWidth;
+ mSurfaceHeight = myHeight;
mFormat = mRequestedFormat;
+ mLastWindowVisibility = mWindowVisibility;
- // Scaling/Translate window's layout here because mLayout is not used elsewhere.
-
- // Places the window relative
- mLayout.x = mWindowSpaceLeft;
- mLayout.y = mWindowSpaceTop;
- mLayout.width = getWidth();
- mLayout.height = getHeight();
+ mScreenRect.left = mWindowSpaceLeft;
+ mScreenRect.top = mWindowSpaceTop;
+ mScreenRect.right = mWindowSpaceLeft + getWidth();
+ mScreenRect.bottom = mWindowSpaceTop + getHeight();
if (mTranslator != null) {
- mTranslator.translateLayoutParamsInAppWindowToScreen(mLayout);
+ mTranslator.translateRectInAppWindowToScreen(mScreenRect);
}
- mLayout.format = mRequestedFormat;
- mLayout.flags |=WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
- | WindowManager.LayoutParams.FLAG_SCALED
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
- ;
- if (!creating && !sizeChanged) {
- mLayout.privateFlags |=
- WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY;
- } else {
- mLayout.privateFlags &=
- ~WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY;
+ final Rect surfaceInsets = getParentSurfaceInsets();
+ mScreenRect.offset(surfaceInsets.left, surfaceInsets.top);
+
+ if (creating) {
+ mSurfaceSession = new SurfaceSession(viewRoot.mSurface);
+ mSurfaceControl = new SurfaceControl(mSurfaceSession,
+ "SurfaceView - " + viewRoot.getTitle().toString(),
+ mSurfaceWidth, mSurfaceHeight, mFormat,
+ mSurfaceFlags);
}
- if (!getContext().getResources().getCompatibilityInfo().supportsScreen()) {
- mLayout.privateFlags |=
- WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
- }
- mLayout.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION
- | WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
-
- if (mWindow == null) {
- Display display = getDisplay();
- mWindow = new MyWindow(this);
- mLayout.type = mWindowType;
- mLayout.gravity = Gravity.START|Gravity.TOP;
- mSession.addToDisplayWithoutInputChannel(mWindow, mWindow.mSeq, mLayout,
- mVisible ? VISIBLE : GONE, display.getDisplayId(), mContentInsets,
- mStableInsets);
- }
-
- boolean realSizeChanged;
- boolean reportDrawNeeded;
-
- int relayoutResult;
+ boolean realSizeChanged = false;
mSurfaceLock.lock();
try {
- mUpdateWindowNeeded = false;
- reportDrawNeeded = mReportDrawNeeded;
- mReportDrawNeeded = false;
mDrawingStopped = !visible;
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+ "Cur surface: " + mSurface);
- relayoutResult = mSession.relayout(
- mWindow, mWindow.mSeq, mLayout, mWindowSpaceWidth, mWindowSpaceHeight,
- visible ? VISIBLE : GONE,
- WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY,
- mWinFrame, mOverscanInsets, mContentInsets,
- mVisibleInsets, mStableInsets, mOutsets, mBackdropFrame,
- mConfiguration, mNewSurface);
- if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
- reportDrawNeeded = true;
+ SurfaceControl.openTransaction();
+ try {
+ mSurfaceControl.setLayer(mSubLayer);
+ if (mViewVisibility) {
+ mSurfaceControl.show();
+ } else {
+ mSurfaceControl.hide();
+ }
+
+ // While creating the surface, we will set it's initial
+ // geometry. Outside of that though, we should generally
+ // leave it to the RenderThread.
+ if (creating || !mRtHandlingPositionUpdates) {
+ mSurfaceControl.setPosition(mScreenRect.left, mScreenRect.top);
+ mSurfaceControl.setMatrix(mScreenRect.width() / (float) mSurfaceWidth,
+ 0.0f, 0.0f,
+ mScreenRect.height() / (float) mSurfaceHeight);
+ }
+ if (sizeChanged) {
+ mSurfaceControl.setSize(mSurfaceWidth, mSurfaceHeight);
+ }
+ } finally {
+ SurfaceControl.closeTransaction();
}
- if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
- + "New surface: " + mNewSurface
- + ", vis=" + visible + ", frame=" + mWinFrame);
+ if (sizeChanged || creating) {
+ redrawNeeded = true;
+ }
mSurfaceFrame.left = 0;
mSurfaceFrame.top = 0;
if (mTranslator == null) {
- mSurfaceFrame.right = mWinFrame.width();
- mSurfaceFrame.bottom = mWinFrame.height();
+ mSurfaceFrame.right = mSurfaceWidth;
+ mSurfaceFrame.bottom = mSurfaceHeight;
} else {
float appInvertedScale = mTranslator.applicationInvertedScale;
- mSurfaceFrame.right = (int) (mWinFrame.width() * appInvertedScale + 0.5f);
- mSurfaceFrame.bottom = (int) (mWinFrame.height() * appInvertedScale + 0.5f);
+ mSurfaceFrame.right = (int) (mSurfaceWidth * appInvertedScale + 0.5f);
+ mSurfaceFrame.bottom = (int) (mSurfaceHeight * appInvertedScale + 0.5f);
}
final int surfaceWidth = mSurfaceFrame.right;
@@ -576,12 +539,11 @@
}
try {
- redrawNeeded |= creating | reportDrawNeeded;
+ redrawNeeded |= visible && !mDrawFinished;
SurfaceHolder.Callback callbacks[] = null;
- final boolean surfaceChanged = (relayoutResult
- & WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED) != 0;
+ final boolean surfaceChanged = creating;
if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) {
mSurfaceCreated = false;
if (mSurface.isValid()) {
@@ -608,7 +570,10 @@
}
}
- mSurface.transferFrom(mNewSurface);
+ if (creating) {
+ mSurface.copyFrom(mSurfaceControl);
+ }
+
if (visible && mSurface.isValid()) {
if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) {
mSurfaceCreated = true;
@@ -641,53 +606,55 @@
callbacks = getSurfaceCallbacks();
}
SurfaceCallbackHelper sch =
- new SurfaceCallbackHelper(mSession, mWindow);
+ new SurfaceCallbackHelper(this::onDrawFinished);
sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
}
}
} finally {
mIsCreating = false;
- mSession.performDeferredDestroy(mWindow);
+ if (mSurfaceControl != null && !mSurfaceCreated) {
+ mSurfaceControl.destroy();
+ mSurfaceControl = null;
+ }
}
- } catch (RemoteException ex) {
+ } catch (Exception ex) {
Log.e(TAG, "Exception from relayout", ex);
}
if (DEBUG) Log.v(
- TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
- " w=" + mLayout.width + " h=" + mLayout.height +
- ", frame=" + mSurfaceFrame);
+ TAG, "Layout: x=" + mScreenRect.left + " y=" + mScreenRect.top
+ + " w=" + mScreenRect.width() + " h=" + mScreenRect.height()
+ + ", frame=" + mSurfaceFrame);
} else {
// Calculate the window position in case RT loses the window
// and we need to fallback to a UI-thread driven position update
- getLocationInWindow(mLocation);
+ getLocationInSurface(mLocation);
final boolean positionChanged = mWindowSpaceLeft != mLocation[0]
|| mWindowSpaceTop != mLocation[1];
+ final boolean layoutSizeChanged = getWidth() != mScreenRect.width()
+ || getHeight() != mScreenRect.height();
if (positionChanged || layoutSizeChanged) { // Only the position has changed
mWindowSpaceLeft = mLocation[0];
mWindowSpaceTop = mLocation[1];
- // For our size changed check, we keep mLayout.width and mLayout.height
+ // For our size changed check, we keep mScreenRect.width() and mScreenRect.height()
// in view local space.
- mLocation[0] = mLayout.width = getWidth();
- mLocation[1] = mLayout.height = getHeight();
+ mLocation[0] = getWidth();
+ mLocation[1] = getHeight();
- transformFromViewToWindowSpace(mLocation);
-
- mTmpRect.set(mWindowSpaceLeft, mWindowSpaceTop,
+ mScreenRect.set(mWindowSpaceLeft, mWindowSpaceTop,
mLocation[0], mLocation[1]);
if (mTranslator != null) {
- mTranslator.translateRectInAppWindowToScreen(mTmpRect);
+ mTranslator.translateRectInAppWindowToScreen(mScreenRect);
}
if (!isHardwareAccelerated() || !mRtHandlingPositionUpdates) {
try {
- if (DEBUG) Log.d(TAG, String.format("%d updateWindowPosition UI, " +
+ if (DEBUG) Log.d(TAG, String.format("%d updateSurfacePosition UI, " +
"postion = [%d, %d, %d, %d]", System.identityHashCode(this),
- mTmpRect.left, mTmpRect.top,
- mTmpRect.right, mTmpRect.bottom));
- mSession.repositionChild(mWindow, mTmpRect.left, mTmpRect.top,
- mTmpRect.right, mTmpRect.bottom, -1, mTmpRect);
- } catch (RemoteException ex) {
+ mScreenRect.left, mScreenRect.top,
+ mScreenRect.right, mScreenRect.bottom));
+ setParentSpaceRectangle(mScreenRect, -1);
+ } catch (Exception ex) {
Log.e(TAG, "Exception from relayout", ex);
}
}
@@ -695,20 +662,43 @@
}
}
+ private void onDrawFinished() {
+ if (DEBUG) {
+ Log.i(TAG, System.identityHashCode(this) + " "
+ + "finishedDrawing");
+ }
+ mHandler.sendEmptyMessage(DRAW_FINISHED_MSG);
+ }
+
+ private void setParentSpaceRectangle(Rect position, long frameNumber) {
+ ViewRootImpl viewRoot = getViewRootImpl();
+
+ SurfaceControl.openTransaction();
+ try {
+ if (frameNumber > 0) {
+ mSurfaceControl.deferTransactionUntil(viewRoot.mSurface, frameNumber);
+ }
+ mSurfaceControl.setPosition(position.left, position.top);
+ mSurfaceControl.setMatrix(position.width() / (float) mSurfaceWidth,
+ 0.0f, 0.0f,
+ position.height() / (float) mSurfaceHeight);
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+ }
+
private Rect mRTLastReportedPosition = new Rect();
/**
* Called by native by a Rendering Worker thread to update the window position
* @hide
*/
- public final void updateWindowPosition_renderWorker(long frameNumber,
+ public final void updateSurfacePosition_renderWorker(long frameNumber,
int left, int top, int right, int bottom) {
- IWindowSession session = mSession;
- MyWindow window = mWindow;
- if (session == null || window == null) {
- // Guess we got detached, that sucks
+ if (mSurfaceControl == null) {
return;
}
+
// TODO: This is teensy bit racey in that a brand new SurfaceView moving on
// its 2nd frame if RenderThread is running slowly could potentially see
// this as false, enter the branch, get pre-empted, then this comes along
@@ -726,35 +716,29 @@
}
try {
if (DEBUG) {
- Log.d(TAG, String.format("%d updateWindowPosition RenderWorker, frameNr = %d, " +
+ Log.d(TAG, String.format("%d updateSurfacePosition RenderWorker, frameNr = %d, " +
"postion = [%d, %d, %d, %d]", System.identityHashCode(this),
frameNumber, left, top, right, bottom));
}
- // Just using mRTLastReportedPosition as a dummy rect here
- session.repositionChild(window, left, top, right, bottom,
- frameNumber,
- mRTLastReportedPosition);
- // Now overwrite mRTLastReportedPosition with our values
mRTLastReportedPosition.set(left, top, right, bottom);
- } catch (RemoteException ex) {
+ setParentSpaceRectangle(mRTLastReportedPosition, frameNumber);
+ // Now overwrite mRTLastReportedPosition with our values
+ } catch (Exception ex) {
Log.e(TAG, "Exception from repositionChild", ex);
}
}
/**
- * Called by native on RenderThread to notify that the window is no longer in the
+ * Called by native on RenderThread to notify that the view is no longer in the
* draw tree. UI thread is blocked at this point.
* @hide
*/
- public final void windowPositionLost_uiRtSync(long frameNumber) {
+ public final void surfacePositionLost_uiRtSync(long frameNumber) {
if (DEBUG) {
Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d",
System.identityHashCode(this), frameNumber));
}
- IWindowSession session = mSession;
- MyWindow window = mWindow;
- if (session == null || window == null) {
- // We got detached prior to receiving this, abort
+ if (mSurfaceControl == null) {
return;
}
if (mRtHandlingPositionUpdates) {
@@ -763,19 +747,14 @@
// safely access other member variables at this time.
// So do what the UI thread would have done if RT wasn't handling position
// updates.
- mTmpRect.set(mLayout.x, mLayout.y,
- mLayout.x + mLayout.width,
- mLayout.y + mLayout.height);
-
- if (!mTmpRect.isEmpty() && !mTmpRect.equals(mRTLastReportedPosition)) {
+ if (!mScreenRect.isEmpty() && !mScreenRect.equals(mRTLastReportedPosition)) {
try {
- if (DEBUG) Log.d(TAG, String.format("%d updateWindowPosition, " +
+ if (DEBUG) Log.d(TAG, String.format("%d updateSurfacePosition, " +
"postion = [%d, %d, %d, %d]", System.identityHashCode(this),
- mTmpRect.left, mTmpRect.top,
- mTmpRect.right, mTmpRect.bottom));
- session.repositionChild(window, mTmpRect.left, mTmpRect.top,
- mTmpRect.right, mTmpRect.bottom, frameNumber, mWinFrame);
- } catch (RemoteException ex) {
+ mScreenRect.left, mScreenRect.top,
+ mScreenRect.right, mScreenRect.bottom));
+ setParentSpaceRectangle(mScreenRect, frameNumber);
+ } catch (Exception ex) {
Log.e(TAG, "Exception from relayout", ex);
}
}
@@ -792,10 +771,6 @@
return callbacks;
}
- void handleGetNewSurface() {
- updateWindow();
- }
-
/**
* Check to see if the surface has fixed size dimensions or if the surface's
* dimensions are dimensions are dependent on its current layout.
@@ -807,65 +782,8 @@
return (mRequestedWidth != -1 || mRequestedHeight != -1);
}
- private static class MyWindow extends BaseIWindow {
- private final WeakReference<SurfaceView> mSurfaceView;
-
- public MyWindow(SurfaceView surfaceView) {
- mSurfaceView = new WeakReference<SurfaceView>(surfaceView);
- }
-
- @Override
- public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
- Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
- Configuration newConfig, Rect backDropRect, boolean forceLayout,
- boolean alwaysConsumeNavBar, int displayId) {
- SurfaceView surfaceView = mSurfaceView.get();
- if (surfaceView != null) {
- if (DEBUG) Log.v(TAG, surfaceView + " got resized: w=" + frame.width()
- + " h=" + frame.height() + ", cur w=" + mCurWidth + " h=" + mCurHeight);
- surfaceView.mSurfaceLock.lock();
- try {
- if (reportDraw) {
- surfaceView.mUpdateWindowNeeded = true;
- surfaceView.mReportDrawNeeded = true;
- surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG);
- } else if (surfaceView.mWinFrame.width() != frame.width()
- || surfaceView.mWinFrame.height() != frame.height()
- || forceLayout) {
- surfaceView.mUpdateWindowNeeded = true;
- surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG);
- }
- } finally {
- surfaceView.mSurfaceLock.unlock();
- }
- }
- }
-
- @Override
- public void dispatchAppVisibility(boolean visible) {
- // The point of SurfaceView is to let the app control the surface.
- }
-
- @Override
- public void dispatchGetNewSurface() {
- SurfaceView surfaceView = mSurfaceView.get();
- if (surfaceView != null) {
- Message msg = surfaceView.mHandler.obtainMessage(GET_NEW_SURFACE_MSG);
- surfaceView.mHandler.sendMessage(msg);
- }
- }
-
- @Override
- public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
- Log.w("SurfaceView", "Unexpected focus in surface: focus=" + hasFocus + ", touchEnabled=" + touchEnabled);
- }
-
- @Override
- public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
- }
-
- int mCurWidth = -1;
- int mCurHeight = -1;
+ private boolean isAboveParent() {
+ return mSubLayer >= 0;
}
private final SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
@@ -913,15 +831,14 @@
@Override
public void setFormat(int format) {
-
// for backward compatibility reason, OPAQUE always
// means 565 for SurfaceView
if (format == PixelFormat.OPAQUE)
format = PixelFormat.RGB_565;
mRequestedFormat = format;
- if (mWindow != null) {
- updateWindow();
+ if (mSurfaceControl != null) {
+ updateSurface();
}
}
@@ -982,10 +899,10 @@
mSurfaceLock.lock();
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Locking canvas... stopped="
- + mDrawingStopped + ", win=" + mWindow);
+ + mDrawingStopped + ", surfaceControl=" + mSurfaceControl);
Canvas c = null;
- if (!mDrawingStopped && mWindow != null) {
+ if (!mDrawingStopped && mSurfaceControl != null) {
try {
if (hardware) {
c = mSurface.lockHardwareCanvas();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 8cfd6a7..aa1cbf2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -94,12 +94,12 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.view.accessibility.AccessibilityNodeProvider;
+import android.view.accessibility.AccessibilityWindowInfo;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Transformation;
-import android.view.autofill.AutoFillManager;
-import android.view.autofill.AutoFillType;
-import android.view.autofill.AutoFillValue;
+import android.view.autofill.AutofillManager;
+import android.view.autofill.AutofillValue;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
@@ -945,175 +945,175 @@
/** @hide */
@IntDef({
- AUTO_FILL_MODE_INHERIT,
- AUTO_FILL_MODE_AUTO,
- AUTO_FILL_MODE_MANUAL
+ AUTOFILL_MODE_INHERIT,
+ AUTOFILL_MODE_AUTO,
+ AUTOFILL_MODE_MANUAL
})
@Retention(RetentionPolicy.SOURCE)
- public @interface AutoFillMode {}
+ public @interface AutofillMode {}
/**
- * This view inherits the auto-fill state from it's parent. If there is no parent it is
- * {@link #AUTO_FILL_MODE_AUTO}.
- * Use with {@link #setAutoFillMode(int)} and <a href="#attr_android:autoFillMode">
- * {@code android:autoFillMode}.
+ * This view inherits the autofill state from it's parent. If there is no parent it is
+ * {@link #AUTOFILL_MODE_AUTO}.
+ * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode">
+ * {@code android:autofillMode}.
*/
- public static final int AUTO_FILL_MODE_INHERIT = 0;
+ public static final int AUTOFILL_MODE_INHERIT = 0;
/**
- * Allows this view to automatically trigger an auto-fill request when it get focus.
- * Use with {@link #setAutoFillMode(int)} and <a href="#attr_android:autoFillMode">
- * {@code android:autoFillMode}.
+ * Allows this view to automatically trigger an autofill request when it get focus.
+ * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode">
+ * {@code android:autofillMode}.
*/
- public static final int AUTO_FILL_MODE_AUTO = 1;
+ public static final int AUTOFILL_MODE_AUTO = 1;
/**
- * Do not trigger an auto-fill request if this view is focused. The user can still force
- * an auto-fill request.
- * <p>This does not prevent this field from being auto-filled if an auto-fill operation is
+ * Do not trigger an autofill request if this view is focused. The user can still force
+ * an autofill request.
+ * <p>This does not prevent this field from being autofilled if an autofill operation is
* triggered from a different view.</p>
*
- * Use with {@link #setAutoFillMode(int)} and <a href="#attr_android:autoFillMode">{@code
- * android:autoFillMode}.
+ * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode">{@code
+ * android:autofillMode}.
*/
- public static final int AUTO_FILL_MODE_MANUAL = 2;
+ public static final int AUTOFILL_MODE_MANUAL = 2;
/** @hide */
@IntDef({
- AUTO_FILL_HINT_NONE,
- AUTO_FILL_HINT_EMAIL_ADDRESS,
- AUTO_FILL_HINT_NAME,
- AUTO_FILL_HINT_POSTAL_ADDRESS,
- AUTO_FILL_HINT_PASSWORD,
- AUTO_FILL_HINT_PHONE,
- AUTO_FILL_HINT_USERNAME,
- AUTO_FILL_HINT_POSTAL_CODE,
- AUTO_FILL_HINT_CREDIT_CARD_NUMBER,
- AUTO_FILL_HINT_CREDIT_CARD_SECURITY_CODE,
- AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DATE,
- AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_MONTH,
- AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_YEAR,
- AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DAY,
+ AUTOFILL_HINT_NONE,
+ AUTOFILL_HINT_EMAIL_ADDRESS,
+ AUTOFILL_HINT_NAME,
+ AUTOFILL_HINT_POSTAL_ADDRESS,
+ AUTOFILL_HINT_PASSWORD,
+ AUTOFILL_HINT_PHONE,
+ AUTOFILL_HINT_USERNAME,
+ AUTOFILL_HINT_POSTAL_CODE,
+ AUTOFILL_HINT_CREDIT_CARD_NUMBER,
+ AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE,
+ AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE,
+ AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH,
+ AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR,
+ AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY,
})
@Retention(RetentionPolicy.SOURCE)
- public @interface AutoFillHint {}
+ public @interface AutofillHint {}
/**
- * No auto-fill hint is set.
+ * No autofill hint is set.
*
- * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
- * {@code android:autoFillHint}.
+ * Use with {@link #setAutofillHint(int)} and <a href="#attr_android:autofillHint">
+ * {@code android:autofillHint}.
*/
- public static final int AUTO_FILL_HINT_NONE = 0;
+ public static final int AUTOFILL_HINT_NONE = 0;
/**
* This view contains an email address.
*
- * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
- * {@code android:autoFillHint}.
+ * Use with {@link #setAutofillHint(int)} and <a href="#attr_android:autofillHint">
+ * {@code android:autofillHint}.
*/
- public static final int AUTO_FILL_HINT_EMAIL_ADDRESS = 0x1;
+ public static final int AUTOFILL_HINT_EMAIL_ADDRESS = 0x1;
/**
* The view contains a real name.
*
- * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
- * {@code android:autoFillHint}.
+ * Use with {@link #setAutofillHint(int)} and <a href="#attr_android:autofillHint">
+ * {@code android:autofillHint}.
*/
- public static final int AUTO_FILL_HINT_NAME = 0x2;
+ public static final int AUTOFILL_HINT_NAME = 0x2;
/**
* The view contains a user name.
*
- * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
- * {@code android:autoFillHint}.
+ * Use with {@link #setAutofillHint(int)} and <a href="#attr_android:autofillHint">
+ * {@code android:autofillHint}.
*/
- public static final int AUTO_FILL_HINT_USERNAME = 0x4;
+ public static final int AUTOFILL_HINT_USERNAME = 0x4;
/**
* The view contains a password.
*
- * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
- * {@code android:autoFillHint}.
+ * Use with {@link #setAutofillHint(int)} and <a href="#attr_android:autofillHint">
+ * {@code android:autofillHint}.
*/
- public static final int AUTO_FILL_HINT_PASSWORD = 0x8;
+ public static final int AUTOFILL_HINT_PASSWORD = 0x8;
/**
* The view contains a phone number.
*
- * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
- * {@code android:autoFillHint}.
+ * Use with {@link #setAutofillHint(int)} and <a href="#attr_android:autofillHint">
+ * {@code android:autofillHint}.
*/
- public static final int AUTO_FILL_HINT_PHONE = 0x10;
+ public static final int AUTOFILL_HINT_PHONE = 0x10;
/**
* The view contains a postal address.
*
- * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
- * {@code android:autoFillHint}.
+ * Use with {@link #setAutofillHint(int)} and <a href="#attr_android:autofillHint">
+ * {@code android:autofillHint}.
*/
- public static final int AUTO_FILL_HINT_POSTAL_ADDRESS = 0x20;
+ public static final int AUTOFILL_HINT_POSTAL_ADDRESS = 0x20;
/**
* The view contains a postal code.
*
- * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
- * {@code android:autoFillHint}.
+ * Use with {@link #setAutofillHint(int)} and <a href="#attr_android:autofillHint">
+ * {@code android:autofillHint}.
*/
- public static final int AUTO_FILL_HINT_POSTAL_CODE = 0x40;
+ public static final int AUTOFILL_HINT_POSTAL_CODE = 0x40;
/**
* The view contains a credit card number.
*
- * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
- * {@code android:autoFillHint}.
+ * Use with {@link #setAutofillHint(int)} and <a href="#attr_android:autofillHint">
+ * {@code android:autofillHint}.
*/
- public static final int AUTO_FILL_HINT_CREDIT_CARD_NUMBER = 0x80;
+ public static final int AUTOFILL_HINT_CREDIT_CARD_NUMBER = 0x80;
/**
* The view contains a credit card security code.
*
- * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
- * {@code android:autoFillHint}.
+ * Use with {@link #setAutofillHint(int)} and <a href="#attr_android:autofillHint">
+ * {@code android:autofillHint}.
*/
- public static final int AUTO_FILL_HINT_CREDIT_CARD_SECURITY_CODE = 0x100;
+ public static final int AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = 0x100;
/**
* The view contains a credit card expiration date.
*
- * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
- * {@code android:autoFillHint}.
+ * Use with {@link #setAutofillHint(int)} and <a href="#attr_android:autofillHint">
+ * {@code android:autofillHint}.
*/
- public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DATE = 0x200;
+ public static final int AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE = 0x200;
/**
* The view contains the month a credit card expires.
*
- * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
- * {@code android:autoFillHint}.
+ * Use with {@link #setAutofillHint(int)} and <a href="#attr_android:autofillHint">
+ * {@code android:autofillHint}.
*/
- public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = 0x400;
+ public static final int AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = 0x400;
/**
* The view contains the year a credit card expires.
*
- * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
- * {@code android:autoFillHint}.
+ * Use with {@link #setAutofillHint(int)} and <a href="#attr_android:autofillHint">
+ * {@code android:autofillHint}.
*/
- public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_YEAR = 0x800;
+ public static final int AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR = 0x800;
/**
* The view contains the day a credit card expires.
*
- * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
- * {@code android:autoFillHint}.
+ * Use with {@link #setAutofillHint(int)} and <a href="#attr_android:autofillHint">
+ * {@code android:autofillHint}.
*/
- public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DAY = 0x1000;
+ public static final int AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = 0x1000;
/**
- * Hint for the auto-fill services that describes the content of the view.
+ * Hint for the autofill services that describes the content of the view.
*/
- @AutoFillHint private int mAutoFillHint;
+ @AutofillHint private int mAutofillHint;
/** @hide */
@IntDef({
@@ -1134,18 +1134,18 @@
/**
* Autofill type for a text field, which is filled by a {@link CharSequence}.
*
- * <p>{@link AutoFillValue} instances for autofilling a {@link View} can be obtained through
- * {@link AutoFillValue#forText(CharSequence)}, and the value passed to auto-fill a
- * {@link View} can be fetched through {@link AutoFillValue#getTextValue()}.
+ * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
+ * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
+ * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
*/
public static final int AUTOFILL_TYPE_TEXT = 1;
/**
* Autofill type for a togglable field, which is filled by a {@code boolean}.
*
- * <p>{@link AutoFillValue} instances for auto-filling a {@link View} can be obtained through
- * {@link AutoFillValue#forToggle(boolean)}, and the value passed to auto-fill a
- * {@link View} can be fetched through {@link AutoFillValue#getToggleValue()}.
+ * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
+ * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
+ * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
*/
public static final int AUTOFILL_TYPE_TOGGLE = 2;
@@ -1153,12 +1153,12 @@
* Autofill type for a selection list field, which is filled by an {@code int}
* representing the element index inside the list (starting at {@code 0}).
*
- * <p>{@link AutoFillValue} instances for autofilling a {@link View} can be obtained through
- * {@link AutoFillValue#forList(int)}, and the value passed to auto-fill a
- * {@link View} can be fetched through {@link AutoFillValue#getListValue()}.
+ * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
+ * {@link AutofillValue#forList(int)}, and the value passed to autofill a
+ * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
*
* <p>The available options in the selection list are typically provided by
- * {@link android.app.assist.AssistStructure.ViewNode#getAutoFillOptions()}.
+ * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
*/
public static final int AUTOFILL_TYPE_LIST = 3;
@@ -1168,9 +1168,9 @@
* the number of milliseconds since the standard base time known as "the epoch", namely
* January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
*
- * <p>{@link AutoFillValue} instances for autofilling a {@link View} can be obtained through
- * {@link AutoFillValue#forDate(long)}, and the values passed to
- * auto-fill a {@link View} can be fetched through {@link AutoFillValue#getDateValue()}.
+ * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
+ * {@link AutofillValue#forDate(long)}, and the values passed to
+ * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
*/
public static final int AUTOFILL_TYPE_DATE = 4;
@@ -2768,8 +2768,13 @@
* 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
@@ -2990,21 +2995,21 @@
private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
/**
- * Shift for the place where the auto-fill mode is stored in the pflags
+ * Shift for the place where the autofill mode is stored in the pflags
*
- * @see #getAutoFillMode()
- * @see #setAutoFillMode(int)
+ * @see #getAutofillMode()
+ * @see #setAutofillMode(int)
*/
- private static final int PFLAG3_AUTO_FILL_MODE_SHIFT = 19;
+ private static final int PFLAG3_AUTOFILL_MODE_SHIFT = 19;
/**
- * Mask for auto-fill modes
+ * Mask for autofill modes
*
- * @see #getAutoFillMode()
- * @see #setAutoFillMode(int)
+ * @see #getAutofillMode()
+ * @see #setAutofillMode(int)
*/
- private static final int PFLAG3_AUTO_FILL_MODE_MASK = (AUTO_FILL_MODE_INHERIT
- | AUTO_FILL_MODE_AUTO | AUTO_FILL_MODE_MANUAL) << PFLAG3_AUTO_FILL_MODE_SHIFT;
+ private static final int PFLAG3_AUTOFILL_MODE_MASK = (AUTOFILL_MODE_INHERIT
+ | AUTOFILL_MODE_AUTO | AUTOFILL_MODE_MANUAL) << PFLAG3_AUTOFILL_MODE_SHIFT;
/**
* Shift for the bits in {@link #mPrivateFlags3} related to the
@@ -5037,14 +5042,14 @@
setFocusedByDefault(a.getBoolean(attr, true));
}
break;
- case R.styleable.View_autoFillMode:
+ case R.styleable.View_autofillMode:
if (a.peekValue(attr) != null) {
- setAutoFillMode(a.getInt(attr, AUTO_FILL_MODE_INHERIT));
+ setAutofillMode(a.getInt(attr, AUTOFILL_MODE_INHERIT));
}
break;
- case R.styleable.View_autoFillHint:
+ case R.styleable.View_autofillHint:
if (a.peekValue(attr) != null) {
- setAutoFillHint(a.getInt(attr, AUTO_FILL_HINT_NONE));
+ setAutofillHint(a.getInt(attr, AUTOFILL_HINT_NONE));
}
break;
case R.styleable.View_importantForAutofill:
@@ -6786,14 +6791,14 @@
mAttachInfo.mKeyDispatchState.reset(this);
}
- if (isAutoFillable() && isAttachedToWindow()
- && getResolvedAutoFillMode() == AUTO_FILL_MODE_AUTO) {
- AutoFillManager afm = getAutoFillManager();
+ if (isAutofillable() && isAttachedToWindow()
+ && getResolvedAutofillMode() == AUTOFILL_MODE_AUTO) {
+ AutofillManager afm = getAutofillManager();
if (afm != null) {
if (gainFocus) {
- afm.startAutoFillRequest(this);
+ afm.startAutofillRequest(this);
} else {
- afm.stopAutoFillRequest(this);
+ afm.stopAutofillRequest(this);
}
}
}
@@ -7238,18 +7243,18 @@
* fills in all data that can be inferred from the view itself.
*/
public void onProvideStructure(ViewStructure structure) {
- onProvideStructureForAssistOrAutoFill(structure, false);
+ onProvideStructureForAssistOrAutofill(structure, false);
}
/**
- * Called when assist structure is being retrieved from a view as part of an auto-fill request.
+ * Called when assist structure is being retrieved from a view as part of an autofill request.
*
- * <p>This method already provides most of what's needed for auto-fill, but should be overridden
+ * <p>This method already provides most of what's needed for autofill, but should be overridden
* <ol>
* <li>The view contents does not include PII (Personally Identifiable Information), so it
* can call {@link ViewStructure#setSanitized(boolean)} passing {@code true}.
* <li>It must set fields such {@link ViewStructure#setText(CharSequence)},
- * {@link ViewStructure#setAutoFillOptions(String[])}, or {@link ViewStructure#setUrl(String)}.
+ * {@link ViewStructure#setAutofillOptions(String[])}, or {@link ViewStructure#setUrl(String)}.
* </ol>
*
* @param structure Fill in with structured view data. The default implementation
@@ -7257,12 +7262,12 @@
* @param flags optional flags (currently {@code 0}).
*/
@CallSuper
- public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
- onProvideStructureForAssistOrAutoFill(structure, true);
+ public void onProvideAutofillStructure(ViewStructure structure, int flags) {
+ onProvideStructureForAssistOrAutofill(structure, true);
}
- private void onProvideStructureForAssistOrAutoFill(ViewStructure structure,
- boolean forAutoFill) {
+ private void onProvideStructureForAssistOrAutofill(ViewStructure structure,
+ boolean forAutofill) {
final int id = mID;
if (id != NO_ID && !isViewIdGenerated(id)) {
String pkg, type, entry;
@@ -7279,17 +7284,17 @@
structure.setId(id, null, null, null);
}
- if (forAutoFill) {
+ if (forAutofill) {
final @AutofillType int autofillType = getAutofillType();
- // Don't need to fill auto-fill info if view does not support it.
- // For example, only TextViews that are editable support auto-fill
+ // Don't need to fill autofill info if view does not support it.
+ // For example, only TextViews that are editable support autofill
if (autofillType != AUTOFILL_TYPE_NONE) {
- // The auto-fill id needs to be unique, but its value doesn't matter, so it's better
+ // The autofill id needs to be unique, but its value doesn't matter, so it's better
// to reuse the accessibility id to save space.
- structure.setAutoFillId(getAccessibilityViewId());
+ structure.setAutofillId(getAccessibilityViewId());
structure.setAutofillType(autofillType);
- structure.setAutoFillHint(getAutoFillHint());
- structure.setAutoFillValue(getAutoFillValue());
+ structure.setAutofillHint(getAutofillHint());
+ structure.setAutofillValue(getAutofillValue());
}
}
@@ -7327,6 +7332,9 @@
structure.setChecked(true);
}
}
+ if (isOpaque()) {
+ structure.setOpaque(true);
+ }
if (isContextClickable()) {
structure.setContextClickable(true);
}
@@ -7343,11 +7351,11 @@
* optimal implementation providing this data.
*/
public void onProvideVirtualStructure(ViewStructure structure) {
- onProvideVirtualStructureForAssistOrAutoFill(structure, false);
+ onProvideVirtualStructureForAssistOrAutofill(structure, false);
}
/**
- * Called when assist structure is being retrieved from a view as part of an auto-fill request
+ * Called when assist structure is being retrieved from a view as part of an autofill request
* to generate additional virtual structure under this view.
*
* <p>The default implementation uses {@link #getAccessibilityNodeProvider()} to try to
@@ -7357,27 +7365,27 @@
* <p>When implementing this method, subclasses must follow the rules below:
*
* <ol>
- * <li>Also implement {@link #autoFillVirtual(int, AutoFillValue)} to auto-fill the virtual
+ * <li>Also implement {@link #autofillVirtual(int, AutofillValue)} to autofill the virtual
* children.
* <li>Call
- * {@link android.view.autofill.AutoFillManager#startAutoFillRequestOnVirtualView} and
- * {@link android.view.autofill.AutoFillManager#stopAutoFillRequestOnVirtualView(View, int)}
+ * {@link android.view.autofill.AutofillManager#startAutofillRequestOnVirtualView} and
+ * {@link android.view.autofill.AutofillManager#stopAutofillRequestOnVirtualView(View, int)}
* when the focus inside the view changed.
- * <li>Call {@link android.view.autofill.AutoFillManager#virtualValueChanged(View, int,
- * AutoFillValue)} when the value of a child changed.
- * <li>Call {@link android.view.autofill.AutoFillManager#reset()} when the auto-fill context
+ * <li>Call {@link android.view.autofill.AutofillManager#virtualValueChanged(View, int,
+ * AutofillValue)} when the value of a child changed.
+ * <li>Call {@link android.view.autofill.AutofillManager#reset()} when the autofill context
* of the view structure changed.
* </ol>
*
* @param structure Fill in with structured view data.
* @param flags optional flags (currently {@code 0}).
*/
- public void onProvideAutoFillVirtualStructure(ViewStructure structure, int flags) {
- onProvideVirtualStructureForAssistOrAutoFill(structure, true);
+ public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
+ onProvideVirtualStructureForAssistOrAutofill(structure, true);
}
- private void onProvideVirtualStructureForAssistOrAutoFill(ViewStructure structure,
- boolean forAutoFill) {
+ private void onProvideVirtualStructureForAssistOrAutofill(ViewStructure structure,
+ boolean forAutofill) {
// NOTE: currently flags are only used for AutoFill; if they're used for Assist as well,
// this method should take a boolean with the type of request.
AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
@@ -7385,7 +7393,7 @@
AccessibilityNodeInfo info = createAccessibilityNodeInfo();
structure.setChildCount(1);
ViewStructure root = structure.newChild(0);
- populateVirtualStructure(root, provider, info, forAutoFill);
+ populateVirtualStructure(root, provider, info, forAutofill);
info.recycle();
}
}
@@ -7394,13 +7402,13 @@
* Automatically fills the content of this view with the {@code value}.
*
* <p>By default does nothing, but views should override it (and {@link #getAutofillType()},
- * {@link #getAutoFillValue()}, and {@link #onProvideAutoFillStructure(ViewStructure, int)}
- * to support the AutoFill Framework.
+ * {@link #getAutofillValue()}, and {@link #onProvideAutofillStructure(ViewStructure, int)}
+ * to support the Autofill Framework.
*
* <p>Typically, it is implemented by:
*
* <ol>
- * <li>Calling the proper getter method on {@link AutoFillValue} to fetch the actual value.
+ * <li>Calling the proper getter method on {@link AutofillValue} to fetch the actual value.
* <li>Passing the actual value to the equivalent setter in the view.
* <ol>
*
@@ -7413,76 +7421,56 @@
* }
* </pre>
*
- * @param value value to be auto-filled.
+ * @param value value to be autofilled.
*/
- public void autoFill(@SuppressWarnings("unused") AutoFillValue value) {
+ public void autofill(@SuppressWarnings("unused") AutofillValue value) {
}
/**
* Automatically fills the content of a virtual view with the {@code value}
*
- * <p>See {@link #autoFill(AutoFillValue)} and
- * {@link #onProvideAutoFillVirtualStructure(ViewStructure, int)} for more info.
+ * <p>See {@link #autofill(AutofillValue)} and
+ * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info.
*
- * @param value value to be auto-filled.
+ * @param value value to be autofilled.
* @param virtualId id identifying the virtual child inside the custom view.
*/
- public void autoFillVirtual(@SuppressWarnings("unused") int virtualId,
- @SuppressWarnings("unused") AutoFillValue value) {
+ public void autofillVirtual(@SuppressWarnings("unused") int virtualId,
+ @SuppressWarnings("unused") AutofillValue value) {
}
/**
- * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
- */
- @Deprecated
- @Nullable
- public final AutoFillType getAutoFillType() {
- switch (getAutofillType()) {
- case AUTOFILL_TYPE_TEXT:
- return AutoFillType.forText();
- case AUTOFILL_TYPE_TOGGLE:
- return AutoFillType.forToggle();
- case AUTOFILL_TYPE_LIST:
- return AutoFillType.forList();
- case AUTOFILL_TYPE_DATE:
- return AutoFillType.forDate();
- default:
- return null;
- }
- }
-
- /**
- * Describes the auto-fill type that should be used on calls to
- * {@link #autoFill(AutoFillValue)} and {@link #autoFillVirtual(int, AutoFillValue)}.
+ * Describes the autofill type that should be used on calls to
+ * {@link #autofill(AutofillValue)} and {@link #autofillVirtual(int, AutofillValue)}.
*
* <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it (and
- * {@link #autoFill(AutoFillValue)} to support the AutoFill Framework.
+ * {@link #autofill(AutofillValue)} to support the Autofill Framework.
*/
public @AutofillType int getAutofillType() {
return AUTOFILL_TYPE_NONE;
}
/**
- * Describes the content of a view so that a auto-fill service can fill in the appropriate data.
+ * Describes the content of a view so that a autofill service can fill in the appropriate data.
*
* @return The hint set via the attribute
*
- * @attr ref android.R.styleable#View_autoFillHint
+ * @attr ref android.R.styleable#View_autofillHint
*/
@ViewDebug.ExportedProperty()
- @AutoFillHint public int getAutoFillHint() {
- return mAutoFillHint;
+ @AutofillHint public int getAutofillHint() {
+ return mAutofillHint;
}
/**
- * Gets the {@link View}'s current auto-fill value.
+ * Gets the {@link View}'s current autofill value.
*
* <p>By default returns {@code null}, but views should override it (and
- * {@link #autoFill(AutoFillValue)}, and {@link #getAutofillType()} to support the AutoFill
+ * {@link #autofill(AutofillValue)}, and {@link #getAutofillType()} to support the Autofill
* Framework.
*/
@Nullable
- public AutoFillValue getAutoFillValue() {
+ public AutofillValue getAutofillValue() {
return null;
}
@@ -7528,16 +7516,16 @@
*
* <p>Generally speaking, a view is important for autofill if:
* <ol>
- * <li>The view can-be autofilled by an {@link android.service.autofill.AutoFillService}.
- * <li>The view contents can help an {@link android.service.autofill.AutoFillService} to
+ * <li>The view can-be autofilled by an {@link android.service.autofill.AutofillService}.
+ * <li>The view contents can help an {@link android.service.autofill.AutofillService} to
* autofill other views.
* <ol>
*
* <p>For example, view containers should typically return {@code false} for performance reasons
* (since the important info is provided by their children), but if the container is actually
* whose children are part of a compound view, it should return {@code true} (and then override
- * {@link #dispatchProvideAutoFillStructure(ViewStructure, int)} to simply call
- * {@link #onProvideAutoFillStructure(ViewStructure, int)} so its children are not included in
+ * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
+ * {@link #onProvideAutofillStructure(ViewStructure, int)} so its children are not included in
* the structure). On the other hand, views representing labels or editable fields should
* typically return {@code true}, but in some cases they could return {@code false} (for
* example, if they're part of a "Captcha" mechanism).
@@ -7554,9 +7542,9 @@
*
* <p>This decision applies just for the view, not its children - if the view children are not
* important for autofill, the view should override
- * {@link #dispatchProvideAutoFillStructure(ViewStructure, int)} to simply call
- * {@link #onProvideAutoFillStructure(ViewStructure, int)} (instead of calling
- * {@link #dispatchProvideAutoFillStructure(ViewStructure, int)} for each child).
+ * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
+ * {@link #onProvideAutofillStructure(ViewStructure, int)} (instead of calling
+ * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} for each child).
*
* @return whether the view is considered important for autofill.
*
@@ -7599,16 +7587,16 @@
}
@Nullable
- private AutoFillManager getAutoFillManager() {
- return mContext.getSystemService(AutoFillManager.class);
+ private AutofillManager getAutofillManager() {
+ return mContext.getSystemService(AutofillManager.class);
}
- private boolean isAutoFillable() {
- return getAutofillType() != AUTOFILL_TYPE_NONE && !isAutoFillBlocked();
+ private boolean isAutofillable() {
+ return getAutofillType() != AUTOFILL_TYPE_NONE && !isAutofillBlocked();
}
private void populateVirtualStructure(ViewStructure structure,
- AccessibilityNodeProvider provider, AccessibilityNodeInfo info, boolean forAutoFill) {
+ AccessibilityNodeProvider provider, AccessibilityNodeInfo info, boolean forAutofill) {
structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
null, null, null);
Rect rect = structure.getTempRect();
@@ -7646,7 +7634,7 @@
CharSequence cname = info.getClassName();
structure.setClassName(cname != null ? cname.toString() : null);
structure.setContentDescription(info.getContentDescription());
- if (!forAutoFill && (info.getText() != null || info.getError() != null)) {
+ if (!forAutofill && (info.getText() != null || info.getError() != null)) {
// TODO(b/33197203) (b/33269702): when sanitized, try to use the Accessibility API to
// just set sanitized values (like text coming from resource files), rather than not
// setting it at all.
@@ -7660,7 +7648,7 @@
AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
ViewStructure child = structure.newChild(i);
- populateVirtualStructure(child, provider, cinfo, forAutoFill);
+ populateVirtualStructure(child, provider, cinfo, forAutofill);
cinfo.recycle();
}
}
@@ -7672,7 +7660,7 @@
* {@link #onProvideVirtualStructure}.
*/
public void dispatchProvideStructure(ViewStructure structure) {
- dispatchProvideStructureForAssistOrAutoFill(structure, false);
+ dispatchProvideStructureForAssistOrAutofill(structure, false);
}
/**
@@ -7681,27 +7669,27 @@
* <p>The structure must be filled according to the request type, which is set in the
* {@code flags} parameter - see the documentation on each flag for more details.
*
- * <p>The default implementation calls {@link #onProvideAutoFillStructure(ViewStructure, int)}
- * and {@link #onProvideAutoFillVirtualStructure(ViewStructure, int)}.
+ * <p>The default implementation calls {@link #onProvideAutofillStructure(ViewStructure, int)}
+ * and {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
*
* @param structure Fill in with structured view data.
* @param flags optional flags (currently {@code 0}).
*/
- public void dispatchProvideAutoFillStructure(ViewStructure structure, int flags) {
- dispatchProvideStructureForAssistOrAutoFill(structure, true);
+ public void dispatchProvideAutofillStructure(ViewStructure structure, int flags) {
+ dispatchProvideStructureForAssistOrAutofill(structure, true);
}
- private void dispatchProvideStructureForAssistOrAutoFill(ViewStructure structure,
- boolean forAutoFill) {
- boolean blocked = forAutoFill ? isAutoFillBlocked() : isAssistBlocked();
+ private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure,
+ boolean forAutofill) {
+ boolean blocked = forAutofill ? isAutofillBlocked() : isAssistBlocked();
if (!blocked) {
- if (forAutoFill) {
- // The auto-fill id needs to be unique, but its value doesn't matter,
+ if (forAutofill) {
+ // The autofill id needs to be unique, but its value doesn't matter,
// so it's better to reuse the accessibility id to save space.
- structure.setAutoFillId(getAccessibilityViewId());
+ structure.setAutofillId(getAccessibilityViewId());
// NOTE: flags are not currently supported, hence 0
- onProvideAutoFillStructure(structure, 0);
- onProvideAutoFillVirtualStructure(structure, 0);
+ onProvideAutofillStructure(structure, 0);
+ onProvideAutofillVirtualStructure(structure, 0);
} else {
onProvideStructure(structure);
onProvideVirtualStructure(structure);
@@ -8115,7 +8103,7 @@
*/
public int getAccessibilityWindowId() {
return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
- : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
+ : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
}
/**
@@ -9082,29 +9070,29 @@
}
/**
- * Set auto-fill mode for the view.
+ * Set autofill mode for the view.
*
- * @param autoFillMode One of {@link #AUTO_FILL_MODE_INHERIT}, {@link #AUTO_FILL_MODE_AUTO},
- * or {@link #AUTO_FILL_MODE_MANUAL}.
- * @attr ref android.R.styleable#View_autoFillMode
+ * @param autofillMode One of {@link #AUTOFILL_MODE_INHERIT}, {@link #AUTOFILL_MODE_AUTO},
+ * or {@link #AUTOFILL_MODE_MANUAL}.
+ * @attr ref android.R.styleable#View_autofillMode
*/
- public void setAutoFillMode(@AutoFillMode int autoFillMode) {
- Preconditions.checkArgumentInRange(autoFillMode, AUTO_FILL_MODE_INHERIT,
- AUTO_FILL_MODE_MANUAL, "autoFillMode");
+ public void setAutofillMode(@AutofillMode int autofillMode) {
+ Preconditions.checkArgumentInRange(autofillMode, AUTOFILL_MODE_INHERIT,
+ AUTOFILL_MODE_MANUAL, "autofillMode");
- mPrivateFlags3 &= ~PFLAG3_AUTO_FILL_MODE_MASK;
- mPrivateFlags3 |= autoFillMode << PFLAG3_AUTO_FILL_MODE_SHIFT;
+ mPrivateFlags3 &= ~PFLAG3_AUTOFILL_MODE_MASK;
+ mPrivateFlags3 |= autofillMode << PFLAG3_AUTOFILL_MODE_SHIFT;
}
/**
- * Sets the a hint that helps the auto-fill service to select the appropriate data to fill the
+ * Sets the a hint that helps the autofill service to select the appropriate data to fill the
* view.
*
- * @param autoFillHint The auto-fill hint to set
- * @attr ref android.R.styleable#View_autoFillHint
+ * @param autofillHint The autofill hint to set
+ * @attr ref android.R.styleable#View_autofillHint
*/
- public void setAutoFillHint(@AutoFillHint int autoFillHint) {
- mAutoFillHint = autoFillHint;
+ public void setAutofillHint(@AutofillHint int autofillHint) {
+ mAutofillHint = autofillHint;
}
/**
@@ -9537,19 +9525,19 @@
/**
* @hide
* Indicates whether this view will participate in data collection through
- * {@link ViewStructure} for auto-fill purposes.
+ * {@link ViewStructure} for autofill purposes.
*
* <p>If {@code true}, it will not provide any data for itself or its children.
* <p>If {@code false}, the normal data collection will be allowed.
*
- * @return Returns {@code false} if assist data collection for auto-fill is not blocked,
+ * @return Returns {@code false} if assist data collection for autofill is not blocked,
* else {@code true}.
*
* TODO(b/33197203): update / remove javadoc tags below
* @see #setAssistBlocked(boolean)
* @attr ref android.R.styleable#View_assistBlocked
*/
- public boolean isAutoFillBlocked() {
+ public boolean isAutofillBlocked() {
return false; // TODO(b/33197203): properly implement it
}
@@ -9711,44 +9699,44 @@
}
/**
- * Returns the auto-fill mode for this view.
+ * Returns the autofill mode for this view.
*
- * @return One of {@link #AUTO_FILL_MODE_INHERIT}, {@link #AUTO_FILL_MODE_AUTO}, or
- * {@link #AUTO_FILL_MODE_MANUAL}.
- * @attr ref android.R.styleable#View_autoFillMode
+ * @return One of {@link #AUTOFILL_MODE_INHERIT}, {@link #AUTOFILL_MODE_AUTO}, or
+ * {@link #AUTOFILL_MODE_MANUAL}.
+ * @attr ref android.R.styleable#View_autofillMode
*/
@ViewDebug.ExportedProperty(mapping = {
- @ViewDebug.IntToString(from = AUTO_FILL_MODE_INHERIT, to = "AUTO_FILL_MODE_INHERIT"),
- @ViewDebug.IntToString(from = AUTO_FILL_MODE_AUTO, to = "AUTO_FILL_MODE_AUTO"),
- @ViewDebug.IntToString(from = AUTO_FILL_MODE_MANUAL, to = "AUTO_FILL_MODE_MANUAL")
+ @ViewDebug.IntToString(from = AUTOFILL_MODE_INHERIT, to = "AUTOFILL_MODE_INHERIT"),
+ @ViewDebug.IntToString(from = AUTOFILL_MODE_AUTO, to = "AUTOFILL_MODE_AUTO"),
+ @ViewDebug.IntToString(from = AUTOFILL_MODE_MANUAL, to = "AUTOFILL_MODE_MANUAL")
})
- @AutoFillMode
- public int getAutoFillMode() {
- return (mPrivateFlags3 & PFLAG3_AUTO_FILL_MODE_MASK) >> PFLAG3_AUTO_FILL_MODE_SHIFT;
+ @AutofillMode
+ public int getAutofillMode() {
+ return (mPrivateFlags3 & PFLAG3_AUTOFILL_MODE_MASK) >> PFLAG3_AUTOFILL_MODE_SHIFT;
}
/**
- * Returns the resolved auto-fill mode for this view.
+ * Returns the resolved autofill mode for this view.
*
- * This is the same as {@link #getAutoFillMode()} but if the mode is
- * {@link #AUTO_FILL_MODE_INHERIT} the parents auto-fill mode will be returned.
+ * This is the same as {@link #getAutofillMode()} but if the mode is
+ * {@link #AUTOFILL_MODE_INHERIT} the parents autofill mode will be returned.
*
- * @return One of {@link #AUTO_FILL_MODE_AUTO}, or {@link #AUTO_FILL_MODE_MANUAL}. If the auto-
- * fill mode can not be resolved e.g. {@link #getAutoFillMode()} is
- * {@link #AUTO_FILL_MODE_INHERIT} and the {@link View} is detached
- * {@link #AUTO_FILL_MODE_AUTO} is returned.
+ * @return One of {@link #AUTOFILL_MODE_AUTO}, or {@link #AUTOFILL_MODE_MANUAL}. If the auto-
+ * fill mode can not be resolved e.g. {@link #getAutofillMode()} is
+ * {@link #AUTOFILL_MODE_INHERIT} and the {@link View} is detached
+ * {@link #AUTOFILL_MODE_AUTO} is returned.
*/
- public @AutoFillMode int getResolvedAutoFillMode() {
- @AutoFillMode int autoFillMode = getAutoFillMode();
+ public @AutofillMode int getResolvedAutofillMode() {
+ @AutofillMode int autofillMode = getAutofillMode();
- if (autoFillMode == AUTO_FILL_MODE_INHERIT) {
+ if (autofillMode == AUTOFILL_MODE_INHERIT) {
if (mParent == null) {
- return AUTO_FILL_MODE_AUTO;
+ return AUTOFILL_MODE_AUTO;
} else {
- return mParent.getResolvedAutoFillMode();
+ return mParent.getResolvedAutofillMode();
}
} else {
- return autoFillMode;
+ return autofillMode;
}
}
@@ -11904,7 +11892,9 @@
if (!mHasPerformedLongPress) {
// This is a tap, so remove the longpress check
removeLongPressCallback();
- return performClick();
+ if (!event.isCanceled()) {
+ return performClick();
+ }
}
}
}
@@ -16889,10 +16879,10 @@
}
needGlobalAttributesUpdate(false);
- if (isAutoFillable() && isFocused() && getResolvedAutoFillMode() == AUTO_FILL_MODE_AUTO) {
- AutoFillManager afm = getAutoFillManager();
+ if (isAutofillable() && isFocused() && getResolvedAutofillMode() == AUTOFILL_MODE_AUTO) {
+ AutofillManager afm = getAutofillManager();
if (afm != null) {
- afm.startAutoFillRequest(this);
+ afm.startAutofillRequest(this);
}
}
}
@@ -16942,10 +16932,10 @@
mOverlay.getOverlayView().dispatchDetachedFromWindow();
}
- if (isAutoFillable() && isFocused() && getResolvedAutoFillMode() == AUTO_FILL_MODE_AUTO) {
- AutoFillManager afm = getAutoFillManager();
+ if (isAutofillable() && isFocused() && getResolvedAutofillMode() == AUTOFILL_MODE_AUTO) {
+ AutofillManager afm = getAutofillManager();
if (afm != null) {
- afm.stopAutoFillRequest(this);
+ afm.stopAutofillRequest(this);
}
}
}
@@ -24668,7 +24658,7 @@
/**
* The id of the window for accessibility purposes.
*/
- int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
+ int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
/**
* Flags related to accessibility processing.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 214249f..9fa9985e 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3337,8 +3337,8 @@
* default {@link View} implementation.
*/
@Override
- public void dispatchProvideAutoFillStructure(ViewStructure structure, int flags) {
- super.dispatchProvideAutoFillStructure(structure, flags);
+ public void dispatchProvideAutofillStructure(ViewStructure structure, int flags) {
+ super.dispatchProvideAutofillStructure(structure, flags);
dispatchProvideStructureForAssistOrAutoFill(structure, true);
}
@@ -3363,8 +3363,8 @@
}
private void dispatchProvideStructureForAssistOrAutoFill(ViewStructure structure,
- boolean forAutoFill) {
- boolean blocked = forAutoFill ? isAutoFillBlocked() : isAssistBlocked();
+ boolean forAutofill) {
+ boolean blocked = forAutofill ? isAutofillBlocked() : isAssistBlocked();
if (blocked || structure.getChildCount() != 0) {
return;
}
@@ -3372,7 +3372,7 @@
final ArrayList<View> childrenList;
final int childrenCount;
- if (forAutoFill) {
+ if (forAutofill) {
childrenArray = null;
// TODO(b/33197203): the current algorithm allocates a new list for each children that
// is a view group; ideally, we should use mAttachInfo.mTempArrayList instead, but that
@@ -3432,7 +3432,7 @@
preorderedList = new ArrayList<>(childrenCount);
for (int j = 0; j < childrenCount; j++) {
final int index = permutation[j];
- final View child = forAutoFill
+ final View child = forAutofill
? childrenList.get(index)
: childrenArray[index];
preorderedList.add(child);
@@ -3443,15 +3443,15 @@
}
}
- final View child = forAutoFill
+ final View child = forAutofill
? getAndVerifyPreorderedView(preorderedList, childrenList, childIndex)
: getAndVerifyPreorderedView(preorderedList, childrenArray, childIndex);
final ViewStructure cstructure = structure.newChild(i);
// Must explicitly check which recursive method to call.
- if (forAutoFill) {
+ if (forAutofill) {
// NOTE: flags are not currently supported, hence 0
- child.dispatchProvideAutoFillStructure(cstructure, 0);
+ child.dispatchProvideAutofillStructure(cstructure, 0);
} else {
child.dispatchProvideStructure(cstructure);
}
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index 1467b69..d5aab48 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -661,15 +661,15 @@
public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle arguments);
/**
- * Return the resolved auto-fill mode.
+ * Return the resolved autofill mode.
*
- * @return One of {@link View#AUTO_FILL_MODE_AUTO}, {@link View#AUTO_FILL_MODE_MANUAL} if the
- * auto-fill mode can be resolved. If the auto-fill mode cannot be resolved
- * {@link View#AUTO_FILL_MODE_AUTO}.
+ * @return One of {@link View#AUTOFILL_MODE_AUTO}, {@link View#AUTOFILL_MODE_MANUAL} if the
+ * autofill mode can be resolved. If the autofill mode cannot be resolved
+ * {@link View#AUTOFILL_MODE_AUTO}.
*
- * @see View#getResolvedAutoFillMode()
+ * @see View#getResolvedAutofillMode()
*/
- default @View.AutoFillMode int getResolvedAutoFillMode() {
- return View.AUTO_FILL_MODE_AUTO;
+ default @View.AutofillMode int getResolvedAutofillMode() {
+ return View.AUTOFILL_MODE_AUTO;
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 20d960f..580888c 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -82,6 +82,7 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.view.accessibility.AccessibilityNodeProvider;
+import android.view.accessibility.AccessibilityWindowInfo;
import android.view.accessibility.IAccessibilityInteractionConnection;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
import android.view.animation.AccelerateDecelerateInterpolator;
@@ -2632,6 +2633,14 @@
}
}
+ private void onDrawFinished() {
+ try {
+ mWindowSession.finishDrawing(mWindow);
+ } catch (RemoteException e) {
+ // Have fun!
+ }
+ }
+
private void performDraw() {
if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) {
return;
@@ -2682,7 +2691,7 @@
}
if (mSurfaceHolder != null && mSurface.isValid()) {
- SurfaceCallbackHelper sch = new SurfaceCallbackHelper(mWindowSession, mWindow);
+ SurfaceCallbackHelper sch = new SurfaceCallbackHelper(this::onDrawFinished);
SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
@@ -6872,12 +6881,7 @@
final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId(
sourceNodeId);
final AccessibilityNodeInfo node;
- if (virtualNodeId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
- node = provider.createAccessibilityNodeInfo(
- AccessibilityNodeProvider.HOST_VIEW_ID);
- } else {
- node = provider.createAccessibilityNodeInfo(virtualNodeId);
- }
+ node = provider.createAccessibilityNodeInfo(virtualNodeId);
setAccessibilityFocus(source, node);
}
}
@@ -6963,10 +6967,6 @@
final long focusedSourceNodeId = mAccessibilityFocusedVirtualView.getSourceNodeId();
int focusedChildId = AccessibilityNodeInfo.getVirtualDescendantId(focusedSourceNodeId);
- if (focusedChildId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
- // TODO: Should we clear the focused virtual view?
- focusedChildId = AccessibilityNodeProvider.HOST_VIEW_ID;
- }
// Refresh the node for the focused virtual view.
final Rect oldBounds = mTempRect;
@@ -7487,8 +7487,8 @@
}
public void ensureConnection() {
- final boolean registered =
- mAttachInfo.mAccessibilityWindowId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
+ final boolean registered = mAttachInfo.mAccessibilityWindowId
+ != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
if (!registered) {
mAttachInfo.mAccessibilityWindowId =
mAccessibilityManager.addAccessibilityInteractionConnection(mWindow,
@@ -7497,10 +7497,10 @@
}
public void ensureNoConnection() {
- final boolean registered =
- mAttachInfo.mAccessibilityWindowId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
+ final boolean registered = mAttachInfo.mAccessibilityWindowId
+ != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
if (registered) {
- mAttachInfo.mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
+ mAttachInfo.mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
mAccessibilityManager.removeAccessibilityInteractionConnection(mWindow);
}
}
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index c7c2bb8..bccaca2 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -19,14 +19,13 @@
import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.Bundle;
-import android.view.autofill.AutoFillId;
-import android.view.autofill.AutoFillType;
-import android.view.autofill.AutoFillValue;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
/**
* Container for storing additional per-view data generated by {@link View#onProvideStructure
- * View.onProvideStructure} and {@link View#onProvideAutoFillStructure
- * View.onProvideAutoFillStructure}.
+ * View.onProvideStructure} and {@link View#onProvideAutofillStructure
+ * View.onProvideAutofillStructure}.
*/
public abstract class ViewStructure {
@@ -147,6 +146,11 @@
public abstract void setActivated(boolean state);
/**
+ * Set the opaque state of this view, as per {@link View#isOpaque View.isOpaque()}.
+ */
+ public abstract void setOpaque(boolean opaque);
+
+ /**
* Set the class name of the view, as per
* {@link View#getAccessibilityClassName View.getAccessibilityClassName()}.
*/
@@ -264,19 +268,19 @@
public abstract ViewStructure newChild(int index);
/**
- * Create a new child {@link ViewStructure} in this view for auto-fill purposes.
+ * Create a new child {@link ViewStructure} in this view for autofill purposes.
*
* @param index the index (in the list of children) to put the new child at (see
* {@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#autofillVirtual(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 newChildForAutofill(int index, int virtualId, int flags);
/**
* Like {@link #newChild}, but allows the caller to asynchronously populate the returned
@@ -289,7 +293,7 @@
public abstract ViewStructure asyncNewChild(int index);
/**
- * Like {@link #newChildForAutoFill(int, int, int)}, but allows the caller to asynchronously
+ * Like {@link #newChildForAutofill(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
@@ -302,19 +306,13 @@
* {@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#autofillVirtual(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);
-
- /**
- * @deprecated TODO(b/35956626): remove once clients use setAutoFilltype()
- */
- @Deprecated
- public abstract void setAutoFillType(AutoFillType info);
+ public abstract ViewStructure asyncNewChildForAutofill(int index, int virtualId, int flags);
/**
* Sets the {@link View#getAutofillType()} that can be used to autofill this node.
@@ -322,26 +320,23 @@
public abstract void setAutofillType(@View.AutofillType int type);
/**
- * Sets the a hint that helps the auto-fill service to select the appropriate data to fill the
+ * Sets the a hint that helps the autofill service to select the appropriate data to fill the
* view.
*/
- // TODO(b/35364993): add CTS/unit test
- public abstract void setAutoFillHint(@View.AutoFillHint int hint);
+ public abstract void setAutofillHint(@View.AutofillHint int hint);
/**
- * Sets the {@link AutoFillValue} representing the current value of this node.
+ * Sets the {@link AutofillValue} representing the current value of this node.
*/
- // TODO(b/33197203, b/33802548): add CTS/unit test
- public abstract void setAutoFillValue(AutoFillValue value);
+ public abstract void setAutofillValue(AutofillValue value);
/**
- * Sets the options that can be used to auto-fill this node.
+ * Sets the options that can be used to autofill this node.
*
- * <p>Typically used by nodes whose {@link AutoFillType} is a list to indicate the meaning of
- * each possible value in the list.
+ * <p>Typically used by nodes whose {@link View#getAutofillType()} is a list to indicate the
+ * meaning of each possible value in the list.
*/
- // TODO(b/33197203, b/33802548): add CTS/unit test
- public abstract void setAutoFillOptions(String[] options);
+ public abstract void setAutofillOptions(String[] options);
/**
* Sets the {@link android.text.InputType} bits of this node.
@@ -352,7 +347,7 @@
/**
* Marks this node as sanitized so its content are sent on {@link
- * android.service.autofill.AutoFillService#onFillRequest(android.app.assist.AssistStructure,
+ * android.service.autofill.AutofillService#onFillRequest(android.app.assist.AssistStructure,
* Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback)}.
*
* <p>Only nodes that does not have PII (Personally Identifiable Information - sensitive data
@@ -360,7 +355,7 @@
* as sanitized; a good rule of thumb is to mark as sanitized nodes whose value were statically
* set from resources.
*
- * <p>Should only be set when the node is used for AutoFill purposes - it will be ignored
+ * <p>Should only be set when the node is used for autofill purposes - it will be ignored
* when used for Assist.
*/
public abstract void setSanitized(boolean sanitized);
@@ -375,10 +370,10 @@
public abstract Rect getTempRect();
/** @hide */
- public abstract void setAutoFillId(int viewId);
+ public abstract void setAutofillId(int viewId);
/** @hide */
- public abstract AutoFillId getAutoFillId();
+ public abstract AutofillId getAutofillId();
/**
* Sets the URL represented by this node.
diff --git a/core/java/android/view/WindowInfo.java b/core/java/android/view/WindowInfo.java
index 737e4607..95a6394 100644
--- a/core/java/android/view/WindowInfo.java
+++ b/core/java/android/view/WindowInfo.java
@@ -46,6 +46,7 @@
public List<IBinder> childTokens;
public CharSequence title;
public int accessibilityIdOfAnchor = View.NO_ID;
+ public boolean inPictureInPicture;
private WindowInfo() {
/* do nothing - hide constructor */
@@ -69,6 +70,7 @@
window.boundsInScreen.set(other.boundsInScreen);
window.title = other.title;
window.accessibilityIdOfAnchor = other.accessibilityIdOfAnchor;
+ window.inPictureInPicture = other.inPictureInPicture;
if (other.childTokens != null && !other.childTokens.isEmpty()) {
if (window.childTokens == null) {
@@ -101,6 +103,7 @@
boundsInScreen.writeToParcel(parcel, flags);
parcel.writeCharSequence(title);
parcel.writeInt(accessibilityIdOfAnchor);
+ parcel.writeInt(inPictureInPicture ? 1 : 0);
if (childTokens != null && !childTokens.isEmpty()) {
parcel.writeInt(1);
@@ -136,6 +139,7 @@
boundsInScreen.readFromParcel(parcel);
title = parcel.readCharSequence();
accessibilityIdOfAnchor = parcel.readInt();
+ inPictureInPicture = (parcel.readInt() == 1);
final boolean hasChildren = (parcel.readInt() == 1);
if (hasChildren) {
@@ -156,6 +160,7 @@
if (childTokens != null) {
childTokens.clear();
}
+ inPictureInPicture = false;
}
public static final Parcelable.Creator<WindowInfo> CREATOR =
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 828583c..19213ca 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -158,7 +158,7 @@
*/
public AccessibilityNodeInfo getRootInActiveWindow(int connectionId) {
return findAccessibilityNodeInfoByAccessibilityId(connectionId,
- AccessibilityNodeInfo.ACTIVE_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID,
+ AccessibilityWindowInfo.ACTIVE_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID,
false, AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS, null);
}
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 45302b6..fe888ec 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -21,6 +21,7 @@
import android.Manifest;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -822,6 +823,31 @@
}
}
+ /**
+ * Set an IAccessibilityInteractionConnection to replace the actions of a picture-in-picture
+ * window. Intended for use by the System UI only.
+ *
+ * @param connection The connection to handle the actions. Set to {@code null} to avoid
+ * affecting the actions.
+ *
+ * @hide
+ */
+ public void setPictureInPictureActionReplacingConnection(
+ @Nullable IAccessibilityInteractionConnection connection) {
+ final IAccessibilityManager service;
+ synchronized (mLock) {
+ service = getServiceLocked();
+ if (service == null) {
+ return;
+ }
+ }
+ try {
+ service.setPictureInPictureActionReplacingConnection(connection);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error setting picture in picture action replacement", re);
+ }
+ }
+
private IAccessibilityManager getServiceLocked() {
if (mService == null) {
tryConnectToServiceLocked(null);
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 8094fa6..50f17e0 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -85,17 +85,19 @@
/** @hide */
public static final int UNDEFINED_SELECTION_INDEX = -1;
+ /* Special IDs for node source IDs */
/** @hide */
public static final int UNDEFINED_ITEM_ID = Integer.MAX_VALUE;
/** @hide */
- public static final long ROOT_NODE_ID = makeNodeId(UNDEFINED_ITEM_ID, UNDEFINED_ITEM_ID);
+ public static final int ROOT_ITEM_ID = Integer.MAX_VALUE - 1;
/** @hide */
- public static final int ACTIVE_WINDOW_ID = UNDEFINED_ITEM_ID;
+ public static final long UNDEFINED_NODE_ID = makeNodeId(UNDEFINED_ITEM_ID, UNDEFINED_ITEM_ID);
/** @hide */
- public static final int ANY_WINDOW_ID = -2;
+ public static final long ROOT_NODE_ID = makeNodeId(ROOT_ITEM_ID,
+ AccessibilityNodeProvider.HOST_VIEW_ID);
/** @hide */
public static final int FLAG_PREFETCH_PREDECESSORS = 0x00000001;
@@ -474,6 +476,34 @@
"android.view.accessibility.action.ARGUMENT_PROGRESS_VALUE";
/**
+ * Argument for specifying the x coordinate to which to move a window.
+ * <p>
+ * <strong>Type:</strong> int<br>
+ * <strong>Actions:</strong>
+ * <ul>
+ * <li>{@link AccessibilityAction#ACTION_MOVE_WINDOW}</li>
+ * </ul>
+ *
+ * @see AccessibilityAction#ACTION_MOVE_WINDOW
+ */
+ public static final String ACTION_ARGUMENT_MOVE_WINDOW_X =
+ "android.view.accessibility.action.ARGUMENT_MOVE_WINDOW_X";
+
+ /**
+ * Argument for specifying the y coordinate to which to move a window.
+ * <p>
+ * <strong>Type:</strong> int<br>
+ * <strong>Actions:</strong>
+ * <ul>
+ * <li>{@link AccessibilityAction#ACTION_MOVE_WINDOW}</li>
+ * </ul>
+ *
+ * @see AccessibilityAction#ACTION_MOVE_WINDOW
+ */
+ public static final String ACTION_ARGUMENT_MOVE_WINDOW_Y =
+ "android.view.accessibility.action.ARGUMENT_MOVE_WINDOW_Y";
+
+ /**
* Argument to pass the {@link AccessibilityClickableSpan}.
* For use with R.id.accessibilityActionClickOnClickableSpan
* @hide
@@ -654,13 +684,6 @@
* @hide
*/
public static long makeNodeId(int accessibilityViewId, int virtualDescendantId) {
- // We changed the value for undefined node to positive due to wrong
- // global id composition (two 32-bin ints into one 64-bit long) but
- // the value used for the host node provider view has id -1 so we
- // remap it here.
- if (virtualDescendantId == AccessibilityNodeProvider.HOST_VIEW_ID) {
- virtualDescendantId = UNDEFINED_ITEM_ID;
- }
return (((long) virtualDescendantId) << VIRTUAL_DESCENDANT_ID_SHIFT) | accessibilityViewId;
}
@@ -673,12 +696,12 @@
// Data.
private int mWindowId = UNDEFINED_ITEM_ID;
- private long mSourceNodeId = ROOT_NODE_ID;
- private long mParentNodeId = ROOT_NODE_ID;
- private long mLabelForId = ROOT_NODE_ID;
- private long mLabeledById = ROOT_NODE_ID;
- private long mTraversalBefore = ROOT_NODE_ID;
- private long mTraversalAfter = ROOT_NODE_ID;
+ private long mSourceNodeId = UNDEFINED_NODE_ID;
+ private long mParentNodeId = UNDEFINED_NODE_ID;
+ private long mLabelForId = UNDEFINED_NODE_ID;
+ private long mLabeledById = UNDEFINED_NODE_ID;
+ private long mTraversalBefore = UNDEFINED_NODE_ID;
+ private long mTraversalAfter = UNDEFINED_NODE_ID;
private int mBooleanProperties;
private final Rect mBoundsInParent = new Rect();
@@ -733,7 +756,7 @@
* @param source The info source.
*/
public void setSource(View source) {
- setSource(source, UNDEFINED_ITEM_ID);
+ setSource(source, AccessibilityNodeProvider.HOST_VIEW_ID);
}
/**
@@ -950,7 +973,7 @@
* @throws IllegalStateException If called from an AccessibilityService.
*/
public void addChild(View child) {
- addChildInternal(child, UNDEFINED_ITEM_ID, true);
+ addChildInternal(child, AccessibilityNodeProvider.HOST_VIEW_ID, true);
}
/**
@@ -960,7 +983,7 @@
* @hide
*/
public void addChildUnchecked(View child) {
- addChildInternal(child, UNDEFINED_ITEM_ID, false);
+ addChildInternal(child, AccessibilityNodeProvider.HOST_VIEW_ID, false);
}
/**
@@ -978,7 +1001,7 @@
* @throws IllegalStateException If called from an AccessibilityService.
*/
public boolean removeChild(View child) {
- return removeChild(child, UNDEFINED_ITEM_ID);
+ return removeChild(child, AccessibilityNodeProvider.HOST_VIEW_ID);
}
/**
@@ -1205,6 +1228,17 @@
}
/**
+ * Removes all actions.
+ *
+ * @hide
+ */
+ public void removeAllActions() {
+ if (mActions != null) {
+ mActions.clear();
+ }
+ }
+
+ /**
* Gets the node before which this one is visited during traversal. A screen-reader
* must visit the content of this node before the content of the one it precedes.
*
@@ -1233,7 +1267,7 @@
* @see #getTraversalBefore()
*/
public void setTraversalBefore(View view) {
- setTraversalBefore(view, UNDEFINED_ITEM_ID);
+ setTraversalBefore(view, AccessibilityNodeProvider.HOST_VIEW_ID);
}
/**
@@ -1294,7 +1328,7 @@
* @see #getTraversalAfter()
*/
public void setTraversalAfter(View view) {
- setTraversalAfter(view, UNDEFINED_ITEM_ID);
+ setTraversalAfter(view, AccessibilityNodeProvider.HOST_VIEW_ID);
}
/**
@@ -1572,7 +1606,7 @@
* @throws IllegalStateException If called from an AccessibilityService.
*/
public void setParent(View parent) {
- setParent(parent, UNDEFINED_ITEM_ID);
+ setParent(parent, AccessibilityNodeProvider.HOST_VIEW_ID);
}
/**
@@ -2533,7 +2567,7 @@
* @param labeled The view for which this info serves as a label.
*/
public void setLabelFor(View labeled) {
- setLabelFor(labeled, UNDEFINED_ITEM_ID);
+ setLabelFor(labeled, AccessibilityNodeProvider.HOST_VIEW_ID);
}
/**
@@ -2585,7 +2619,7 @@
* @param label The view that labels this node's source.
*/
public void setLabeledBy(View label) {
- setLabeledBy(label, UNDEFINED_ITEM_ID);
+ setLabeledBy(label, AccessibilityNodeProvider.HOST_VIEW_ID);
}
/**
@@ -2815,6 +2849,20 @@
}
/**
+ * Sets the id of the source node.
+ *
+ * @param sourceId The id.
+ * @param windowId The window id.
+ *
+ * @hide
+ */
+ public void setSourceNodeId(long sourceId, int windowId) {
+ enforceNotSealed();
+ mSourceNodeId = sourceId;
+ mWindowId = windowId;
+ }
+
+ /**
* Gets the id of the source node.
*
* @return The id.
@@ -3299,12 +3347,12 @@
*/
private void clear() {
mSealed = false;
- mSourceNodeId = ROOT_NODE_ID;
- mParentNodeId = ROOT_NODE_ID;
- mLabelForId = ROOT_NODE_ID;
- mLabeledById = ROOT_NODE_ID;
- mTraversalBefore = ROOT_NODE_ID;
- mTraversalAfter = ROOT_NODE_ID;
+ mSourceNodeId = UNDEFINED_NODE_ID;
+ mParentNodeId = UNDEFINED_NODE_ID;
+ mLabelForId = UNDEFINED_NODE_ID;
+ mLabeledById = UNDEFINED_NODE_ID;
+ mTraversalBefore = UNDEFINED_NODE_ID;
+ mTraversalAfter = UNDEFINED_NODE_ID;
mWindowId = UNDEFINED_ITEM_ID;
mConnectionId = UNDEFINED_CONNECTION_ID;
mMaxTextLength = -1;
@@ -3324,9 +3372,7 @@
mError = null;
mContentDescription = null;
mViewIdResourceName = null;
- if (mActions != null) {
- mActions.clear();
- }
+ removeAllActions();
mTextSelectionStart = UNDEFINED_SELECTION_INDEX;
mTextSelectionEnd = UNDEFINED_SELECTION_INDEX;
mInputType = InputType.TYPE_NULL;
@@ -3975,6 +4021,16 @@
public static final AccessibilityAction ACTION_SET_PROGRESS =
new AccessibilityAction(R.id.accessibilityActionSetProgress, null);
+ /**
+ * Action to move a window to a new location.
+ * <p>
+ * <strong>Arguments:</strong>
+ * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVE_WINDOW_X}
+ * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVE_WINDOW_Y}
+ */
+ public static final AccessibilityAction ACTION_MOVE_WINDOW =
+ new AccessibilityAction(R.id.accessibilityActionMoveWindow, null);
+
private static final ArraySet<AccessibilityAction> sStandardActions = new ArraySet<>();
static {
sStandardActions.add(ACTION_FOCUS);
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index f2979bb..3f1fece 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -91,7 +91,7 @@
int mAddedCount= UNDEFINED;
int mRemovedCount = UNDEFINED;
AccessibilityNodeInfo mSourceNode;
- int mSourceWindowId = UNDEFINED;
+ int mSourceWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
CharSequence mClassName;
CharSequence mContentDescription;
@@ -136,11 +136,12 @@
public void setSource(View root, int virtualDescendantId) {
enforceNotSealed();
boolean important = true;
- mSourceWindowId = UNDEFINED;
+ mSourceWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
clearSourceNode();
if (root != null) {
- if (virtualDescendantId == UNDEFINED ||
- virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+ if (virtualDescendantId == View.NO_ID
+ || virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID
+ || virtualDescendantId == AccessibilityNodeProvider.HOST_VIEW_ID) {
important = root.isImportantForAccessibility();
mSourceNode = root.createAccessibilityNodeInfo();
} else {
@@ -156,6 +157,25 @@
}
/**
+ * Set the source directly to an AccessibilityNodeInfo rather than indirectly via a View
+ *
+ * @param info The source
+ *
+ * @hide
+ */
+ public void setSource(AccessibilityNodeInfo info) {
+ enforceNotSealed();
+ clearSourceNode();
+ mSourceWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
+ if (info != null) {
+ mSourceNode = AccessibilityNodeInfo.obtain(info);
+ setBooleanProperty(PROPERTY_IMPORTANT_FOR_ACCESSIBILITY,
+ mSourceNode.isImportantForAccessibility());
+ mSourceWindowId = info.getWindowId();
+ }
+ }
+
+ /**
* Gets the {@link AccessibilityNodeInfo} of the event source.
* <p>
* <strong>Note:</strong> It is a client responsibility to recycle the received info
@@ -833,6 +853,7 @@
mSourceNode.recycle();
mSourceNode = null;
}
+
}
@Override
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index c390406..2a7537b 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -74,7 +74,15 @@
*/
public static final int TYPE_SPLIT_SCREEN_DIVIDER = 5;
- private static final int UNDEFINED = -1;
+ /* Special values for window IDs */
+ /** @hide */
+ public static final int ACTIVE_WINDOW_ID = Integer.MAX_VALUE;
+ /** @hide */
+ public static final int UNDEFINED_WINDOW_ID = -1;
+ /** @hide */
+ public static final int ANY_WINDOW_ID = -2;
+ /** @hide */
+ public static final int PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID = -3;
private static final int BOOLEAN_PROPERTY_ACTIVE = 1 << 0;
private static final int BOOLEAN_PROPERTY_FOCUSED = 1 << 1;
@@ -87,17 +95,18 @@
private static AtomicInteger sNumInstancesInUse;
// Data.
- private int mType = UNDEFINED;
- private int mLayer = UNDEFINED;
+ private int mType = UNDEFINED_WINDOW_ID;
+ private int mLayer = UNDEFINED_WINDOW_ID;
private int mBooleanProperties;
- private int mId = UNDEFINED;
- private int mParentId = UNDEFINED;
+ private int mId = UNDEFINED_WINDOW_ID;
+ private int mParentId = UNDEFINED_WINDOW_ID;
private final Rect mBoundsInScreen = new Rect();
private LongArray mChildIds;
private CharSequence mTitle;
- private int mAnchorId = UNDEFINED;
+ private int mAnchorId = UNDEFINED_WINDOW_ID;
+ private boolean mInPictureInPicture;
- private int mConnectionId = UNDEFINED;
+ private int mConnectionId = UNDEFINED_WINDOW_ID;
private AccessibilityWindowInfo() {
/* do nothing - hide constructor */
@@ -177,7 +186,7 @@
* @return The root node.
*/
public AccessibilityNodeInfo getRoot() {
- if (mConnectionId == UNDEFINED) {
+ if (mConnectionId == UNDEFINED_WINDOW_ID) {
return null;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
@@ -203,7 +212,8 @@
* @return The anchor node, or {@code null} if none exists.
*/
public AccessibilityNodeInfo getAnchor() {
- if ((mConnectionId == UNDEFINED) || (mAnchorId == UNDEFINED) || (mParentId == UNDEFINED)) {
+ if ((mConnectionId == UNDEFINED_WINDOW_ID) || (mAnchorId == UNDEFINED_WINDOW_ID)
+ || (mParentId == UNDEFINED_WINDOW_ID)) {
return null;
}
@@ -212,13 +222,27 @@
mParentId, mAnchorId, true, 0, null);
}
+ /** @hide */
+ public void setPictureInPicture(boolean pictureInPicture) {
+ mInPictureInPicture = pictureInPicture;
+ }
+
+ /**
+ * Check if the window is in picture-in-picture mode.
+ *
+ * @return {@code true} if the window is in picture-in-picture mode, {@code false} otherwise.
+ */
+ public boolean inPictureInPicture() {
+ return mInPictureInPicture;
+ }
+
/**
* Gets the parent window.
*
* @return The parent window, or {@code null} if none exists.
*/
public AccessibilityWindowInfo getParent() {
- if (mConnectionId == UNDEFINED || mParentId == UNDEFINED) {
+ if (mConnectionId == UNDEFINED_WINDOW_ID || mParentId == UNDEFINED_WINDOW_ID) {
return null;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
@@ -371,7 +395,7 @@
if (mChildIds == null) {
throw new IndexOutOfBoundsException();
}
- if (mConnectionId == UNDEFINED) {
+ if (mConnectionId == UNDEFINED_WINDOW_ID) {
return null;
}
final int childId = (int) mChildIds.get(index);
@@ -429,6 +453,7 @@
infoClone.mBoundsInScreen.set(info.mBoundsInScreen);
infoClone.mTitle = info.mTitle;
infoClone.mAnchorId = info.mAnchorId;
+ infoClone.mInPictureInPicture = info.mInPictureInPicture;
if (info.mChildIds != null && info.mChildIds.size() > 0) {
if (infoClone.mChildIds == null) {
@@ -486,6 +511,7 @@
mBoundsInScreen.writeToParcel(parcel, flags);
parcel.writeCharSequence(mTitle);
parcel.writeInt(mAnchorId);
+ parcel.writeInt(mInPictureInPicture ? 1 : 0);
final LongArray childIds = mChildIds;
if (childIds == null) {
@@ -510,6 +536,7 @@
mBoundsInScreen.readFromParcel(parcel);
mTitle = parcel.readCharSequence();
mAnchorId = parcel.readInt();
+ mInPictureInPicture = parcel.readInt() == 1;
final int childCount = parcel.readInt();
if (childCount > 0) {
@@ -556,6 +583,7 @@
builder.append(", bounds=").append(mBoundsInScreen);
builder.append(", focused=").append(isFocused());
builder.append(", active=").append(isActive());
+ builder.append(", pictureInPicture=").append(inPictureInPicture());
if (DEBUG) {
builder.append(", parent=").append(mParentId);
builder.append(", children=[");
@@ -572,8 +600,8 @@
}
builder.append(']');
} else {
- builder.append(", hasParent=").append(mParentId != UNDEFINED);
- builder.append(", isAnchored=").append(mAnchorId != UNDEFINED);
+ builder.append(", hasParent=").append(mParentId != UNDEFINED_WINDOW_ID);
+ builder.append(", isAnchored=").append(mAnchorId != UNDEFINED_WINDOW_ID);
builder.append(", hasChildren=").append(mChildIds != null
&& mChildIds.size() > 0);
}
@@ -585,17 +613,18 @@
* Clears the internal state.
*/
private void clear() {
- mType = UNDEFINED;
- mLayer = UNDEFINED;
+ mType = UNDEFINED_WINDOW_ID;
+ mLayer = UNDEFINED_WINDOW_ID;
mBooleanProperties = 0;
- mId = UNDEFINED;
- mParentId = UNDEFINED;
+ mId = UNDEFINED_WINDOW_ID;
+ mParentId = UNDEFINED_WINDOW_ID;
mBoundsInScreen.setEmpty();
if (mChildIds != null) {
mChildIds.clear();
}
- mConnectionId = UNDEFINED;
- mAnchorId = UNDEFINED;
+ mConnectionId = UNDEFINED_WINDOW_ID;
+ mAnchorId = UNDEFINED_WINDOW_ID;
+ mInPictureInPicture = false;
mTitle = null;
}
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index 8fde47a..157980f 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -45,10 +45,13 @@
List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType, int userId);
int addAccessibilityInteractionConnection(IWindow windowToken,
- in IAccessibilityInteractionConnection connection, int userId);
+ in IAccessibilityInteractionConnection connection, int userId);
void removeAccessibilityInteractionConnection(IWindow windowToken);
+ void setPictureInPictureActionReplacingConnection(
+ in IAccessibilityInteractionConnection connection);
+
void registerUiTestAutomationService(IBinder owner, IAccessibilityServiceClient client,
in AccessibilityServiceInfo info, int flags);
diff --git a/core/java/android/view/autofill/AutoFillId.aidl b/core/java/android/view/autofill/AutoFillId.aidl
index 56f0338..fc57ce7 100644
--- a/core/java/android/view/autofill/AutoFillId.aidl
+++ b/core/java/android/view/autofill/AutoFillId.aidl
@@ -16,4 +16,5 @@
package android.view.autofill;
+// @deprecated TODO(b/35956626): remove once clients use AutofillId
parcelable AutoFillId;
\ No newline at end of file
diff --git a/core/java/android/view/autofill/AutoFillId.java b/core/java/android/view/autofill/AutoFillId.java
index 38dc404..081fb02 100644
--- a/core/java/android/view/autofill/AutoFillId.java
+++ b/core/java/android/view/autofill/AutoFillId.java
@@ -15,67 +15,26 @@
*/
package android.view.autofill;
-import static android.view.autofill.Helper.DEBUG;
-
import android.os.Parcel;
import android.os.Parcelable;
/**
- * A unique identifier for an auto-fill node inside an {@link android.app.Activity}.
+ * @hide
+ * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
*/
+@Deprecated
public final class AutoFillId implements Parcelable {
- private int mViewId;
- private boolean mVirtual;
- private int mVirtualId;
-
- // TODO(b/33197203): use factory and cache values, since they're immutable
- /** @hide */
- public AutoFillId(int id) {
- mVirtual = false;
- mViewId = id;
- }
+ private final AutofillId mRealId;
/** @hide */
- public AutoFillId(AutoFillId parent, int virtualChildId) {
- mVirtual = true;
- mViewId = parent.mViewId;
- mVirtualId = virtualChildId;
+ public AutoFillId(AutofillId daRealId) {
+ this.mRealId = daRealId;
}
- /** @hide */
- public AutoFillId(int parentId, int virtualChildId) {
- mVirtual = true;
- mViewId = parentId;
- mVirtualId = virtualChildId;
- }
-
- /** @hide */
- public int getViewId() {
- return mViewId;
- }
-
- /** @hide */
- public int getVirtualChildId() {
- return mVirtualId;
- }
-
- /** @hide */
- public boolean isVirtual() {
- return mVirtual;
- }
-
- /////////////////////////////////
- // Object "contract" methods. //
- /////////////////////////////////
-
@Override
public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + mViewId;
- result = prime * result + mVirtualId;
- return result;
+ return mRealId.hashCode();
}
@Override
@@ -84,20 +43,7 @@
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
final AutoFillId other = (AutoFillId) obj;
- if (mViewId != other.mViewId) return false;
- if (mVirtualId != other.mVirtualId) return false;
- return true;
- }
-
- @Override
- public String toString() {
- if (!DEBUG) return super.toString();
-
- final StringBuilder builder = new StringBuilder().append(mViewId);
- if (mVirtual) {
- builder.append(":").append(mVirtualId);
- }
- return builder.toString();
+ return mRealId.equals(other.mRealId);
}
@Override
@@ -107,15 +53,21 @@
@Override
public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeInt(mViewId);
- parcel.writeInt(mVirtual ? 1 : 0);
- parcel.writeInt(mVirtualId);
+ parcel.writeParcelable(mRealId, 0);
}
private AutoFillId(Parcel parcel) {
- mViewId = parcel.readInt();
- mVirtual = parcel.readInt() == 1;
- mVirtualId = parcel.readInt();
+ mRealId = parcel.readParcelable(null);
+ }
+
+ /** @hide */
+ public AutofillId getDaRealId() {
+ return mRealId;
+ }
+
+ /** @hide */
+ public static AutoFillId forDaRealId(AutofillId id) {
+ return id == null ? null : new AutoFillId(id);
}
public static final Parcelable.Creator<AutoFillId> CREATOR =
diff --git a/core/java/android/view/autofill/AutoFillType.java b/core/java/android/view/autofill/AutoFillType.java
index 37966b2..c508ba4 100644
--- a/core/java/android/view/autofill/AutoFillType.java
+++ b/core/java/android/view/autofill/AutoFillType.java
@@ -23,16 +23,18 @@
import android.view.View;
/**
- * Defines the type of a object that can be used to auto-fill a {@link View} so the
- * {@link android.service.autofill.AutoFillService} can use the proper {@link AutoFillValue} to
+ * Defines the type of a object that can be used to autofill a {@link View} so the
+ * {@link android.service.autofill.AutofillService} can use the proper {@link AutofillValue} to
* fill it.
*
- * TODO(b/35956626): remove once clients use getAutoFilltype
+ * @hide
+ * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
*/
+@Deprecated
public final class AutoFillType implements Parcelable {
// Cached instance for types that don't have subtype; it uses the "lazy initialization holder
- // class idiom" (Effective Java, Item 71) to avoid memory utilization when auto-fill is not
+ // class idiom" (Effective Java, Item 71) to avoid memory utilization when autofill is not
// enabled.
private static class DefaultTypesHolder {
static final AutoFillType TEXT = new AutoFillType(TYPE_TEXT);
@@ -54,10 +56,6 @@
/**
* Checks if this is a type for a text field, which is filled by a {@link CharSequence}.
- *
- * <p>{@link AutoFillValue} instances for auto-filling a {@link View} can be obtained through
- * {@link AutoFillValue#forText(CharSequence)}, and the value passed to auto-fill a
- * {@link View} can be fetched through {@link AutoFillValue#getTextValue()}.
*/
public boolean isText() {
return mType == TYPE_TEXT;
@@ -65,10 +63,6 @@
/**
* Checks if this is a a type for a togglable field, which is filled by a {@code boolean}.
- *
- * <p>{@link AutoFillValue} instances for auto-filling a {@link View} can be obtained through
- * {@link AutoFillValue#forToggle(boolean)}, and the value passed to auto-fill a
- * {@link View} can be fetched through {@link AutoFillValue#getToggleValue()}.
*/
public boolean isToggle() {
return mType == TYPE_TOGGLE;
@@ -77,14 +71,7 @@
/**
* Checks if this is a type for a selection list field, which is filled by a {@code integer}
* representing the element index inside the list (starting at {@code 0}.
- *
- * <p>{@link AutoFillValue} instances for auto-filling a {@link View} can be obtained through
- * {@link AutoFillValue#forList(int)}, and the value passed to auto-fill a
- * {@link View} can be fetched through {@link AutoFillValue#getListValue()}.
- *
- * <p>The available options in the selection list are typically provided by
- * {@link android.app.assist.AssistStructure.ViewNode#getAutoFillOptions()}.
- */
+ */
public boolean isList() {
return mType == TYPE_LIST;
}
@@ -93,10 +80,6 @@
* Checks if this is a type for a date and time, which is represented by a long representing
* the number of milliseconds since the standard base time known as "the epoch", namely
* January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
- *
- * <p>{@link AutoFillValue} instances for auto-filling a {@link View} can be obtained through
- * {@link AutoFillValue#forDate(long)}, and the values passed to
- * auto-fill a {@link View} can be fetched through {@link AutoFillValue#getDateValue()}.
*/
public boolean isDate() {
return mType == TYPE_DATE;
diff --git a/core/java/android/view/autofill/AutoFillValue.aidl b/core/java/android/view/autofill/AutoFillValue.aidl
index 3b284b9..05b7562 100644
--- a/core/java/android/view/autofill/AutoFillValue.aidl
+++ b/core/java/android/view/autofill/AutoFillValue.aidl
@@ -16,4 +16,5 @@
package android.view.autofill;
+// @deprecated TODO(b/35956626): remove once clients use AutofillValue
parcelable AutoFillValue;
\ No newline at end of file
diff --git a/core/java/android/view/autofill/AutoFillValue.java b/core/java/android/view/autofill/AutoFillValue.java
index 11fab68..5dd17f1 100644
--- a/core/java/android/view/autofill/AutoFillValue.java
+++ b/core/java/android/view/autofill/AutoFillValue.java
@@ -24,24 +24,15 @@
import android.view.View;
/**
- * Abstracts how a {@link View} can be auto-filled by an
- * {@link android.service.autofill.AutoFillService}.
- *
- * <p>Each {@link AutoFillValue} has a {@code type} and optionally a {@code sub-type}: the
- * {@code type} defines the view's UI control category (like a text field), while the optional
- * {@code sub-type} define its semantics (like a postal address).
+ * @hide
+ * @deprecated TODO(b/35956626): remove once clients use AutofillValue
*/
+@Deprecated
public final class AutoFillValue implements Parcelable {
- private final String mText;
- private final int mListIndex;
- private final boolean mToggle;
- private final long mDate;
+ private final AutofillValue mRealValue;
- private AutoFillValue(CharSequence text, int listIndex, boolean toggle, long date) {
- mText = (text == null) ? null : text.toString();
- mListIndex = listIndex;
- mToggle = toggle;
- mDate = date;
+ private AutoFillValue(AutofillValue daRealValue) {
+ this.mRealValue = daRealValue;
}
/**
@@ -50,7 +41,7 @@
* <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.
*/
public CharSequence getTextValue() {
- return mText;
+ return mRealValue.getTextValue();
}
/**
@@ -59,7 +50,7 @@
* <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.
*/
public boolean getToggleValue() {
- return mToggle;
+ return mRealValue.getToggleValue();
}
/**
@@ -68,7 +59,7 @@
* <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.
*/
public int getListValue() {
- return mListIndex;
+ return mRealValue.getListValue();
}
/**
@@ -77,7 +68,7 @@
* <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.
*/
public long getDateValue() {
- return mDate;
+ return mRealValue.getDateValue();
}
/////////////////////////////////////
@@ -86,13 +77,7 @@
@Override
public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((mText == null) ? 0 : mText.hashCode());
- result = prime * result + mListIndex;
- result = prime * result + (mToggle ? 1231 : 1237);
- result = prime * result + (int) (mDate ^ (mDate >>> 32));
- return result;
+ return mRealValue.hashCode();
}
@Override
@@ -101,32 +86,19 @@
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
final AutoFillValue other = (AutoFillValue) obj;
- if (mText == null) {
- if (other.mText != null) return false;
- } else {
- if (!mText.equals(other.mText)) return false;
- }
- if (mListIndex != other.mListIndex) return false;
- if (mToggle != other.mToggle) return false;
- if (mDate != other.mDate) return false;
- return true;
+ return mRealValue.equals(other.mRealValue);
}
/** @hide */
public String coerceToString() {
- // TODO(b/33197203): How can we filter on toggles or list values?
- return mText;
+ return mRealValue.coerceToString();
}
@Override
public String toString() {
if (!DEBUG) return super.toString();
- if (mText != null) {
- return mText.length() + "_chars";
- }
-
- return "[l=" + mListIndex + ", t=" + mToggle + ", d=" + mDate + "]";
+ return mRealValue.toString();
}
/////////////////////////////////////
@@ -140,17 +112,11 @@
@Override
public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeString(mText);
- parcel.writeInt(mListIndex);
- parcel.writeInt(mToggle ? 1 : 0);
- parcel.writeLong(mDate);
+ parcel.writeParcelable(mRealValue, 0);
}
private AutoFillValue(Parcel parcel) {
- mText = parcel.readString();
- mListIndex = parcel.readInt();
- mToggle = parcel.readInt() == 1;
- mDate = parcel.readLong();
+ mRealValue = parcel.readParcelable(null);
}
public static final Parcelable.Creator<AutoFillValue> CREATOR =
@@ -169,17 +135,14 @@
////////////////////
// Factory methods //
////////////////////
-
- // TODO(b/33197203): add unit tests for each supported type (new / get should return same value)
/**
* Creates a new {@link AutoFillValue} to autofill a {@link View} representing a text field.
*
* <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.
*/
- // TODO(b/33197203): use cache
@Nullable
public static AutoFillValue forText(@Nullable CharSequence value) {
- return value == null ? null : new AutoFillValue(value, 0, false, 0);
+ return value == null ? null : new AutoFillValue(AutofillValue.forText(value));
}
/**
@@ -189,7 +152,7 @@
* <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.
*/
public static AutoFillValue forToggle(boolean value) {
- return new AutoFillValue(null, 0, value, 0);
+ return new AutoFillValue(AutofillValue.forToggle(value));
}
/**
@@ -199,7 +162,7 @@
* <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.
*/
public static AutoFillValue forList(int value) {
- return new AutoFillValue(null, value, false, 0);
+ return new AutoFillValue(AutofillValue.forList(value));
}
/**
@@ -208,6 +171,16 @@
* <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.
*/
public static AutoFillValue forDate(long date) {
- return new AutoFillValue(null, 0, false, date);
+ return new AutoFillValue(AutofillValue.forDate(date));
+ }
+
+ /** @hide */
+ public static AutoFillValue forDaRealValue(AutofillValue daRealValue) {
+ return new AutoFillValue(daRealValue);
+ }
+
+ /** @hide */
+ public AutofillValue getDaRealValue() {
+ return mRealValue;
}
}
diff --git a/core/java/android/view/autofill/AutofillId.aidl b/core/java/android/view/autofill/AutofillId.aidl
new file mode 100644
index 0000000..7ac3d5b
--- /dev/null
+++ b/core/java/android/view/autofill/AutofillId.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.view.autofill;
+
+parcelable AutofillId;
\ No newline at end of file
diff --git a/core/java/android/view/autofill/AutofillId.java b/core/java/android/view/autofill/AutofillId.java
new file mode 100644
index 0000000..d678015
--- /dev/null
+++ b/core/java/android/view/autofill/AutofillId.java
@@ -0,0 +1,135 @@
+/*
+ * 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.view.autofill;
+
+import static android.view.autofill.Helper.DEBUG;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.View;
+
+/**
+ * A unique identifier for an autofill node inside an {@link android.app.Activity}.
+ */
+public final class AutofillId implements Parcelable {
+
+ private final int mViewId;
+ private final boolean mVirtual;
+ private final int mVirtualId;
+
+ // TODO(b/33197203): use factory and cache values, since they're immutable
+ /** @hide */
+ public AutofillId(int id) {
+ mVirtual = false;
+ mViewId = id;
+ mVirtualId = View.NO_ID;
+ }
+
+ /** @hide */
+ public AutofillId(AutofillId parent, int virtualChildId) {
+ mVirtual = true;
+ mViewId = parent.mViewId;
+ mVirtualId = virtualChildId;
+ }
+
+ /** @hide */
+ public AutofillId(int parentId, int virtualChildId) {
+ mVirtual = true;
+ mViewId = parentId;
+ mVirtualId = virtualChildId;
+ }
+
+ /** @hide */
+ public int getViewId() {
+ return mViewId;
+ }
+
+ /** @hide */
+ public int getVirtualChildId() {
+ return mVirtualId;
+ }
+
+ /** @hide */
+ public boolean isVirtual() {
+ return mVirtual;
+ }
+
+ /////////////////////////////////
+ // Object "contract" methods. //
+ /////////////////////////////////
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + mViewId;
+ result = prime * result + mVirtualId;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ final AutofillId other = (AutofillId) obj;
+ if (mViewId != other.mViewId) return false;
+ if (mVirtualId != other.mVirtualId) return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ if (!DEBUG) return super.toString();
+
+ final StringBuilder builder = new StringBuilder().append(mViewId);
+ if (mVirtual) {
+ builder.append(":").append(mVirtualId);
+ }
+ return builder.toString();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeInt(mViewId);
+ parcel.writeInt(mVirtual ? 1 : 0);
+ parcel.writeInt(mVirtualId);
+ }
+
+ private AutofillId(Parcel parcel) {
+ mViewId = parcel.readInt();
+ mVirtual = parcel.readInt() == 1;
+ mVirtualId = parcel.readInt();
+ }
+
+ public static final Parcelable.Creator<AutofillId> CREATOR =
+ new Parcelable.Creator<AutofillId>() {
+ @Override
+ public AutofillId createFromParcel(Parcel source) {
+ return new AutofillId(source);
+ }
+
+ @Override
+ public AutofillId[] newArray(int size) {
+ return new AutofillId[size];
+ }
+ };
+}
diff --git a/core/java/android/view/autofill/AutoFillManager.java b/core/java/android/view/autofill/AutofillManager.java
similarity index 75%
rename from core/java/android/view/autofill/AutoFillManager.java
rename to core/java/android/view/autofill/AutofillManager.java
index 8beaf4e..2a12e4b 100644
--- a/core/java/android/view/autofill/AutoFillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -44,9 +44,9 @@
*/
// TODO(b/33197203): improve this javadoc
//TODO(b/33197203): restrict manager calls to activity
-public final class AutoFillManager {
+public final class AutofillManager {
- private static final String TAG = "AutoFillManager";
+ private static final String TAG = "AutofillManager";
/**
* Intent extra: The assist structure which captures the filled screen.
@@ -89,14 +89,14 @@
private boolean mEnabled;
/** @hide */
- public interface AutoFillClient {
+ public interface AutofillClient {
/**
- * Asks the client to perform an auto-fill.
+ * Asks the client to perform an autofill.
*
- * @param ids The values to auto-fill
- * @param values The values to auto-fill
+ * @param ids The values to autofill
+ * @param values The values to autofill
*/
- void autoFill(List<AutoFillId> ids, List<AutoFillValue> values);
+ void autofill(List<AutofillId> ids, List<AutofillValue> values);
/**
* Asks the client to start an authentication flow.
@@ -115,17 +115,17 @@
/**
* @hide
*/
- public AutoFillManager(Context context, IAutoFillManager service) {
+ public AutofillManager(Context context, IAutoFillManager service) {
mContext = context;
mService = service;
}
/**
- * Called when an auto-fill operation on a {@link View} should start.
+ * Called when an autofill operation on a {@link View} should start.
*
- * @param view {@link View} that triggered the auto-fill request.
+ * @param view {@link View} that triggered the autofill request.
*/
- public void startAutoFillRequest(@NonNull View view) {
+ public void startAutofillRequest(@NonNull View view) {
ensureServiceClientAddedIfNeeded();
if (!mEnabled) {
@@ -134,8 +134,8 @@
final Rect bounds = mTempRect;
view.getBoundsOnScreen(bounds);
- final AutoFillId id = getAutoFillId(view);
- final AutoFillValue value = view.getAutoFillValue();
+ final AutofillId id = getAutofillId(view);
+ final AutofillValue value = view.getAutofillValue();
if (!mHasSession) {
// Starts new session.
@@ -147,16 +147,16 @@
}
/**
- * Called when an auto-fill operation on a {@link View} should stop.
+ * Called when an autofill operation on a {@link View} should stop.
*
- * @param view {@link View} that triggered the auto-fill request in
- * {@link #startAutoFillRequest(View)}.
+ * @param view {@link View} that triggered the autofill request in
+ * {@link #startAutofillRequest(View)}.
*/
- public void stopAutoFillRequest(@NonNull View view) {
+ public void stopAutofillRequest(@NonNull View view) {
ensureServiceClientAddedIfNeeded();
if (mEnabled && mHasSession) {
- final AutoFillId id = getAutoFillId(view);
+ final AutofillId id = getAutofillId(view);
// Update focus on existing session.
updateSession(id, null, null, FLAG_FOCUS_LOST);
@@ -164,13 +164,13 @@
}
/**
- * Called when an auto-fill operation on a virtual {@link View} should start.
+ * Called when an autofill operation on a virtual {@link View} should start.
*
- * @param parent parent of the {@link View} that triggered the auto-fill request.
+ * @param parent parent of the {@link View} that triggered the autofill request.
* @param childId id identifying the virtual child inside the parent view.
* @param bounds child boundaries, relative to the top window.
*/
- public void startAutoFillRequestOnVirtualView(@NonNull View parent, int childId,
+ public void startAutofillRequestOnVirtualView(@NonNull View parent, int childId,
@NonNull Rect bounds) {
ensureServiceClientAddedIfNeeded();
@@ -178,7 +178,7 @@
return;
}
- final AutoFillId id = getAutoFillId(parent, childId);
+ final AutofillId id = getAutofillId(parent, childId);
if (!mHasSession) {
// Starts new session.
@@ -190,17 +190,17 @@
}
/**
- * Called when an auto-fill operation on a virtual {@link View} should stop.
+ * Called when an autofill operation on a virtual {@link View} should stop.
*
- * @param parent parent of the {@link View} that triggered the auto-fill request in
- * {@link #startAutoFillRequestOnVirtualView(View, int, Rect)}.
+ * @param parent parent of the {@link View} that triggered the autofill request in
+ * {@link #startAutofillRequestOnVirtualView(View, int, Rect)}.
* @param childId id identifying the virtual child inside the parent view.
*/
- public void stopAutoFillRequestOnVirtualView(@NonNull View parent, int childId) {
+ public void stopAutofillRequestOnVirtualView(@NonNull View parent, int childId) {
ensureServiceClientAddedIfNeeded();
if (mEnabled && mHasSession) {
- final AutoFillId id = getAutoFillId(parent, childId);
+ final AutofillId id = getAutofillId(parent, childId);
// Update focus on existing session.
updateSession(id, null, null, FLAG_FOCUS_LOST);
@@ -208,7 +208,7 @@
}
/**
- * Called to indicate the value of an auto-fillable {@link View} changed.
+ * Called to indicate the value of an autofillable {@link View} changed.
*
* @param view view whose value changed.
*/
@@ -217,30 +217,30 @@
return;
}
- final AutoFillId id = getAutoFillId(view);
- final AutoFillValue value = view.getAutoFillValue();
+ final AutofillId id = getAutofillId(view);
+ final AutofillValue value = view.getAutofillValue();
updateSession(id, null, value, FLAG_VALUE_CHANGED);
}
/**
- * Called to indicate the value of an auto-fillable virtual {@link View} changed.
+ * Called to indicate the value of an autofillable virtual {@link View} changed.
*
* @param parent parent view whose value changed.
* @param childId id identifying the virtual child inside the parent view.
* @param value new value of the child.
*/
- public void virtualValueChanged(View parent, int childId, AutoFillValue value) {
+ public void virtualValueChanged(View parent, int childId, AutofillValue value) {
if (!mEnabled || !mHasSession) {
return;
}
- final AutoFillId id = getAutoFillId(parent, childId);
+ final AutofillId id = getAutofillId(parent, childId);
updateSession(id, null, value, FLAG_VALUE_CHANGED);
}
/**
- * Called to indicate the current auto-fill context should be reset.
+ * Called to indicate the current autofill context should be reset.
*
* <p>For example, when a virtual view is rendering an {@code HTML} page with a form, it should
* call this method after the form is submitted and another page is rendered.
@@ -253,9 +253,9 @@
finishSession();
}
- private AutoFillClient getClient() {
- if (mContext instanceof AutoFillClient) {
- return (AutoFillClient) mContext;
+ private AutofillClient getClient() {
+ if (mContext instanceof AutofillClient) {
+ return (AutofillClient) mContext;
}
return null;
}
@@ -283,16 +283,17 @@
}
}
- private static AutoFillId getAutoFillId(View view) {
- return new AutoFillId(view.getAccessibilityViewId());
+
+ private static AutofillId getAutofillId(View view) {
+ return new AutofillId(view.getAccessibilityViewId());
}
- private static AutoFillId getAutoFillId(View parent, int childId) {
- return new AutoFillId(parent.getAccessibilityViewId(), childId);
+ private static AutofillId getAutofillId(View parent, int childId) {
+ return new AutofillId(parent.getAccessibilityViewId(), childId);
}
- private void startSession(AutoFillId id, IBinder windowToken,
- Rect bounds, AutoFillValue value) {
+ private void startSession(AutofillId id, IBinder windowToken, Rect bounds,
+ AutofillValue value) {
if (DEBUG) {
Log.d(TAG, "startSession(): id=" + id + ", bounds=" + bounds + ", value=" + value);
}
@@ -301,7 +302,7 @@
mService.startSession(mContext.getActivityToken(), windowToken,
mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
mCallback != null);
- final AutoFillClient client = getClient();
+ final AutofillClient client = getClient();
if (client != null) {
client.resetableStateAvailable();
}
@@ -323,11 +324,11 @@
}
}
- private void updateSession(AutoFillId id, Rect bounds, AutoFillValue value, int flags) {
+ private void updateSession(AutofillId id, Rect bounds, AutofillValue value, int flags) {
if (DEBUG) {
if (VERBOSE || (flags & FLAG_FOCUS_LOST) != 0) {
Log.d(TAG, "updateSession(): id=" + id + ", bounds=" + bounds + ", value=" + value
- + ", flags=" + flags);
+ + ", flags=" + flags);
}
}
@@ -344,7 +345,7 @@
return;
}
if (mServiceClient == null) {
- mServiceClient = new AutoFillManagerClient(this);
+ mServiceClient = new AutofillManagerClient(this);
try {
mEnabled = mService.addClient(mServiceClient, mContext.getUserId());
} catch (RemoteException e) {
@@ -392,7 +393,7 @@
}
}
- private void onAutofillEvent(IBinder windowToken, AutoFillId id, int event) {
+ private void onAutofillEvent(IBinder windowToken, AutofillId id, int event) {
if (mCallback == null) return;
if (id == null) {
Log.w(TAG, "onAutofillEvent(): no id for event " + event);
@@ -466,31 +467,30 @@
@AutofillEventType int event) {}
}
- private static final class AutoFillManagerClient extends IAutoFillManagerClient.Stub {
- private final WeakReference<AutoFillManager> mAutoFillManager;
+ private static final class AutofillManagerClient extends IAutoFillManagerClient.Stub {
+ private final WeakReference<AutofillManager> mAfm;
- AutoFillManagerClient(AutoFillManager autoFillManager) {
- mAutoFillManager = new WeakReference<>(autoFillManager);
+ AutofillManagerClient(AutofillManager autofillManager) {
+ mAfm = new WeakReference<>(autofillManager);
}
@Override
public void setState(boolean enabled) {
- final AutoFillManager autoFillManager = mAutoFillManager.get();
- if (autoFillManager != null) {
- autoFillManager.mContext.getMainThreadHandler().post(() ->
- autoFillManager.mEnabled = enabled);
+ final AutofillManager afm = mAfm.get();
+ if (afm != null) {
+ afm.mContext.getMainThreadHandler().post(() -> afm.mEnabled = enabled);
}
}
@Override
- public void autoFill(List<AutoFillId> ids, List<AutoFillValue> values) {
+ public void autofill(List<AutofillId> ids, List<AutofillValue> values) {
// TODO(b/33197203): must keep the dataset so subsequent calls pass the same
// dataset.extras to service
- final AutoFillManager autoFillManager = mAutoFillManager.get();
- if (autoFillManager != null) {
- autoFillManager.mContext.getMainThreadHandler().post(() -> {
- if (autoFillManager.getClient() != null) {
- autoFillManager.getClient().autoFill(ids, values);
+ final AutofillManager afm = mAfm.get();
+ if (afm != null) {
+ afm.mContext.getMainThreadHandler().post(() -> {
+ if (afm.getClient() != null) {
+ afm.getClient().autofill(ids, values);
}
});
}
@@ -498,23 +498,23 @@
@Override
public void authenticate(IntentSender intent, Intent fillInIntent) {
- final AutoFillManager autoFillManager = mAutoFillManager.get();
- if (autoFillManager != null) {
- autoFillManager.mContext.getMainThreadHandler().post(() -> {
- if (autoFillManager.getClient() != null) {
- autoFillManager.getClient().authenticate(intent, fillInIntent);
+ final AutofillManager afm = mAfm.get();
+ if (afm != null) {
+ afm.mContext.getMainThreadHandler().post(() -> {
+ if (afm.getClient() != null) {
+ afm.getClient().authenticate(intent, fillInIntent);
}
});
}
}
@Override
- public void onAutofillEvent(IBinder windowToken, AutoFillId id, int event) {
- final AutoFillManager autoFillManager = mAutoFillManager.get();
- if (autoFillManager != null) {
- autoFillManager.mContext.getMainThreadHandler().post(() -> {
- if (autoFillManager.getClient() != null) {
- autoFillManager.onAutofillEvent(windowToken, id, event);
+ public void onAutofillEvent(IBinder windowToken, AutofillId id, int event) {
+ final AutofillManager afm = mAfm.get();
+ if (afm != null) {
+ afm.mContext.getMainThreadHandler().post(() -> {
+ if (afm.getClient() != null) {
+ afm.onAutofillEvent(windowToken, id, event);
}
});
}
diff --git a/core/java/android/view/autofill/AutofillValue.aidl b/core/java/android/view/autofill/AutofillValue.aidl
new file mode 100644
index 0000000..a015bad
--- /dev/null
+++ b/core/java/android/view/autofill/AutofillValue.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.view.autofill;
+
+parcelable AutofillValue;
\ No newline at end of file
diff --git a/core/java/android/view/autofill/AutofillValue.java b/core/java/android/view/autofill/AutofillValue.java
new file mode 100644
index 0000000..0c7620e
--- /dev/null
+++ b/core/java/android/view/autofill/AutofillValue.java
@@ -0,0 +1,211 @@
+/*
+ * 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.view.autofill;
+
+import static android.view.autofill.Helper.DEBUG;
+
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.View;
+
+/**
+ * Abstracts how a {@link View} can be autofilled by an
+ * {@link android.service.autofill.AutofillService}.
+ *
+ * <p>Each {@link AutofillValue} is associated with a {@code type}, as defined by
+ * {@link View#getAutofillType()}.
+ */
+public final class AutofillValue implements Parcelable {
+ private final String mText;
+ private final int mListIndex;
+ private final boolean mToggle;
+ private final long mDate;
+
+ private AutofillValue(CharSequence text, int listIndex, boolean toggle, long date) {
+ mText = (text == null) ? null : text.toString();
+ mListIndex = listIndex;
+ mToggle = toggle;
+ mDate = date;
+ }
+
+ /**
+ * Gets the value to autofill a text field.
+ *
+ * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.
+ */
+ public CharSequence getTextValue() {
+ return mText;
+ }
+
+ /**
+ * Gets the value to autofill a toggable field.
+ *
+ * <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.
+ */
+ public boolean getToggleValue() {
+ return mToggle;
+ }
+
+ /**
+ * Gets the value to autofill a selection list field.
+ *
+ * <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.
+ */
+ public int getListValue() {
+ return mListIndex;
+ }
+
+ /**
+ * Gets the value to autofill a date field.
+ *
+ * <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.
+ */
+ public long getDateValue() {
+ return mDate;
+ }
+
+ /////////////////////////////////////
+ // Object "contract" methods. //
+ /////////////////////////////////////
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((mText == null) ? 0 : mText.hashCode());
+ result = prime * result + mListIndex;
+ result = prime * result + (mToggle ? 1231 : 1237);
+ result = prime * result + (int) (mDate ^ (mDate >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ final AutofillValue other = (AutofillValue) obj;
+ if (mText == null) {
+ if (other.mText != null) return false;
+ } else {
+ if (!mText.equals(other.mText)) return false;
+ }
+ if (mListIndex != other.mListIndex) return false;
+ if (mToggle != other.mToggle) return false;
+ if (mDate != other.mDate) return false;
+ return true;
+ }
+
+ /** @hide */
+ public String coerceToString() {
+ // TODO(b/33197203): How can we filter on toggles or list values?
+ return mText;
+ }
+
+ @Override
+ public String toString() {
+ if (!DEBUG) return super.toString();
+
+ if (mText != null) {
+ return mText.length() + "_chars";
+ }
+
+ return "[l=" + mListIndex + ", t=" + mToggle + ", d=" + mDate + "]";
+ }
+
+ /////////////////////////////////////
+ // Parcelable "contract" methods. //
+ /////////////////////////////////////
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeString(mText);
+ parcel.writeInt(mListIndex);
+ parcel.writeInt(mToggle ? 1 : 0);
+ parcel.writeLong(mDate);
+ }
+
+ private AutofillValue(Parcel parcel) {
+ mText = parcel.readString();
+ mListIndex = parcel.readInt();
+ mToggle = parcel.readInt() == 1;
+ mDate = parcel.readLong();
+ }
+
+ public static final Parcelable.Creator<AutofillValue> CREATOR =
+ new Parcelable.Creator<AutofillValue>() {
+ @Override
+ public AutofillValue createFromParcel(Parcel source) {
+ return new AutofillValue(source);
+ }
+
+ @Override
+ public AutofillValue[] newArray(int size) {
+ return new AutofillValue[size];
+ }
+ };
+
+ ////////////////////
+ // Factory methods //
+ ////////////////////
+
+ /**
+ * Creates a new {@link AutofillValue} to autofill a {@link View} representing a text field.
+ *
+ * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.
+ */
+ // TODO(b/33197203): use cache
+ @Nullable
+ public static AutofillValue forText(@Nullable CharSequence value) {
+ return value == null ? null : new AutofillValue(value, 0, false, 0);
+ }
+
+ /**
+ * Creates a new {@link AutofillValue} to autofill a {@link View} representing a toggable
+ * field.
+ *
+ * <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.
+ */
+ public static AutofillValue forToggle(boolean value) {
+ return new AutofillValue(null, 0, value, 0);
+ }
+
+ /**
+ * Creates a new {@link AutofillValue} to autofill a {@link View} representing a selection
+ * list.
+ *
+ * <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.
+ */
+ public static AutofillValue forList(int value) {
+ return new AutofillValue(null, value, false, 0);
+ }
+
+ /**
+ * Creates a new {@link AutofillValue} to autofill a {@link View} representing a date.
+ *
+ * <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.
+ */
+ public static AutofillValue forDate(long value) {
+ return new AutofillValue(null, 0, false, value);
+ }
+}
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index b36c0f1..07d8cab 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -19,8 +19,8 @@
import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder;
-import android.view.autofill.AutoFillId;
-import android.view.autofill.AutoFillValue;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
import android.view.autofill.IAutoFillManagerClient;
/**
@@ -31,10 +31,10 @@
interface IAutoFillManager {
boolean addClient(in IAutoFillManagerClient client, int userId);
oneway void startSession(in IBinder activityToken, IBinder windowToken, in IBinder appCallback,
- in AutoFillId autoFillId, in Rect bounds, in AutoFillValue value, int userId,
+ in AutofillId autoFillId, in Rect bounds, in AutofillValue value, int userId,
boolean hasCallback);
- oneway void updateSession(in IBinder activityToken, in AutoFillId id, in Rect bounds,
- in AutoFillValue value, int flags, int userId);
+ oneway void updateSession(in IBinder activityToken, in AutofillId id, in Rect bounds,
+ in AutofillValue value, int flags, int userId);
oneway void finishSession(in IBinder activityToken, int userId);
oneway void setAuthenticationResult(in Bundle data,
in IBinder activityToken, int userId);
diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
index 9eef7d0..eabf6b1 100644
--- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
@@ -21,24 +21,24 @@
import android.content.Intent;
import android.content.IntentSender;
import android.os.IBinder;
-import android.view.autofill.AutoFillId;
-import android.view.autofill.AutoFillValue;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
/**
- * Object running in the application process and responsible for auto-filling it.
+ * Object running in the application process and responsible for autofilling it.
*
* @hide
*/
oneway interface IAutoFillManagerClient {
/**
- * Notifies the client when the auto-fill enabled state changed.
+ * Notifies the client when the autofill enabled state changed.
*/
void setState(boolean enabled);
/**
- * Auto-fills the activity with the contents of a dataset.
+ * Autofills the activity with the contents of a dataset.
*/
- void autoFill(in List<AutoFillId> ids, in List<AutoFillValue> values);
+ void autofill(in List<AutofillId> ids, in List<AutofillValue> values);
/**
* Authenticates a fill response or a data set.
@@ -48,5 +48,5 @@
/**
* Notifies the client when the auto-fill UI changed.
*/
- void onAutofillEvent(in IBinder windowToken, in AutoFillId id, int event);
+ void onAutofillEvent(in IBinder windowToken, in AutofillId id, int event);
}
diff --git a/core/java/android/view/textclassifier/EntityConfidence.java b/core/java/android/view/textclassifier/EntityConfidence.java
index 7aab71f..0589d204 100644
--- a/core/java/android/view/textclassifier/EntityConfidence.java
+++ b/core/java/android/view/textclassifier/EntityConfidence.java
@@ -42,10 +42,10 @@
float score1 = mEntityConfidence.get(e1);
float score2 = mEntityConfidence.get(e2);
if (score1 > score2) {
- return 1;
+ return -1;
}
if (score1 < score2) {
- return -1;
+ return 1;
}
return 0;
};
diff --git a/core/java/android/view/textclassifier/LangId.java b/core/java/android/view/textclassifier/LangId.java
index 53bc1b0..ada3c37c 100644
--- a/core/java/android/view/textclassifier/LangId.java
+++ b/core/java/android/view/textclassifier/LangId.java
@@ -37,8 +37,8 @@
/**
* Detects the language for given text.
*/
- public String findLanguage(String text) {
- return nativeFindLanguage(mModelPtr, text);
+ public ClassificationResult[] findLanguages(String text) {
+ return nativeFindLanguages(mModelPtr, text);
}
/**
@@ -50,8 +50,20 @@
private static native long nativeNew(int fd);
- private static native String nativeFindLanguage(long context, String text);
+ private static native ClassificationResult[] nativeFindLanguages(
+ long context, String text);
private static native void nativeClose(long context);
-}
+ /** Classification result for findLanguage method. */
+ static final class ClassificationResult {
+ final String mLanguage;
+ /** float range: 0 - 1 */
+ final float mScore;
+
+ ClassificationResult(String language, float score) {
+ mLanguage = language;
+ mScore = score;
+ }
+ }
+}
diff --git a/core/java/android/view/textclassifier/SmartSelection.java b/core/java/android/view/textclassifier/SmartSelection.java
index 47c39e4..c48cd06 100644
--- a/core/java/android/view/textclassifier/SmartSelection.java
+++ b/core/java/android/view/textclassifier/SmartSelection.java
@@ -55,9 +55,11 @@
*
* The begin and end params are character indices in the context string.
*
- * Returns the type of the selection, e.g. "email", "address", "phone".
+ * Returns an array of ClassificationResult objects with the probability
+ * scores for different collections.
*/
- public String classifyText(String context, int selectionBegin, int selectionEnd) {
+ public ClassificationResult[] classifyText(
+ String context, int selectionBegin, int selectionEnd) {
return nativeClassifyText(mCtx, context, selectionBegin, selectionEnd);
}
@@ -73,9 +75,21 @@
private static native int[] nativeSuggest(
long context, String text, int selectionBegin, int selectionEnd);
- private static native String nativeClassifyText(
+ private static native ClassificationResult[] nativeClassifyText(
long context, String text, int selectionBegin, int selectionEnd);
private static native void nativeClose(long context);
+
+ /** Classification result for classifyText method. */
+ static final class ClassificationResult {
+ final String mCollection;
+ /** float range: 0 - 1 */
+ final float mScore;
+
+ ClassificationResult(String collection, float score) {
+ mCollection = collection;
+ mScore = score;
+ }
+ }
}
diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java
index c4d64d1..f032414 100644
--- a/core/java/android/view/textclassifier/TextClassificationManager.java
+++ b/core/java/android/view/textclassifier/TextClassificationManager.java
@@ -85,12 +85,17 @@
Preconditions.checkArgument(text != null);
try {
if (text.length() > 0) {
- final String language = getLanguageDetector().findLanguage(text.toString());
- final Locale locale = new Locale.Builder().setLanguageTag(language).build();
- return Collections.unmodifiableList(Arrays.asList(
- new TextLanguage.Builder(0, text.length())
- .setLanguage(locale, 1.0f /* confidence */)
- .build()));
+ final LangId.ClassificationResult[] results =
+ getLanguageDetector().findLanguages(text.toString());
+ final TextLanguage.Builder tlBuilder = new TextLanguage.Builder(0, text.length());
+ final int size = results.length;
+ for (int i = 0; i < size; i++) {
+ tlBuilder.setLanguage(
+ new Locale.Builder().setLanguageTag(results[i].mLanguage).build(),
+ results[i].mScore);
+ }
+
+ return Collections.unmodifiableList(Arrays.asList(tlBuilder.build()));
}
} catch (Throwable t) {
// Avoid throwing from this method. Log the error.
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 0486f9f..c95a1fb 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -86,10 +86,14 @@
final int start = startEnd[0];
final int end = startEnd[1];
if (start >= 0 && end <= string.length() && start <= end) {
- final String type = getSmartSelection().classifyText(string, start, end);
- return new TextSelection.Builder(start, end)
- .setEntityType(type, 1.0f)
- .build();
+ final TextSelection.Builder tsBuilder = new TextSelection.Builder(start, end);
+ final SmartSelection.ClassificationResult[] results =
+ getSmartSelection().classifyText(string, start, end);
+ final int size = results.length;
+ for (int i = 0; i < size; i++) {
+ tsBuilder.setEntityType(results[i].mCollection, results[i].mScore);
+ }
+ return tsBuilder.build();
} else {
// We can not trust the result. Log the issue and ignore the result.
Log.d(LOG_TAG, "Got bad indices for input text. Ignoring result.");
@@ -113,13 +117,13 @@
try {
if (text.length() > 0) {
final CharSequence classified = text.subSequence(startIndex, endIndex);
- String type = getSmartSelection()
+ SmartSelection.ClassificationResult[] results = getSmartSelection()
.classifyText(text.toString(), startIndex, endIndex);
- if (!TextUtils.isEmpty(type)) {
- type = type.toLowerCase(Locale.ENGLISH).trim();
+ if (results.length > 0) {
// TODO: Added this log for debug only. Remove before release.
- Log.d(LOG_TAG, String.format("Classification type: %s", type));
- return createClassificationResult(type, classified);
+ Log.d(LOG_TAG,
+ String.format("Classification type: %s", results[0].mCollection));
+ return createClassificationResult(results, classified);
}
}
} catch (Throwable t) {
@@ -174,11 +178,17 @@
}
}
- private TextClassificationResult createClassificationResult(String type, CharSequence text) {
+ private TextClassificationResult createClassificationResult(
+ SmartSelection.ClassificationResult[] classifications, CharSequence text) {
final TextClassificationResult.Builder builder = new TextClassificationResult.Builder()
- .setText(text.toString())
- .setEntityType(type, 1.0f /* confidence */);
+ .setText(text.toString());
+ final int size = classifications.length;
+ for (int i = 0; i < size; i++) {
+ builder.setEntityType(classifications[i].mCollection, classifications[i].mScore);
+ }
+
+ final String type = classifications[0].mCollection;
final Intent intent = IntentFactory.create(mContext, type, text.toString());
final PackageManager pm;
final ResolveInfo resolveInfo;
@@ -252,14 +262,17 @@
final int selectionEnd = selection[1];
if (selectionStart >= 0 && selectionEnd <= text.length()
&& selectionStart <= selectionEnd) {
- final String type =
+ final SmartSelection.ClassificationResult[] results =
smartSelection.classifyText(text, selectionStart, selectionEnd);
- if (matches(type, linkMask)) {
- final Intent intent = IntentFactory.create(
- context, type, text.substring(selectionStart, selectionEnd));
- if (hasActivityHandler(context, intent)) {
- final ClickableSpan span = createSpan(context, intent);
- spans.add(new SpanSpec(selectionStart, selectionEnd, span));
+ if (results.length > 0) {
+ final String type = results[0].mCollection;
+ if (matches(type, linkMask)) {
+ final Intent intent = IntentFactory.create(
+ context, type, text.substring(selectionStart, selectionEnd));
+ if (hasActivityHandler(context, intent)) {
+ final ClickableSpan span = createSpan(context, intent);
+ spans.add(new SpanSpec(selectionStart, selectionEnd, span));
+ }
}
}
}
@@ -272,6 +285,7 @@
* Returns true if the classification type matches the specified linkMask.
*/
private static boolean matches(String type, int linkMask) {
+ type = type.trim().toLowerCase(Locale.ENGLISH);
if ((linkMask & Linkify.PHONE_NUMBERS) != 0
&& TextClassifier.TYPE_PHONE.equals(type)) {
return true;
@@ -403,6 +417,7 @@
@Nullable
public static Intent create(Context context, String type, String text) {
+ type = type.trim().toLowerCase(Locale.ENGLISH);
switch (type) {
case TextClassifier.TYPE_EMAIL:
return new Intent(Intent.ACTION_SENDTO)
@@ -418,12 +433,12 @@
.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
default:
return null;
- // TODO: Add other classification types.
}
}
@Nullable
public static String getLabel(Context context, String type) {
+ type = type.trim().toLowerCase(Locale.ENGLISH);
switch (type) {
case TextClassifier.TYPE_EMAIL:
return context.getString(com.android.internal.R.string.email);
@@ -435,7 +450,6 @@
return context.getString(com.android.internal.R.string.browse);
default:
return null;
- // TODO: Add other classification types.
}
}
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 3fbeb03..9a931c2 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2612,8 +2612,8 @@
}
@Override
- public void onProvideAutoFillVirtualStructure(ViewStructure structure, int flags) {
- mProvider.getViewDelegate().onProvideAutoFillVirtualStructure(structure, flags);
+ public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
+ mProvider.getViewDelegate().onProvideAutofillVirtualStructure(structure, flags);
}
/** @hide */
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index ffc18b1..5724a9b 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -318,7 +318,7 @@
public void onProvideVirtualStructure(android.view.ViewStructure structure);
@SuppressWarnings("unused")
- public default void onProvideAutoFillVirtualStructure(android.view.ViewStructure structure,
+ public default void onProvideAutofillVirtualStructure(android.view.ViewStructure structure,
int flags) {
}
diff --git a/core/java/android/widget/AbsSpinner.java b/core/java/android/widget/AbsSpinner.java
index e6cd566..053574f 100644
--- a/core/java/android/widget/AbsSpinner.java
+++ b/core/java/android/widget/AbsSpinner.java
@@ -27,7 +27,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStructure;
-import android.view.autofill.AutoFillValue;
+import android.view.autofill.AutofillValue;
import com.android.internal.R;
@@ -492,8 +492,8 @@
// TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable)
@Override
- public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
- super.onProvideAutoFillStructure(structure, flags);
+ public void onProvideAutofillStructure(ViewStructure structure, int flags) {
+ super.onProvideAutofillStructure(structure, flags);
if (getAdapter() == null) return;
@@ -506,12 +506,12 @@
for (int i = 0; i < count; i++) {
options[i] = getAdapter().getItem(i).toString();
}
- structure.setAutoFillOptions(options);
+ structure.setAutofillOptions(options);
}
}
@Override
- public void autoFill(AutoFillValue value) {
+ public void autofill(AutofillValue value) {
if (!isEnabled()) return;
final int position = value.getListValue();
@@ -524,7 +524,7 @@
}
@Override
- public AutoFillValue getAutoFillValue() {
- return isEnabled() ? AutoFillValue.forList(getSelectedItemPosition()) : null;
+ public AutofillValue getAutofillValue() {
+ return isEnabled() ? AutofillValue.forList(getSelectedItemPosition()) : null;
}
}
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 0b3cff1..e5505a6 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -34,7 +34,7 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.autofill.AutoFillManager;
+import android.view.autofill.AutofillManager;
/**
* An AdapterView is a view whose children are determined by an {@link Adapter}.
@@ -915,8 +915,8 @@
dispatchOnItemSelected();
}
}
- // Always notify AutoFillManager - it will return right away if auto-fill is disabled.
- final AutoFillManager afm = mContext.getSystemService(AutoFillManager.class);
+ // Always notify AutoFillManager - it will return right away if autofill is disabled.
+ final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
if (afm != null) {
afm.valueChanged(this);
}
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index dce33a0..81aec9c 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -35,8 +35,8 @@
import android.view.ViewStructure;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.autofill.AutoFillManager;
-import android.view.autofill.AutoFillValue;
+import android.view.autofill.AutofillManager;
+import android.view.autofill.AutofillValue;
import com.android.internal.R;
@@ -69,7 +69,7 @@
private OnCheckedChangeListener mOnCheckedChangeWidgetListener;
// Indicates whether the toggle state was set from resources or dynamically, so it can be used
- // to sanitize auto-fill requests.
+ // to sanitize autofill requests.
private boolean mCheckedFromResource = false;
private static final int[] CHECKED_STATE_SET = {
@@ -171,7 +171,7 @@
if (mOnCheckedChangeWidgetListener != null) {
mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked);
}
- final AutoFillManager afm = mContext.getSystemService(AutoFillManager.class);
+ final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
if (afm != null) {
afm.valueChanged(this);
}
@@ -572,17 +572,17 @@
stream.addProperty("checked", isChecked());
}
- // TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable)
+ // TODO(b/33197203): add unit/CTS tests for autofill methods (and make sure they handle enable)
@Override
- public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
- super.onProvideAutoFillStructure(structure, flags);
+ public void onProvideAutofillStructure(ViewStructure structure, int flags) {
+ super.onProvideAutofillStructure(structure, flags);
structure.setSanitized(mCheckedFromResource);
}
@Override
- public void autoFill(AutoFillValue value) {
+ public void autofill(AutofillValue value) {
if (!isEnabled()) return;
setChecked(value.getToggleValue());
@@ -594,7 +594,7 @@
}
@Override
- public AutoFillValue getAutoFillValue() {
- return isEnabled() ? AutoFillValue.forToggle(isChecked()) : null;
+ public AutofillValue getAutofillValue() {
+ return isEnabled() ? AutofillValue.forToggle(isChecked()) : null;
}
}
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index c905172..fa8316c 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -33,8 +33,8 @@
import android.view.View;
import android.view.ViewStructure;
import android.view.accessibility.AccessibilityEvent;
-import android.view.autofill.AutoFillManager;
-import android.view.autofill.AutoFillValue;
+import android.view.autofill.AutofillManager;
+import android.view.autofill.AutofillValue;
import com.android.internal.R;
@@ -180,7 +180,7 @@
}
mDelegate.setAutoFillChangeListener((v, y, m, d) -> {
- final AutoFillManager afm = context.getSystemService(AutoFillManager.class);
+ final AutofillManager afm = context.getSystemService(AutofillManager.class);
if (afm != null) {
afm.valueChanged(this);
}
@@ -761,18 +761,18 @@
void onValidationChanged(boolean valid);
}
- // TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable)
+ // TODO(b/33197203): add unit/CTS tests for autofill methods (and make sure they handle enable)
@Override
- public void dispatchProvideAutoFillStructure(ViewStructure structure, int flags) {
- // This view is self-sufficient for auto-fill, so it needs to call
+ public void dispatchProvideAutofillStructure(ViewStructure structure, int flags) {
+ // This view is self-sufficient for autofill, so it needs to call
// onProvideAutoFillStructure() to fill itself, but it does not need to call
// dispatchProvideAutoFillStructure() to fill its children.
- onProvideAutoFillStructure(structure, flags);
+ onProvideAutofillStructure(structure, flags);
}
@Override
- public void autoFill(AutoFillValue value) {
+ public void autofill(AutofillValue value) {
if (!isEnabled()) return;
mDelegate.updateDate(value.getDateValue());
@@ -784,7 +784,7 @@
}
@Override
- public AutoFillValue getAutoFillValue() {
- return isEnabled() ? AutoFillValue.forDate(mDelegate.getDate()) : null;
+ public AutofillValue getAutofillValue() {
+ return isEnabled() ? AutofillValue.forDate(mDelegate.getDate()) : null;
}
}
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index bb8cd28..bd62d6c 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -16,7 +16,6 @@
package android.widget;
-
import android.annotation.IdRes;
import android.content.Context;
import android.content.res.TypedArray;
@@ -25,8 +24,8 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStructure;
-import android.view.autofill.AutoFillManager;
-import android.view.autofill.AutoFillValue;
+import android.view.autofill.AutofillManager;
+import android.view.autofill.AutofillValue;
import com.android.internal.R;
@@ -67,7 +66,7 @@
private PassThroughHierarchyChangeListener mPassThroughListener;
// Indicates whether the child was set from resources or dynamically, so it can be used
- // to sanitize auto-fill requests.
+ // to sanitize autofill requests.
private int mInitialCheckedId = View.NO_ID;
/**
@@ -187,7 +186,7 @@
if (mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
}
- final AutoFillManager afm = mContext.getSystemService(AutoFillManager.class);
+ final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
if (afm != null) {
afm.valueChanged(this);
}
@@ -417,16 +416,16 @@
}
}
- // TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable)
+ // TODO(b/33197203): add unit/CTS tests for autofill methods (and make sure they handle enable)
@Override
- public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
- super.onProvideAutoFillStructure(structure, flags);
+ public void onProvideAutofillStructure(ViewStructure structure, int flags) {
+ super.onProvideAutofillStructure(structure, flags);
structure.setSanitized(mCheckedId == mInitialCheckedId);
}
@Override
- public void autoFill(AutoFillValue value) {
+ public void autofill(AutofillValue value) {
if (!isEnabled()) return;
final int index = value.getListValue();
@@ -444,14 +443,14 @@
}
@Override
- public AutoFillValue getAutoFillValue() {
+ public AutofillValue getAutofillValue() {
if (!isEnabled()) return null;
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getId() == mCheckedId) {
- return AutoFillValue.forList(i);
+ return AutofillValue.forList(i);
}
}
return null;
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index 3811e1a..ddf0e74 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -41,7 +41,6 @@
import android.view.PointerIcon;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewStructure;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -914,27 +913,6 @@
return super.onResolvePointerIcon(event, pointerIndex);
}
- // TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable)
-
- @Override
- public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
- super.onProvideAutoFillStructure(structure, flags);
-
- if (getAdapter() == null) return;
-
- // TODO(b/33197203): implement sanitization so initial value is only sanitized when coming
- // from resources.
-
- final int count = getAdapter().getCount();
- if (count > 0) {
- final String[] options = new String[count];
- for (int i = 0; i < count; i++) {
- options[i] = getAdapter().getItem(i).toString();
- }
- structure.setAutoFillOptions(options);
- }
- }
-
static class SavedState extends AbsSpinner.SavedState {
boolean showDropdown;
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index a9257e6..40253a1 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -1406,17 +1406,17 @@
@Override
public void onProvideStructure(ViewStructure structure) {
super.onProvideStructure(structure);
- onProvideAutoFillStructureForAssistOrAutoFill(structure);
+ onProvideAutoFillStructureForAssistOrAutofill(structure);
}
@Override
- public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
- super.onProvideAutoFillStructure(structure, flags);
- onProvideAutoFillStructureForAssistOrAutoFill(structure);
+ public void onProvideAutofillStructure(ViewStructure structure, int flags) {
+ super.onProvideAutofillStructure(structure, flags);
+ onProvideAutoFillStructureForAssistOrAutofill(structure);
}
// NOTE: currently there is no difference for Assist or AutoFill, so it doesn't take flags
- private void onProvideAutoFillStructureForAssistOrAutoFill(ViewStructure structure) {
+ private void onProvideAutoFillStructureForAssistOrAutofill(ViewStructure structure) {
CharSequence switchText = isChecked() ? mTextOn : mTextOff;
if (!TextUtils.isEmpty(switchText)) {
CharSequence oldText = structure.getText();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b901ab4..ee70acc 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -140,8 +140,8 @@
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AnimationUtils;
-import android.view.autofill.AutoFillManager;
-import android.view.autofill.AutoFillValue;
+import android.view.autofill.AutofillManager;
+import android.view.autofill.AutofillValue;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
@@ -732,7 +732,7 @@
private boolean mHasPresetAutoSizeValues = false;
// Indicates whether the text was set from resources or dynamically, so it can be used to
- // sanitize auto-fill requests.
+ // sanitize autofill requests.
private boolean mTextFromResource = false;
/**
@@ -5231,7 +5231,7 @@
if (needEditableForNotification) {
sendAfterTextChanged((Editable) text);
} else {
- // Always notify AutoFillManager - it will return right away if auto-fill is disabled.
+ // Always notify AutoFillManager - it will return right away if autofill is disabled.
notifyAutoFillManagerAfterTextChanged();
}
@@ -9124,14 +9124,14 @@
}
}
- // Always notify AutoFillManager - it will return right away if auto-fill is disabled.
+ // Always notify AutoFillManager - it will return right away if autofill is disabled.
notifyAutoFillManagerAfterTextChanged();
hideErrorIfUnchanged();
}
private void notifyAutoFillManagerAfterTextChanged() {
- final AutoFillManager afm = mContext.getSystemService(AutoFillManager.class);
+ final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
if (afm != null) {
if (DEBUG_AUTOFILL) {
Log.v(LOG_TAG, "sendAfterTextChanged(): notify AFM for text=" + mText);
@@ -9886,24 +9886,24 @@
@Override
public void onProvideStructure(ViewStructure structure) {
super.onProvideStructure(structure);
- onProvideAutoStructureForAssistOrAutoFill(structure, false);
+ onProvideAutoStructureForAssistOrAutofill(structure, false);
}
@Override
- public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
- super.onProvideAutoFillStructure(structure, flags);
- onProvideAutoStructureForAssistOrAutoFill(structure, true);
+ public void onProvideAutofillStructure(ViewStructure structure, int flags) {
+ super.onProvideAutofillStructure(structure, flags);
+ onProvideAutoStructureForAssistOrAutofill(structure, true);
}
- private void onProvideAutoStructureForAssistOrAutoFill(ViewStructure structure,
- boolean forAutoFill) {
+ private void onProvideAutoStructureForAssistOrAutofill(ViewStructure structure,
+ boolean forAutofill) {
final boolean isPassword = hasPasswordTransformationMethod()
|| isPasswordInputType(getInputType());
- if (forAutoFill) {
+ if (forAutofill) {
structure.setSanitized(mTextFromResource);
}
- if (!isPassword || forAutoFill) {
+ if (!isPassword || forAutofill) {
if (mLayout == null) {
assumeLayout();
}
@@ -10010,10 +10010,10 @@
structure.setInputType(getInputType());
}
- // TODO(b/33197203): add unit/CTS tests for auto-fill methods
+ // TODO(b/33197203): add unit/CTS tests for autofill methods
@Override
- public void autoFill(AutoFillValue value) {
+ public void autofill(AutofillValue value) {
final CharSequence text = value.getTextValue();
if (text != null && isTextEditable()) {
@@ -10028,8 +10028,8 @@
@Override
@Nullable
- public AutoFillValue getAutoFillValue() {
- return isTextEditable() ? AutoFillValue.forText(getText()) : null;
+ public AutofillValue getAutofillValue() {
+ return isTextEditable() ? AutofillValue.forText(getText()) : null;
}
/** @hide */
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 3a19f21..1435983 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -31,8 +31,8 @@
import android.view.View;
import android.view.ViewStructure;
import android.view.accessibility.AccessibilityEvent;
-import android.view.autofill.AutoFillManager;
-import android.view.autofill.AutoFillValue;
+import android.view.autofill.AutofillManager;
+import android.view.autofill.AutofillValue;
import com.android.internal.R;
@@ -142,7 +142,7 @@
break;
}
mDelegate.setAutoFillChangeListener((v, h, m) -> {
- final AutoFillManager afm = context.getSystemService(AutoFillManager.class);
+ final AutofillManager afm = context.getSystemService(AutofillManager.class);
if (afm != null) {
afm.valueChanged(this);
}
@@ -516,18 +516,18 @@
}
}
- // TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable)
+ // TODO(b/33197203): add unit/CTS tests for autofill methods (and make sure they handle enable)
@Override
- public void dispatchProvideAutoFillStructure(ViewStructure structure, int flags) {
- // This view is self-sufficient for auto-fill, so it needs to call
+ public void dispatchProvideAutofillStructure(ViewStructure structure, int flags) {
+ // This view is self-sufficient for autofill, so it needs to call
// onProvideAutoFillStructure() to fill itself, but it does not need to call
// dispatchProvideAutoFillStructure() to fill its children.
- onProvideAutoFillStructure(structure, flags);
+ onProvideAutofillStructure(structure, flags);
}
@Override
- public void autoFill(AutoFillValue value) {
+ public void autofill(AutofillValue value) {
if (!isEnabled()) return;
mDelegate.setDate(value.getDateValue());
@@ -539,7 +539,7 @@
}
@Override
- public AutoFillValue getAutoFillValue() {
- return isEnabled() ? AutoFillValue.forDate(mDelegate.getDate()) : null;
+ public AutofillValue getAutofillValue() {
+ return isEnabled() ? AutofillValue.forDate(mDelegate.getDate()) : null;
}
}
diff --git a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
index cf1bf62..c6cb837 100644
--- a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
+++ b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
@@ -19,6 +19,7 @@
import com.android.internal.R;
import android.content.Context;
+import android.os.Build;
import android.provider.Settings;
import android.text.TextUtils;
@@ -29,20 +30,21 @@
public AmbientDisplayConfiguration(Context context) {
mContext = context;
}
-
+
public boolean enabled(int user) {
return pulseOnNotificationEnabled(user)
|| pulseOnPickupEnabled(user)
- || pulseOnDoubleTapEnabled(user);
+ || pulseOnDoubleTapEnabled(user)
+ || alwaysOnEnabled(user);
}
-
+
public boolean available() {
return pulseOnNotificationAvailable() || pulseOnPickupAvailable()
|| pulseOnDoubleTapAvailable();
}
-
+
public boolean pulseOnNotificationEnabled(int user) {
- return boolSetting(Settings.Secure.DOZE_ENABLED, user) && pulseOnNotificationAvailable();
+ return boolSettingDefaultOn(Settings.Secure.DOZE_ENABLED, user) && pulseOnNotificationAvailable();
}
public boolean pulseOnNotificationAvailable() {
@@ -50,17 +52,17 @@
}
public boolean pulseOnPickupEnabled(int user) {
- return boolSetting(Settings.Secure.DOZE_PULSE_ON_PICK_UP, user)
+ return boolSettingDefaultOn(Settings.Secure.DOZE_PULSE_ON_PICK_UP, user)
&& pulseOnPickupAvailable();
}
-
+
public boolean pulseOnPickupAvailable() {
return mContext.getResources().getBoolean(R.bool.config_dozePulsePickup)
&& ambientDisplayAvailable();
}
-
+
public boolean pulseOnDoubleTapEnabled(int user) {
- return boolSetting(Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP, user)
+ return boolSettingDefaultOn(Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP, user)
&& pulseOnDoubleTapAvailable();
}
@@ -72,6 +74,16 @@
return mContext.getResources().getString(R.string.config_dozeDoubleTapSensorType);
}
+ public boolean alwaysOnEnabled(int user) {
+ return boolSettingDefaultOff(Settings.Secure.DOZE_ALWAYS_ON, user)
+ && alwaysOnAvailable();
+ }
+
+ public boolean alwaysOnAvailable() {
+ // TODO: introduce config_dozeAlwaysOnAvailable. For now just debuggable builds.
+ return Build.IS_DEBUGGABLE && ambientDisplayAvailable();
+ }
+
public String ambientDisplayComponent() {
return mContext.getResources().getString(R.string.config_dozeComponent);
}
@@ -80,8 +92,15 @@
return !TextUtils.isEmpty(ambientDisplayComponent());
}
- private boolean boolSetting(String name, int user) {
- return Settings.Secure.getIntForUser(mContext.getContentResolver(), name, 1, user) != 0;
+ private boolean boolSettingDefaultOn(String name, int user) {
+ return boolSetting(name, user, 1);
}
+ private boolean boolSettingDefaultOff(String name, int user) {
+ return boolSetting(name, user, 0);
+ }
+
+ private boolean boolSetting(String name, int user, int def) {
+ return Settings.Secure.getIntForUser(mContext.getContentResolver(), name, def, user) != 0;
+ }
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 7ff115b..a8e16c9 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -16,6 +16,7 @@
package com.android.internal.policy;
+import android.view.accessibility.AccessibilityNodeInfo;
import com.android.internal.R;
import com.android.internal.policy.PhoneWindow.PanelFeatureState;
import com.android.internal.policy.PhoneWindow.PhoneWindowMenuCallback;
@@ -2251,6 +2252,11 @@
}
@Override
+ public int getAccessibilityViewId() {
+ return AccessibilityNodeInfo.ROOT_ITEM_ID;
+ }
+
+ @Override
public String toString() {
return "DecorView@" + Integer.toHexString(this.hashCode()) + "["
+ getTitleSuffix(mWindow.getAttributes()) + "]";
diff --git a/core/java/com/android/internal/policy/PipSnapAlgorithm.java b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
index f88ac49..ae31873 100644
--- a/core/java/com/android/internal/policy/PipSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
@@ -36,15 +36,18 @@
*/
public class PipSnapAlgorithm {
+ // The below SNAP_MODE_* constants correspond to the config resource value
+ // config_pictureInPictureSnapMode and should not be changed independently.
// Allows snapping to the four corners
private static final int SNAP_MODE_CORNERS_ONLY = 0;
// Allows snapping to the four corners and the mid-points on the long edge in each orientation
private static final int SNAP_MODE_CORNERS_AND_SIDES = 1;
// Allows snapping to anywhere along the edge of the screen
private static final int SNAP_MODE_EDGE = 2;
- // Allows snapping to four corners on a fling towards a corner or slow move near a corner
- // snaps anywhere along the edge of screen otherwise
- private static final int SNAP_MODE_CORNERS_AND_EDGES = 3;
+ // Allows snapping anywhere along the edge of the screen and magnets towards corners
+ private static final int SNAP_MODE_EDGE_MAGNET_CORNERS = 3;
+ // Allows snapping on the long edge in each orientation and magnets towards corners
+ private static final int SNAP_MODE_LONG_EDGE_MAGNET_CORNERS = 4;
// The friction multiplier to control how slippery the PIP is when flung
private static final float SCROLL_FRICTION_MULTIPLIER = 8f;
@@ -55,7 +58,7 @@
private final Context mContext;
private final ArrayList<Integer> mSnapGravities = new ArrayList<>();
- private final int mDefaultSnapMode = SNAP_MODE_CORNERS_AND_EDGES;
+ private final int mDefaultSnapMode = SNAP_MODE_EDGE_MAGNET_CORNERS;
private int mSnapMode = mDefaultSnapMode;
private final float mDefaultSizePercent;
@@ -85,7 +88,9 @@
* Updates the snap algorithm when the configuration changes.
*/
public void onConfigurationChanged() {
- mOrientation = mContext.getResources().getConfiguration().orientation;
+ Resources res = mContext.getResources();
+ mOrientation = res.getConfiguration().orientation;
+ mSnapMode = res.getInteger(com.android.internal.R.integer.config_pictureInPictureSnapMode);
calculateSnapTargets();
}
@@ -127,7 +132,8 @@
movementBounds.right + stackBounds.width(),
movementBounds.bottom + stackBounds.height());
final Rect newBounds = new Rect(stackBounds);
- if (mSnapMode == SNAP_MODE_CORNERS_AND_EDGES) {
+ if (mSnapMode == SNAP_MODE_LONG_EDGE_MAGNET_CORNERS
+ || mSnapMode == SNAP_MODE_EDGE_MAGNET_CORNERS) {
final Rect tmpBounds = new Rect();
final Point[] snapTargets = new Point[mSnapGravities.size()];
for (int i = 0; i < mSnapGravities.size(); i++) {
@@ -137,11 +143,11 @@
}
Point snapTarget = findClosestPoint(stackBounds.left, stackBounds.top, snapTargets);
float distance = distanceToPoint(snapTarget, stackBounds.left, stackBounds.top);
- final float thresh = stackBounds.width() * CORNER_MAGNET_THRESHOLD;
+ final float thresh = Math.max(stackBounds.width(), stackBounds.height())
+ * CORNER_MAGNET_THRESHOLD;
if (distance < thresh) {
newBounds.offsetTo(snapTarget.x, snapTarget.y);
} else {
- // Otherwise we snap to the edge
snapRectToClosestEdge(stackBounds, movementBounds, newBounds);
}
} else if (mSnapMode == SNAP_MODE_EDGE) {
@@ -324,11 +330,20 @@
final int fromTop = Math.abs(stackBounds.top - movementBounds.top);
final int fromRight = Math.abs(movementBounds.right - stackBounds.left);
final int fromBottom = Math.abs(movementBounds.bottom - stackBounds.top);
- if (fromLeft <= fromTop && fromLeft <= fromRight && fromLeft <= fromBottom) {
+ int shortest;
+ if (mSnapMode == SNAP_MODE_LONG_EDGE_MAGNET_CORNERS) {
+ // Only check longest edges
+ shortest = (mOrientation == Configuration.ORIENTATION_LANDSCAPE)
+ ? Math.min(fromTop, fromBottom)
+ : Math.min(fromLeft, fromRight);
+ } else {
+ shortest = Math.min(Math.min(fromLeft, fromRight), Math.min(fromTop, fromBottom));
+ }
+ if (shortest == fromLeft) {
boundsOut.offsetTo(movementBounds.left, boundedTop);
- } else if (fromTop <= fromLeft && fromTop <= fromRight && fromTop <= fromBottom) {
+ } else if (shortest == fromTop) {
boundsOut.offsetTo(boundedLeft, movementBounds.top);
- } else if (fromRight < fromLeft && fromRight < fromTop && fromRight < fromBottom) {
+ } else if (shortest == fromRight) {
boundsOut.offsetTo(movementBounds.right, boundedTop);
} else {
boundsOut.offsetTo(boundedLeft, movementBounds.bottom);
@@ -358,7 +373,8 @@
}
// Fall through
case SNAP_MODE_CORNERS_ONLY:
- case SNAP_MODE_CORNERS_AND_EDGES:
+ case SNAP_MODE_EDGE_MAGNET_CORNERS:
+ case SNAP_MODE_LONG_EDGE_MAGNET_CORNERS:
mSnapGravities.add(Gravity.TOP | Gravity.LEFT);
mSnapGravities.add(Gravity.TOP | Gravity.RIGHT);
mSnapGravities.add(Gravity.BOTTOM | Gravity.LEFT);
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index be69d9f8..d0fbe7c 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -237,6 +237,35 @@
return false;
}
+ @NonNull
+ public static <T> List<T> filter(@Nullable List<?> list, Class<T> c) {
+ if (isEmpty(list)) return Collections.emptyList();
+ ArrayList<T> result = null;
+ for (int i = 0; i < list.size(); i++) {
+ final Object item = list.get(i);
+ if (c.isInstance(item)) {
+ result = add(result, (T) item);
+ }
+ }
+ return emptyIfNull(result);
+ }
+
+ public static <T> boolean any(@Nullable List<T> items,
+ java.util.function.Predicate<T> predicate) {
+ return find(items, predicate) != null;
+ }
+
+ @Nullable
+ public static <T> T find(@Nullable List<T> items,
+ java.util.function.Predicate<T> predicate) {
+ if (isEmpty(items)) return null;
+ for (int i = 0; i < items.size(); i++) {
+ final T item = items.get(i);
+ if (predicate.test(item)) return item;
+ }
+ return null;
+ }
+
public static long total(@Nullable long[] array) {
long total = 0;
if (array != null) {
diff --git a/core/java/com/android/internal/util/BitUtils.java b/core/java/com/android/internal/util/BitUtils.java
new file mode 100644
index 0000000..a208ccb
--- /dev/null
+++ b/core/java/com/android/internal/util/BitUtils.java
@@ -0,0 +1,58 @@
+/*
+ * 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.internal.util;
+
+import android.annotation.Nullable;
+
+import libcore.util.Objects;
+
+import java.util.Arrays;
+import java.util.UUID;
+
+public class BitUtils {
+ private BitUtils() {}
+
+ public static boolean maskedEquals(long a, long b, long mask) {
+ return (a & mask) == (b & mask);
+ }
+
+ public static boolean maskedEquals(byte a, byte b, byte mask) {
+ return (a & mask) == (b & mask);
+ }
+
+ public static boolean maskedEquals(byte[] a, byte[] b, @Nullable byte[] mask) {
+ if (a == null || b == null) return a == b;
+ Preconditions.checkArgument(a.length == b.length, "Inputs must be of same size");
+ if (mask == null) return Arrays.equals(a, b);
+ Preconditions.checkArgument(a.length == mask.length, "Mask must be of same size as inputs");
+ for (int i = 0; i < mask.length; i++) {
+ if (!maskedEquals(a[i], b[i], mask[i])) return false;
+ }
+ return true;
+ }
+
+ public static boolean maskedEquals(UUID a, UUID b, @Nullable UUID mask) {
+ if (mask == null) {
+ return Objects.equal(a, b);
+ }
+ return maskedEquals(a.getLeastSignificantBits(), b.getLeastSignificantBits(),
+ mask.getLeastSignificantBits())
+ && maskedEquals(a.getMostSignificantBits(), b.getMostSignificantBits(),
+ mask.getMostSignificantBits());
+ }
+}
diff --git a/core/java/com/android/internal/view/SurfaceCallbackHelper.java b/core/java/com/android/internal/view/SurfaceCallbackHelper.java
index 5b6a82c..507b673 100644
--- a/core/java/com/android/internal/view/SurfaceCallbackHelper.java
+++ b/core/java/com/android/internal/view/SurfaceCallbackHelper.java
@@ -17,14 +17,11 @@
package com.android.internal.view;
import android.os.RemoteException;
-import android.view.IWindow;
-import android.view.IWindowSession;
import android.view.Surface;
import android.view.SurfaceHolder;
public class SurfaceCallbackHelper {
- IWindowSession mSession;
- IWindow.Stub mWindow;
+ Runnable mRunnable;
int mFinishDrawingCollected = 0;
int mFinishDrawingExpected = 0;
@@ -37,26 +34,18 @@
if (mFinishDrawingCollected < mFinishDrawingExpected) {
return;
}
- try {
- mSession.finishDrawing(mWindow);
- } catch (RemoteException e) {
- }
+ mRunnable.run();
}
}
};
- public SurfaceCallbackHelper(IWindowSession session,
- IWindow.Stub window) {
- mSession = session;
- mWindow = window;
+ public SurfaceCallbackHelper(Runnable callbacksCollected) {
+ mRunnable = callbacksCollected;
}
public void dispatchSurfaceRedrawNeededAsync(SurfaceHolder holder, SurfaceHolder.Callback callbacks[]) {
if (callbacks == null || callbacks.length == 0) {
- try {
- mSession.finishDrawing(mWindow);
- } catch (RemoteException e) {
- }
+ mRunnable.run();
return;
}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index c9f9d6f..95b25932 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -197,7 +197,6 @@
$(JNI_H_INCLUDE) \
$(LOCAL_PATH)/android/graphics \
$(LOCAL_PATH)/../../libs/hwui \
- $(LOCAL_PATH)/../../../native/opengl/libs \
$(LOCAL_PATH)/../../../native/vulkan/include \
$(call include-path-for, bluedroid) \
$(call include-path-for, libhardware)/hardware \
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 417ef8a0..c1bb69d 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -633,8 +633,7 @@
return nullObjectReturn("Could not open file");
}
- std::unique_ptr<SkFILEStream> fileStream(new SkFILEStream(file,
- SkFILEStream::kCallerPasses_Ownership));
+ std::unique_ptr<SkFILEStream> fileStream(new SkFILEStream(file));
// If there is no offset for the file descriptor, we use SkFILEStream directly.
if (::lseek(descriptor, 0, SEEK_CUR) == 0) {
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 7e417b4..a77ed62 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -42,53 +42,16 @@
///////////////////////////////////////////////////////////////////////////////////////////////
-static void Shader_destructor(JNIEnv* env, jobject o, jlong shaderHandle, jlong shaderWithLMHandle)
-{
+static void Shader_safeUnref(JNIEnv* env, jobject o, jlong shaderHandle) {
SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
SkSafeUnref(shader);
}
-static jlong Shader_setLocalMatrix(JNIEnv* env, jobject o, jlong shaderHandle, jlong matrixHandle)
-{
- // ensure we have a valid matrix to use
- const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
- if (NULL == matrix) {
- matrix = &SkMatrix::I();
- }
-
- // The current shader will no longer need a direct reference owned by Shader.java
- // as all the data needed is contained within the newly created LocalMatrixShader.
- SkASSERT(shaderHandle);
- sk_sp<SkShader> currentShader(reinterpret_cast<SkShader*>(shaderHandle));
-
- // Attempt to peel off an existing proxy shader and get the proxy's matrix. If
- // the proxy existed and it's matrix equals the desired matrix then just return
- // the proxy, otherwise replace it with a new proxy containing the desired matrix.
- //
- // refAsALocalMatrixShader(): if the shader contains a proxy then it unwraps the proxy
- // returning both the underlying shader and the proxy's matrix.
- // newWithLocalMatrix(): will return a proxy shader that wraps the provided shader and
- // concats the provided local matrix with the shader's matrix.
- //
- // WARNING: This proxy replacement only behaves like a setter because the Java
- // API enforces that all local matrices are set using this call and
- // not passed to the constructor of the Shader.
- SkMatrix proxyMatrix;
- sk_sp<SkShader> baseShader = currentShader->makeAsALocalMatrixShader(&proxyMatrix);
- if (baseShader.get()) {
- if (proxyMatrix == *matrix) {
- return reinterpret_cast<jlong>(currentShader.release());
- }
- return reinterpret_cast<jlong>(baseShader->makeWithLocalMatrix(*matrix).release());
- }
- return reinterpret_cast<jlong>(currentShader->makeWithLocalMatrix(*matrix).release());
-}
-
///////////////////////////////////////////////////////////////////////////////////////////////
-static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jobject jbitmap,
- jint tileModeX, jint tileModeY)
-{
+static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, jobject jbitmap,
+ jint tileModeX, jint tileModeY) {
+ const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
SkBitmap bitmap;
if (jbitmap) {
// Only pass a valid SkBitmap object to the constructor if the Bitmap exists. Otherwise,
@@ -97,8 +60,8 @@
}
sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
- sk_sp<SkShader> shader = image->makeShader((SkShader::TileMode)tileModeX,
- (SkShader::TileMode)tileModeY);
+ sk_sp<SkShader> shader = image->makeShader(
+ (SkShader::TileMode)tileModeX, (SkShader::TileMode)tileModeY, matrix);
ThrowIAE_IfNull(env, shader.get());
return reinterpret_cast<jlong>(shader.release());
@@ -106,10 +69,10 @@
///////////////////////////////////////////////////////////////////////////////////////////////
-static jlong LinearGradient_create1(JNIEnv* env, jobject o,
- jfloat x0, jfloat y0, jfloat x1, jfloat y1,
- jintArray colorArray, jfloatArray posArray, jint tileMode)
-{
+static jlong LinearGradient_create1(JNIEnv* env, jobject o, jlong matrixPtr,
+ jfloat x0, jfloat y0, jfloat x1, jfloat y1,
+ jintArray colorArray, jfloatArray posArray, jint tileMode) {
+ const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
SkPoint pts[2];
pts[0].set(x0, y0);
pts[1].set(x1, y1);
@@ -126,17 +89,17 @@
SkShader* shader = SkGradientShader::MakeLinear(pts,
reinterpret_cast<const SkColor*>(colorValues), pos, count,
- static_cast<SkShader::TileMode>(tileMode)).release();
+ static_cast<SkShader::TileMode>(tileMode), /* flags */ 0, matrix).release();
env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
ThrowIAE_IfNull(env, shader);
return reinterpret_cast<jlong>(shader);
}
-static jlong LinearGradient_create2(JNIEnv* env, jobject o,
- jfloat x0, jfloat y0, jfloat x1, jfloat y1,
- jint color0, jint color1, jint tileMode)
-{
+static jlong LinearGradient_create2(JNIEnv* env, jobject o, jlong matrixPtr,
+ jfloat x0, jfloat y0, jfloat x1, jfloat y1, jint color0, jint color1, jint tileMode) {
+ const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
+
SkPoint pts[2];
pts[0].set(x0, y0);
pts[1].set(x1, y1);
@@ -145,7 +108,8 @@
colors[0] = color0;
colors[1] = color1;
- SkShader* s = SkGradientShader::MakeLinear(pts, colors, NULL, 2, (SkShader::TileMode)tileMode).release();
+ SkShader* s = SkGradientShader::MakeLinear(pts, colors, NULL, 2,
+ (SkShader::TileMode)tileMode, /* flags */ 0, matrix).release();
ThrowIAE_IfNull(env, s);
return reinterpret_cast<jlong>(s);
@@ -153,8 +117,9 @@
///////////////////////////////////////////////////////////////////////////////////////////////
-static jlong RadialGradient_create1(JNIEnv* env, jobject, jfloat x, jfloat y, jfloat radius,
- jintArray colorArray, jfloatArray posArray, jint tileMode) {
+static jlong RadialGradient_create1(JNIEnv* env, jobject, jlong matrixPtr, jfloat x, jfloat y,
+ jfloat radius, jintArray colorArray, jfloatArray posArray, jint tileMode) {
+ const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
SkPoint center;
center.set(x, y);
@@ -170,7 +135,7 @@
SkShader* shader = SkGradientShader::MakeRadial(center, radius,
reinterpret_cast<const SkColor*>(colorValues), pos, count,
- static_cast<SkShader::TileMode>(tileMode)).release();
+ static_cast<SkShader::TileMode>(tileMode), /* flags */ 0, matrix).release();
env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues),
JNI_ABORT);
@@ -178,8 +143,9 @@
return reinterpret_cast<jlong>(shader);
}
-static jlong RadialGradient_create2(JNIEnv* env, jobject, jfloat x, jfloat y, jfloat radius,
+static jlong RadialGradient_create2(JNIEnv* env, jobject, jlong matrixPtr, jfloat x, jfloat y, jfloat radius,
jint color0, jint color1, jint tileMode) {
+ const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
SkPoint center;
center.set(x, y);
@@ -188,15 +154,16 @@
colors[1] = color1;
SkShader* s = SkGradientShader::MakeRadial(center, radius, colors, NULL, 2,
- (SkShader::TileMode)tileMode).release();
+ (SkShader::TileMode)tileMode, /* flags */ 0, matrix).release();
ThrowIAE_IfNull(env, s);
return reinterpret_cast<jlong>(s);
}
///////////////////////////////////////////////////////////////////////////////
-static jlong SweepGradient_create1(JNIEnv* env, jobject, jfloat x, jfloat y,
+static jlong SweepGradient_create1(JNIEnv* env, jobject, jlong matrixPtr, jfloat x, jfloat y,
jintArray jcolors, jfloatArray jpositions) {
+ const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
size_t count = env->GetArrayLength(jcolors);
const jint* colors = env->GetIntArrayElements(jcolors, NULL);
@@ -208,70 +175,78 @@
#endif
SkShader* shader = SkGradientShader::MakeSweep(x, y,
- reinterpret_cast<const SkColor*>(colors), pos, count).release();
+ reinterpret_cast<const SkColor*>(colors), pos, count, /* flags */ 0, matrix).release();
env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors),
JNI_ABORT);
ThrowIAE_IfNull(env, shader);
return reinterpret_cast<jlong>(shader);
}
-static jlong SweepGradient_create2(JNIEnv* env, jobject, jfloat x, jfloat y,
+static jlong SweepGradient_create2(JNIEnv* env, jobject, jlong matrixPtr, jfloat x, jfloat y,
int color0, int color1) {
+ const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
SkColor colors[2];
colors[0] = color0;
colors[1] = color1;
- SkShader* s = SkGradientShader::MakeSweep(x, y, colors, NULL, 2).release();
+ SkShader* s = SkGradientShader::MakeSweep(x, y, colors, NULL, 2,
+ /* flags */ 0, matrix).release();
ThrowIAE_IfNull(env, s);
return reinterpret_cast<jlong>(s);
}
///////////////////////////////////////////////////////////////////////////////////////////////
-static jlong ComposeShader_create(JNIEnv* env, jobject o,
- jlong shaderAHandle, jlong shaderBHandle, jint xfermodeHandle)
-{
+static jlong ComposeShader_create(JNIEnv* env, jobject o, jlong matrixPtr,
+ jlong shaderAHandle, jlong shaderBHandle, jint xfermodeHandle) {
+ const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
SkShader* shaderA = reinterpret_cast<SkShader *>(shaderAHandle);
SkShader* shaderB = reinterpret_cast<SkShader *>(shaderBHandle);
SkBlendMode mode = static_cast<SkBlendMode>(xfermodeHandle);
- SkShader* shader = SkShader::MakeComposeShader(sk_ref_sp(shaderA),
- sk_ref_sp(shaderB),
- mode).release();
+ sk_sp<SkShader> baseShader(SkShader::MakeComposeShader(
+ sk_ref_sp(shaderA), sk_ref_sp(shaderB), mode));
+
+ SkShader* shader;
+
+ if (matrix) {
+ shader = baseShader->makeWithLocalMatrix(*matrix).release();
+ } else {
+ shader = baseShader.release();
+ }
return reinterpret_cast<jlong>(shader);
}
///////////////////////////////////////////////////////////////////////////////////////////////
static const JNINativeMethod gColorMethods[] = {
- { "nativeRGBToHSV", "(III[F)V", (void*)Color_RGBToHSV },
- { "nativeHSVToColor", "(I[F)I", (void*)Color_HSVToColor }
+ { "nativeRGBToHSV", "(III[F)V", (void*)Color_RGBToHSV },
+ { "nativeHSVToColor", "(I[F)I", (void*)Color_HSVToColor }
};
static const JNINativeMethod gShaderMethods[] = {
- { "nativeDestructor", "(J)V", (void*)Shader_destructor },
- { "nativeSetLocalMatrix", "(JJ)J", (void*)Shader_setLocalMatrix }
+ { "nativeSafeUnref", "(J)V", (void*)Shader_safeUnref },
};
static const JNINativeMethod gBitmapShaderMethods[] = {
- { "nativeCreate", "(Landroid/graphics/Bitmap;II)J", (void*)BitmapShader_constructor },
+ { "nativeCreate", "(JLandroid/graphics/Bitmap;II)J", (void*)BitmapShader_constructor },
};
static const JNINativeMethod gLinearGradientMethods[] = {
- { "nativeCreate1", "(FFFF[I[FI)J", (void*)LinearGradient_create1 },
- { "nativeCreate2", "(FFFFIII)J", (void*)LinearGradient_create2 },
+ { "nativeCreate1", "(JFFFF[I[FI)J", (void*)LinearGradient_create1 },
+ { "nativeCreate2", "(JFFFFIII)J", (void*)LinearGradient_create2 },
};
static const JNINativeMethod gRadialGradientMethods[] = {
- { "nativeCreate1", "(FFF[I[FI)J", (void*)RadialGradient_create1 },
- { "nativeCreate2", "(FFFIII)J", (void*)RadialGradient_create2 },
+ { "nativeCreate1", "(JFFF[I[FI)J", (void*)RadialGradient_create1 },
+ { "nativeCreate2", "(JFFFIII)J", (void*)RadialGradient_create2 },
};
static const JNINativeMethod gSweepGradientMethods[] = {
- { "nativeCreate1", "(FF[I[F)J", (void*)SweepGradient_create1 },
- { "nativeCreate2", "(FFII)J", (void*)SweepGradient_create2 },
+ { "nativeCreate1", "(JFF[I[F)J", (void*)SweepGradient_create1 },
+ { "nativeCreate2", "(JFFII)J", (void*)SweepGradient_create2 },
};
static const JNINativeMethod gComposeShaderMethods[] = {
- { "nativeCreate", "(JJI)J", (void*)ComposeShader_create },
+ { "nativeCreate", "(JJJI)J", (void*)ComposeShader_create },
};
int register_android_graphics_Shader(JNIEnv* env)
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index f221392..6e8c931 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -452,10 +452,6 @@
const RenderProperties& props = node.properties();
uirenderer::Rect bounds(props.getWidth(), props.getHeight());
transform.mapRect(bounds);
- bounds.left -= info.windowInsetLeft;
- bounds.right -= info.windowInsetLeft;
- bounds.top -= info.windowInsetTop;
- bounds.bottom -= info.windowInsetTop;
if (CC_LIKELY(transform.isPureTranslate())) {
// snap/round the computed bounds, so they match the rounding behavior
@@ -627,9 +623,9 @@
int register_android_view_RenderNode(JNIEnv* env) {
jclass clazz = FindClassOrDie(env, "android/view/SurfaceView");
gSurfaceViewPositionUpdateMethod = GetMethodIDOrDie(env, clazz,
- "updateWindowPosition_renderWorker", "(JIIII)V");
+ "updateSurfacePosition_renderWorker", "(JIIII)V");
gSurfaceViewPositionLostMethod = GetMethodIDOrDie(env, clazz,
- "windowPositionLost_uiRtSync", "(J)V");
+ "surfacePositionLost_uiRtSync", "(J)V");
return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
}
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 6192271..713287e 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -21,6 +21,7 @@
#include "jni.h"
#include "JNIHelp.h"
#include "android_os_Parcel.h"
+#include "android/graphics/GraphicBuffer.h"
#include "android/graphics/GraphicsJNI.h"
#include "core_jni_helpers.h"
@@ -496,6 +497,30 @@
return surface->disconnect(-1, IGraphicBufferProducer::DisconnectMode::AllLocal);
}
+static jint nativeAttachAndQueueBuffer(JNIEnv *env, jclass clazz, jlong nativeObject,
+ jobject graphicBuffer) {
+ Surface* surface = reinterpret_cast<Surface*>(nativeObject);
+ sp<GraphicBuffer> bp = graphicBufferForJavaObject(env, graphicBuffer);
+ if (bp == nullptr) {
+ return BAD_VALUE;
+ }
+ int err = ((ANativeWindow*)surface)->perform(surface, NATIVE_WINDOW_API_CONNECT,
+ NATIVE_WINDOW_API_CPU);
+ if (err != OK) {
+ return err;
+ }
+ err = surface->attachBuffer(bp->getNativeBuffer());
+ if (err != OK) {
+ return err;
+ }
+ err = ((ANativeWindow*)surface)->queueBuffer(surface, bp->getNativeBuffer(), -1);
+ if (err != OK) {
+ return err;
+ }
+ err = surface->disconnect(NATIVE_WINDOW_API_CPU);
+ return err;
+}
+
namespace uirenderer {
using namespace android::uirenderer::renderthread;
@@ -574,6 +599,7 @@
{"nativeGetNextFrameNumber", "(J)J", (void*)nativeGetNextFrameNumber },
{"nativeSetScalingMode", "(JI)I", (void*)nativeSetScalingMode },
{"nativeForceScopedDisconnect", "(J)I", (void*)nativeForceScopedDisconnect},
+ {"nativeAttachAndQueueBuffer", "(JLandroid/graphics/GraphicBuffer;)I", (void*)nativeAttachAndQueueBuffer},
// HWUI context
{"nHwuiCreate", "(JJ)J", (void*) hwui::create },
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index a81901d..6fbf49b 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -693,7 +693,6 @@
return JNI_TRUE;
}
-
static void nativeDeferTransactionUntil(JNIEnv* env, jclass clazz, jlong nativeObject,
jobject handleObject, jlong frameNumber) {
auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
@@ -702,6 +701,27 @@
ctrl->deferTransactionUntil(handle, frameNumber);
}
+static void nativeDeferTransactionUntilSurface(JNIEnv* env, jclass clazz, jlong nativeObject,
+ jlong surfaceObject, jlong frameNumber) {
+ auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ sp<Surface> barrier = reinterpret_cast<Surface *>(surfaceObject);
+
+ ctrl->deferTransactionUntil(barrier, frameNumber);
+}
+
+static void nativeReparentChildren(JNIEnv* env, jclass clazz, jlong nativeObject,
+ jobject newParentObject) {
+ auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ sp<IBinder> handle = ibinderForJavaObject(env, newParentObject);
+
+ ctrl->reparentChildren(handle);
+}
+
+static void nativeSeverChildren(JNIEnv* env, jclass clazz, jlong nativeObject) {
+ auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ ctrl->detachChildren();
+}
+
static void nativeSetOverrideScalingMode(JNIEnv* env, jclass clazz, jlong nativeObject,
jint scalingMode) {
auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
@@ -824,6 +844,12 @@
(void*)nativeSetDisplayPowerMode },
{"nativeDeferTransactionUntil", "(JLandroid/os/IBinder;J)V",
(void*)nativeDeferTransactionUntil },
+ {"nativeDeferTransactionUntilSurface", "(JJJ)V",
+ (void*)nativeDeferTransactionUntilSurface },
+ {"nativeReparentChildren", "(JLandroid/os/IBinder;)V",
+ (void*)nativeReparentChildren } ,
+ {"nativeSeverChildren", "(J)V",
+ (void*)nativeSeverChildren } ,
{"nativeSetOverrideScalingMode", "(JI)V",
(void*)nativeSetOverrideScalingMode },
{"nativeGetHandle", "(J)Landroid/os/IBinder;",
diff --git a/core/jni/android_view_SurfaceSession.cpp b/core/jni/android_view_SurfaceSession.cpp
index dad6958..508d897 100644
--- a/core/jni/android_view_SurfaceSession.cpp
+++ b/core/jni/android_view_SurfaceSession.cpp
@@ -24,6 +24,7 @@
#include <utils/RefBase.h>
#include <gui/SurfaceComposerClient.h>
+#include <gui/Surface.h>
namespace android {
@@ -45,6 +46,13 @@
return reinterpret_cast<jlong>(client);
}
+static jlong nativeCreateScoped(JNIEnv* env, jclass clazz, jlong surfaceObject) {
+ Surface *parent = reinterpret_cast<Surface*>(surfaceObject);
+ SurfaceComposerClient* client = new SurfaceComposerClient(parent->getIGraphicBufferProducer());
+ client->incStrong((void*)nativeCreate);
+ return reinterpret_cast<jlong>(client);
+}
+
static void nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) {
SurfaceComposerClient* client = reinterpret_cast<SurfaceComposerClient*>(ptr);
client->decStrong((void*)nativeCreate);
@@ -55,11 +63,12 @@
client->dispose();
}
-
static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "nativeCreate", "()J",
(void*)nativeCreate },
+ { "nativeCreateScoped", "(J)J",
+ (void*)nativeCreateScoped },
{ "nativeDestroy", "(J)V",
(void*)nativeDestroy },
{ "nativeKill", "(J)V",
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 37eae48a..e1c0a21 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -27,7 +27,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include <EGL/egl_cache.h>
+#include <private/EGL/cache.h>
#include <utils/Looper.h>
#include <utils/RefBase.h>
@@ -178,13 +178,9 @@
}
}
// TODO: This is hacky
- info.windowInsetLeft = -stagingProperties().getLeft();
- info.windowInsetTop = -stagingProperties().getTop();
info.updateWindowPositions = true;
RenderNode::prepareTree(info);
info.updateWindowPositions = false;
- info.windowInsetLeft = 0;
- info.windowInsetTop = 0;
info.errorHandler = nullptr;
}
@@ -891,7 +887,7 @@
static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
jstring diskCachePath) {
const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
- egl_cache_t::get()->setCacheFilename(cacheArray);
+ android::egl_set_cache_filename(cacheArray);
env->ReleaseStringUTFChars(diskCachePath, cacheArray);
}
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index 56bec18..1ac05f9 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -22,9 +22,9 @@
#include <utils/misc.h>
-#include <EGL/egl_display.h>
#include <EGL/egl.h>
#include <GLES/gl.h>
+#include <private/EGL/display.h>
#include <gui/Surface.h>
#include <gui/GLConsumer.h>
@@ -180,8 +180,7 @@
static jint jni_getInitCount(JNIEnv *_env, jobject _clazz, jobject display) {
EGLDisplay dpy = getDisplay(_env, display);
- egl_display_t* eglDisplay = get_display_nowake(dpy);
- return eglDisplay ? eglDisplay->getRefsCount() : 0;
+ return android::egl_get_init_count(dpy);
}
static jboolean jni_eglReleaseThread(JNIEnv *_env, jobject _this) {
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index ee50c29..7eb0582 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -341,7 +341,7 @@
SettingProto input_methods_subtype_history = 5;
SettingProto input_method_selector_visibility = 6;
SettingProto voice_interaction_service = 7;
- SettingProto auto_fill_service = 8;
+ SettingProto autofill_service = 8;
SettingProto bluetooth_hci_log = 9;
SettingProto user_setup_complete = 10;
SettingProto completed_category_prefix = 11;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c2a2e69..c991f22 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -216,6 +216,7 @@
<protected-broadcast android:name="android.btopp.intent.action.OPEN_INBOUND" />
<protected-broadcast android:name="android.btopp.intent.action.TRANSFER_COMPLETE" />
<protected-broadcast android:name="android.btopp.intent.action.ACCEPT" />
+ <protected-broadcast android:name="android.btopp.intent.action.DECLINE" />
<protected-broadcast android:name="com.android.bluetooth.gatt.REFRESH_BATCHED_SCAN" />
<protected-broadcast android:name="com.android.bluetooth.pbap.authchall" />
<protected-broadcast android:name="com.android.bluetooth.pbap.userconfirmtimeout" />
@@ -2305,6 +2306,10 @@
<permission android:name="android.permission.RETRIEVE_WINDOW_TOKEN"
android:protectionLevel="signature" />
+ <!-- @hide Allows an application to modify accessibility information from another app. -->
+ <permission android:name="android.permission.MODIFY_ACCESSIBILITY_DATA"
+ android:protectionLevel="signature" />
+
<!-- @hide Allows an application to collect frame statistics -->
<permission android:name="android.permission.FRAME_STATS"
android:protectionLevel="signature" />
@@ -2440,10 +2445,16 @@
<permission android:name="android.permission.BIND_VOICE_INTERACTION"
android:protectionLevel="signature" />
- <!-- Must be required by a {@link android.service.autofill.AutoFillService},
+ <!-- Must be required by a {@link android.service.autofill.AutofillService},
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
+ <permission android:name="android.permission.BIND_AUTOFILL"
+ android:protectionLevel="signature" />
+
+ <!-- TODO(b/35956626): temporary until clients change to BIND_AUTOFILL
+ <p>Protection level: signature
+ -->
<permission android:name="android.permission.BIND_AUTO_FILL"
android:protectionLevel="signature" />
@@ -3285,6 +3296,11 @@
<permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi Allows an application to show notifications before the device is provisioned.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.NOTIFICATION_DURING_SETUP"
+ android:protectionLevel="signature|privileged" />
+
<!-- @SystemApi Allows an application to manage auto-fill sessions.
@hide <p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.MANAGE_AUTO_FILL"
diff --git a/core/res/res/values-sw600dp/config.xml b/core/res/res/values-sw600dp/config.xml
index 7f57ded..6edb88e 100644
--- a/core/res/res/values-sw600dp/config.xml
+++ b/core/res/res/values-sw600dp/config.xml
@@ -28,7 +28,7 @@
<!-- see comment in values/config.xml -->
<dimen name="config_prefDialogWidth">580dp</dimen>
-
+
<!-- If true, the screen can be rotated via the accelerometer in all 4
rotations as the default behavior. -->
<bool name="config_allowAllRotations">true</bool>
@@ -41,5 +41,15 @@
<dimen name="config_minScalingSpan">32mm</dimen>
<integer name="config_dockedStackDividerSnapMode">1</integer>
+
+ <!-- The snap mode to use for picture-in-picture. These values correspond to constants defined
+ in PipSnapAlgorithm and should not be changed independently.
+ 0 - Snap to the four corners
+ 1 - Snap to the four corners and the mid-points on the long edge in each orientation
+ 2 - Snap anywhere along the edge of the screen
+ 3 - Snap anywhere along the edge of the screen and magnet to corners
+ 4 - Snap to the long edges in each orientation and magnet to corners
+ -->
+ <integer name="config_pictureInPictureSnapMode">3</integer>
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index b3cb2c7..21c8780 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2293,22 +2293,22 @@
<enum name="auto" value="0x00000010" />
</attr>
- <!-- Controls the auto-fill behavior for this view. -->
- <attr name="autoFillMode">
+ <!-- Controls the autofill behavior for this view. -->
+ <attr name="autofillMode">
<!-- Inherit the behavior from the parent. If there is no parent it is auto. This is the
default value for this attribute.-->
<enum name="inherit" value="0" />
- <!-- Allows this view to automatically trigger an auto-fill request when it get focus.
+ <!-- Allows this view to automatically trigger an autofill request when it get focus.
-->
<enum name="auto" value="1" />
- <!-- Do not trigger an auto-fill request when this view is focused. The user can still
- manually force an auto-fill request for this view. -->
+ <!-- Do not trigger an autofill request when this view is focused. The user can still
+ manually force an autofill request for this view. -->
<enum name="manual" value="2" />
</attr>
- <!-- Describes the content of a view so that a auto-fill service can fill in the appropriate
+ <!-- Describes the content of a view so that a autofill service can fill in the appropriate
data. Multiple flags can be combined to mean e.g. emailAddress or postalAddress. -->
- <attr name="autoFillHint">
+ <attr name="autofillHint">
<!-- No hint. -->
<flag name="none" value="0" />
<!-- The view contains an email address. -->
@@ -7717,14 +7717,21 @@
</declare-styleable>
<!-- =============================== -->
- <!-- AutoFill attributes -->
+ <!-- Autofill attributes -->
<!-- =============================== -->
<eat-comment />
<!-- Use <code>autofill-service</code> as the root tag of the XML resource that describes a
- {@link android.service.autofill.AutoFillService}, which is referenced from its
+ {@link android.service.autofill.AutofillService}, which is referenced from its
{@link android.service.autofill#SERVICE_META_DATA} meta-data entry.
-->
+ <declare-styleable name="AutofillService">
+ <!-- Fully qualified class name of an activity that allows the user to modify
+ the settings for this service. -->
+ <attr name="settingsActivity" />
+ </declare-styleable>
+
+ <!-- TODO(b/35956626): temporary until clients change to AutofillService -->
<declare-styleable name="AutoFillService">
<!-- Fully qualified class name of an activity that allows the user to modify
the settings for this service. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a3a0c83..6e0d9dc 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -470,6 +470,8 @@
<integer translatable="false" name="config_wifi_framework_LAST_SELECTION_AWARD">480</integer>
<integer translatable="false" name="config_wifi_framework_PASSPOINT_SECURITY_AWARD">40</integer>
<integer translatable="false" name="config_wifi_framework_SECURITY_AWARD">80</integer>
+ <!-- Integer specifying the base interval in seconds for the exponential backoff scan for autojoin -->
+ <integer translatable="false" name="config_wifi_framework_exponential_backoff_scan_base_interval">20</integer>
<!-- Integer parameters of the wifi to cellular handover feature
wifi should not stick to bad networks -->
<integer translatable="false" name="config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz">-82</integer>
@@ -2569,6 +2571,16 @@
ratio larger than this is considered to wide and short to be usable. -->
<item name="config_pictureInPictureMaxAspectRatio" format="float" type="dimen">2.35</item>
+ <!-- The snap mode to use for picture-in-picture. These values correspond to constants defined
+ in PipSnapAlgorithm and should not be changed independently.
+ 0 - Snap to the four corners
+ 1 - Snap to the four corners and the mid-points on the long edge in each orientation
+ 2 - Snap anywhere along the edge of the screen
+ 3 - Snap anywhere along the edge of the screen and magnet to corners
+ 4 - Snap to the long edges in each orientation and magnet to corners
+ -->
+ <integer name="config_pictureInPictureSnapMode">4</integer>
+
<!-- Controls the snap mode for the docked stack divider
0 - 3 snap targets: left/top has 16:9 ratio, 1:1, and right/bottom has 16:9 ratio
1 - 3 snap targets: fixed ratio, 1:1, (1 - fixed ratio)
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 613616f..f8a071d 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -135,4 +135,7 @@
<!-- ItemTouchHelper uses this id to save a View's original elevation. -->
<item type="id" name="item_touch_helper_previous_elevation"/>
+
+ <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_MOVE_WINDOW}. -->
+ <item type="id" name="accessibilityActionMoveWindow" />
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index b664448..359fbcb 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2797,12 +2797,12 @@
<public name="numericModifiers" />
<public name="fontProviderAuthority" />
<public name="fontProviderQuery" />
- <public name="autoFillMode" />
+ <public name="autofillMode" />
<public name="primaryContentAlpha" />
<public name="secondaryContentAlpha" />
<public name="requiredFeature" />
<public name="requiredNotFeature" />
- <public name="autoFillHint" />
+ <public name="autofillHint" />
<public name="fontProviderPackage" />
<public name="importantForAutofill" />
</public-group>
@@ -2812,6 +2812,7 @@
<public-group type="id" first-id="0x01020041">
<public name="textAssist" />
+ <public name="accessibilityActionMoveWindow" />
</public-group>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index bd8d572..d1d406d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3167,13 +3167,13 @@
<skip />
<!-- Name of notification channel the system post notification to inform the use about apps
that are drawing ui on-top of other apps (alert-windows) [CHAR LIMIT=NONE] -->
- <string name="alert_windows_notification_channel_name"><xliff:g id="name" example="Google Maps">%s</xliff:g> draw over other apps</string>
+ <string name="alert_windows_notification_channel_name"><xliff:g id="name" example="Google Maps">%s</xliff:g> displaying over other apps</string>
<!-- Notification title when an application is displaying ui on-top of other apps
[CHAR LIMIT=30] -->
- <string name="alert_windows_notification_title"><xliff:g id="name" example="Google Maps">%s</xliff:g> app displaying on top.</string>
+ <string name="alert_windows_notification_title"><xliff:g id="name" example="Google Maps">%s</xliff:g> is displaying over other apps.</string>
<!-- Notification body when an application is displaying ui on-top of other apps
[CHAR LIMIT=NONE] -->
- <string name="alert_windows_notification_message">Parts of this app may remain visible at all times. If this feature isn\'t working correctly, turn it off.</string>
+ <string name="alert_windows_notification_message">If you don’t want <xliff:g id="name" example="Google Maps">%s</xliff:g> to use this feature, tap to open settings and turn it off.</string>
<!-- Notification action to turn-off app displaying on-top of other apps. [CHAR LIMIT=20] -->
<string name="alert_windows_notification_turn_off_action">TURN OFF</string>
@@ -3195,11 +3195,15 @@
<string name="ext_media_unmountable_notification_title">Corrupted <xliff:g id="name" example="SD card">%s</xliff:g></string>
<!-- Notification body when external media is unmountable (corrupt) [CHAR LIMIT=NONE] -->
<string name="ext_media_unmountable_notification_message"><xliff:g id="name" example="SD card">%s</xliff:g> is corrupt. Tap to fix.</string>
+ <!-- TV-specifiv notification body when external media is unmountable (corrupt) [CHAR LIMIT=NONE] -->
+ <string name="ext_media_unmountable_notification_message" product="tv"><xliff:g id="name" example="SD card">%s</xliff:g> is corrupt. Select to fix.</string>
<!-- Notification title when external media is unsupported [CHAR LIMIT=30] -->
<string name="ext_media_unsupported_notification_title">Unsupported <xliff:g id="name" example="SD card">%s</xliff:g></string>
<!-- Notification body when external media is unsupported [CHAR LIMIT=NONE] -->
<string name="ext_media_unsupported_notification_message">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>. Tap to set up in a supported format.</string>
+ <!-- TV-specific notification body when external media is unsupported [CHAR LIMIT=NONE] -->
+ <string name="ext_media_unsupported_notification_message" product="tv">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>. Select to set up in a supported format.</string>
<!-- Notification title when external media is unsafely removed [CHAR LIMIT=30] -->
<string name="ext_media_badremoval_notification_title"><xliff:g id="name" example="SD card">%s</xliff:g> unexpectedly removed</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 32babab..0c318cf 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1556,6 +1556,7 @@
<java-symbol type="dimen" name="docked_stack_minimize_thickness" />
<java-symbol type="dimen" name="pip_minimized_visible_size" />
<java-symbol type="integer" name="config_dockedStackDividerSnapMode" />
+ <java-symbol type="integer" name="config_pictureInPictureSnapMode" />
<java-symbol type="fraction" name="docked_stack_divider_fixed_ratio" />
<java-symbol type="fraction" name="thumbnail_fullscreen_scale" />
<java-symbol type="integer" name="thumbnail_width_tv" />
diff --git a/core/tests/coretests/src/android/metrics/LogMakerTest.java b/core/tests/coretests/src/android/metrics/LogMakerTest.java
index ece44be..bab9f63 100644
--- a/core/tests/coretests/src/android/metrics/LogMakerTest.java
+++ b/core/tests/coretests/src/android/metrics/LogMakerTest.java
@@ -171,6 +171,14 @@
assertEquals(null, builder.getPackageName());
}
+ public void testSetAndClearPid() {
+ LogMaker builder = new LogMaker(0);
+ builder.setProcessId(1);
+ assertEquals(1, builder.getProcessId());
+ builder.clearProcessId();
+ assertEquals(-1, builder.getProcessId());
+ }
+
public void testGiantLogOmitted() {
LogMaker badBuilder = new LogMaker(0);
StringBuilder b = new StringBuilder();
diff --git a/core/tests/coretests/src/android/provider/DocumentsProviderTest.java b/core/tests/coretests/src/android/provider/DocumentsProviderTest.java
index d1c68a9..09cbbff 100644
--- a/core/tests/coretests/src/android/provider/DocumentsProviderTest.java
+++ b/core/tests/coretests/src/android/provider/DocumentsProviderTest.java
@@ -52,7 +52,7 @@
mResolver = getMockContentResolver();
}
- public void testFindPath_docUri() throws Exception {
+ public void testFindDocumentPath_docUri() throws Exception {
final Path expected = new Path(ROOT_ID, Arrays.asList(PARENT_DOCUMENT_ID, DOCUMENT_ID));
mProvider.nextPath = expected;
@@ -65,7 +65,7 @@
}
}
- public void testFindPath_treeUri() throws Exception {
+ public void testFindDocumentPath_treeUri() throws Exception {
mProvider.nextIsChildDocument = true;
final Path expected = new Path(null, Arrays.asList(PARENT_DOCUMENT_ID, DOCUMENT_ID));
@@ -73,12 +73,13 @@
final Uri docUri = buildTreeDocumentUri(
TestDocumentsProvider.AUTHORITY, PARENT_DOCUMENT_ID, DOCUMENT_ID);
- final List<String> actual = DocumentsContract.findDocumentPath(mResolver, docUri);
+ final Path actual = DocumentsContract.findDocumentPath(mResolver, docUri);
- assertEquals(expected.getPath(), actual);
+ assertNull(actual.getRootId());
+ assertEquals(expected.getPath(), actual.getPath());
}
- public void testFindPath_treeUri_throwsOnNonChildDocument() throws Exception {
+ public void testFindDocumentPath_treeUri_throwsOnNonChildDocument() throws Exception {
mProvider.nextPath = new Path(null, Arrays.asList(PARENT_DOCUMENT_ID, DOCUMENT_ID));
final Uri docUri = buildTreeDocumentUri(
@@ -86,18 +87,28 @@
assertNull(DocumentsContract.findDocumentPath(mResolver, docUri));
}
- public void testFindPath_treeUri_erasesNonNullRootId() throws Exception {
+ public void testFindDocumentPath_treeUri_erasesNonNullRootId() throws Exception {
mProvider.nextIsChildDocument = true;
mProvider.nextPath = new Path(ROOT_ID, Arrays.asList(PARENT_DOCUMENT_ID, DOCUMENT_ID));
final Uri docUri = buildTreeDocumentUri(
TestDocumentsProvider.AUTHORITY, PARENT_DOCUMENT_ID, DOCUMENT_ID);
- try (ContentProviderClient client =
- mResolver.acquireUnstableContentProviderClient(docUri)) {
- Path path = DocumentsContract.findDocumentPath(client, docUri);
- assertNull(path.getRootId());
- }
+ Path path = DocumentsContract.findDocumentPath(mResolver, docUri);
+ assertNull(path.getRootId());
+ assertEquals(Arrays.asList(PARENT_DOCUMENT_ID, DOCUMENT_ID), path.getPath());
+ }
+
+ public void testFindDocumentPath_treeUri_erasesDocsOutsideTree() throws Exception {
+ mProvider.nextIsChildDocument = true;
+
+ mProvider.nextPath = new Path(
+ null, Arrays.asList(ANCESTOR_DOCUMENT_ID, PARENT_DOCUMENT_ID, DOCUMENT_ID));
+
+ final Uri docUri = buildTreeDocumentUri(
+ TestDocumentsProvider.AUTHORITY, PARENT_DOCUMENT_ID, DOCUMENT_ID);
+ Path path = DocumentsContract.findDocumentPath(mResolver, docUri);
+ assertEquals(Arrays.asList(PARENT_DOCUMENT_ID, DOCUMENT_ID), path.getPath());
}
private static Uri buildTreeDocumentUri(String authority, String parentDocId, String docId) {
diff --git a/core/tests/coretests/src/android/provider/FontsContractTest.java b/core/tests/coretests/src/android/provider/FontsContractTest.java
index db623a4..d90fc2b 100644
--- a/core/tests/coretests/src/android/provider/FontsContractTest.java
+++ b/core/tests/coretests/src/android/provider/FontsContractTest.java
@@ -15,12 +15,12 @@
*/
package android.provider;
-import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.content.pm.ApplicationInfo;
@@ -28,6 +28,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.Signature;
+import android.database.MatrixCursor;
import android.graphics.Typeface;
import android.graphics.fonts.FontRequest;
import android.graphics.fonts.FontResult;
@@ -72,11 +73,12 @@
mResultReceiver = mock(ResultReceiver.class);
}
- public void testGetFontFromProvider() {
+ public void testGetFontFromProvider_resultOK() {
mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
- verify(mResultReceiver).send(eq(FontsContract.RESULT_CODE_OK), bundleCaptor.capture());
+ verify(mResultReceiver).send(
+ eq(FontsContract.Columns.RESULT_CODE_OK), bundleCaptor.capture());
Bundle bundle = bundleCaptor.getValue();
assertNotNull(bundle);
@@ -96,7 +98,8 @@
final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
- verify(mResultReceiver).send(eq(FontsContract.RESULT_CODE_OK), bundleCaptor.capture());
+ verify(mResultReceiver).send(
+ eq(FontsContract.Columns.RESULT_CODE_OK), bundleCaptor.capture());
Bundle bundle = bundleCaptor.getValue();
assertNotNull(bundle);
@@ -111,11 +114,79 @@
assertNotNull(fontResult.getFileDescriptor());
}
+ public void testGetFontFromProvider_resultFontNotFound() {
+ // Make the provider return unknown
+ mProvider.setResultCode(FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND);
+ mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
+
+ verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND,null);
+ }
+
+ public void testGetFontFromProvider_resultFontUnavailable() {
+ // Make the provider return font unavailable
+ mProvider.setResultCode(FontsContract.Columns.RESULT_CODE_FONT_UNAVAILABLE);
+ mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
+
+ verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_FONT_UNAVAILABLE,null);
+ }
+
+ public void testGetFontFromProvider_resultMalformedQuery() {
+ // Make the provider return font unavailable
+ mProvider.setResultCode(FontsContract.Columns.RESULT_CODE_MALFORMED_QUERY);
+ mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
+
+ verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_MALFORMED_QUERY,null);
+ }
+
+ public void testGetFontFromProvider_resultFontNotFoundSecondRow() {
+ MatrixCursor cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
+ FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
+ FontsContract.Columns.STYLE, FontsContract.Columns.RESULT_CODE });
+ cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
+ FontsContract.Columns.RESULT_CODE_OK});
+ cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
+ FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND});
+ mProvider.setCustomCursor(cursor);
+ mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
+
+ verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND, null);
+ }
+
+ public void testGetFontFromProvider_resultFontNotFoundOtherRow() {
+ MatrixCursor cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
+ FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
+ FontsContract.Columns.STYLE, FontsContract.Columns.RESULT_CODE });
+ cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
+ FontsContract.Columns.RESULT_CODE_OK});
+ cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
+ FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND});
+ cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
+ FontsContract.Columns.RESULT_CODE_OK});
+ mProvider.setCustomCursor(cursor);
+ mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
+
+ verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND, null);
+ }
+
+ public void testGetFontFromProvider_resultCodeIsNegativeNumber() {
+ MatrixCursor cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
+ FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
+ FontsContract.Columns.STYLE, FontsContract.Columns.RESULT_CODE });
+ cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
+ FontsContract.Columns.RESULT_CODE_OK});
+ cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL, -5});
+ mProvider.setCustomCursor(cursor);
+ mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
+
+ verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND, null);
+ }
+
public void testGetProvider_providerNotFound() {
when(mPackageManager.resolveContentProvider(anyString(), anyInt())).thenReturn(null);
- ProviderInfo result = mContract.getProvider(request);
+ ProviderInfo result = mContract.getProvider(request, mResultReceiver);
+ verify(mResultReceiver).send(FontsContract.RESULT_CODE_PROVIDER_NOT_FOUND, null);
assertNull(result);
}
@@ -124,8 +195,9 @@
info.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
when(mPackageManager.resolveContentProvider(anyString(), anyInt())).thenReturn(info);
- ProviderInfo result = mContract.getProvider(request);
+ ProviderInfo result = mContract.getProvider(request, mResultReceiver);
+ verifyZeroInteractions(mResultReceiver);
assertEquals(info, result);
}
@@ -136,8 +208,10 @@
when(mPackageManager.resolveContentProvider(anyString(), anyInt())).thenReturn(info);
ProviderInfo result = mContract.getProvider(
- new FontRequest(TestFontsProvider.AUTHORITY, "com.wrong.package", "query"));
+ new FontRequest(TestFontsProvider.AUTHORITY, "com.wrong.package", "query"),
+ mResultReceiver);
+ verify(mResultReceiver).send(FontsContract.RESULT_CODE_PROVIDER_NOT_FOUND, null);
assertNull(result);
}
@@ -146,8 +220,9 @@
setupPackageManager();
// The default request is missing the certificates info.
- ProviderInfo result = mContract.getProvider(request);
+ ProviderInfo result = mContract.getProvider(request, mResultReceiver);
+ verify(mResultReceiver).send(FontsContract.RESULT_CODE_WRONG_CERTIFICATES, null);
assertNull(result);
}
@@ -159,8 +234,9 @@
List<byte[]> certList = Arrays.asList(wrongCert);
FontRequest requestWrongCerts = new FontRequest(
TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", Arrays.asList(certList));
- ProviderInfo result = mContract.getProvider(requestWrongCerts);
+ ProviderInfo result = mContract.getProvider(requestWrongCerts, mResultReceiver);
+ verify(mResultReceiver).send(FontsContract.RESULT_CODE_WRONG_CERTIFICATES, null);
assertNull(result);
}
@@ -171,8 +247,9 @@
List<byte[]> certList = Arrays.asList(BYTE_ARRAY);
FontRequest requestRightCerts = new FontRequest(
TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", Arrays.asList(certList));
- ProviderInfo result = mContract.getProvider(requestRightCerts);
+ ProviderInfo result = mContract.getProvider(requestRightCerts, mResultReceiver);
+ verifyZeroInteractions(mResultReceiver);
assertEquals(info, result);
}
@@ -184,9 +261,10 @@
List<byte[]> certList = Arrays.asList(wrongCert, BYTE_ARRAY);
FontRequest requestRightCerts = new FontRequest(
TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", Arrays.asList(certList));
- ProviderInfo result = mContract.getProvider(requestRightCerts);
+ ProviderInfo result = mContract.getProvider(requestRightCerts, mResultReceiver);
// There is one too many certs, should fail as the set doesn't match.
+ verify(mResultReceiver).send(FontsContract.RESULT_CODE_WRONG_CERTIFICATES, null);
assertNull(result);
}
@@ -200,8 +278,9 @@
certList.add(Arrays.asList(BYTE_ARRAY));
FontRequest requestRightCerts = new FontRequest(
TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", certList);
- ProviderInfo result = mContract.getProvider(requestRightCerts);
+ ProviderInfo result = mContract.getProvider(requestRightCerts, mResultReceiver);
+ verifyZeroInteractions(mResultReceiver);
assertEquals(info, result);
}
@@ -213,8 +292,9 @@
certList.add(Arrays.asList(BYTE_ARRAY));
FontRequest requestRightCerts = new FontRequest(
TestFontsProvider.AUTHORITY, "com.wrong.package.name", "query", certList);
- ProviderInfo result = mContract.getProvider(requestRightCerts);
+ ProviderInfo result = mContract.getProvider(requestRightCerts, mResultReceiver);
+ verify(mResultReceiver).send(FontsContract.RESULT_CODE_PROVIDER_NOT_FOUND, null);
assertNull(result);
}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 696d498..903ef84 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -385,7 +385,7 @@
Settings.Secure.ASSIST_DISCLOSURE_ENABLED,
Settings.Secure.ASSIST_SCREENSHOT_ENABLED,
Settings.Secure.ASSIST_STRUCTURE_ENABLED,
- Settings.Secure.AUTO_FILL_SERVICE,
+ Settings.Secure.AUTOFILL_SERVICE,
Settings.Secure.AUTOMATIC_STORAGE_MANAGER_BYTES_CLEARED,
Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED,
Settings.Secure.AUTOMATIC_STORAGE_MANAGER_LAST_RUN,
diff --git a/core/tests/coretests/src/android/provider/TestDocumentsProvider.java b/core/tests/coretests/src/android/provider/TestDocumentsProvider.java
index d61049d..1bd8ff6 100644
--- a/core/tests/coretests/src/android/provider/TestDocumentsProvider.java
+++ b/core/tests/coretests/src/android/provider/TestDocumentsProvider.java
@@ -85,7 +85,7 @@
}
@Override
- public Path findDocumentPath(String documentId, @Nullable String parentDocumentId) {
+ public Path findDocumentPath(@Nullable String parentDocumentId, String documentId) {
lastDocumentId = documentId;
lastParentDocumentId = parentDocumentId;
diff --git a/core/tests/coretests/src/android/provider/TestFontsProvider.java b/core/tests/coretests/src/android/provider/TestFontsProvider.java
index 6d40f37..13f5318 100644
--- a/core/tests/coretests/src/android/provider/TestFontsProvider.java
+++ b/core/tests/coretests/src/android/provider/TestFontsProvider.java
@@ -41,6 +41,15 @@
private ParcelFileDescriptor mPfd;
private boolean mReturnAllFields = true;
+ private int mResultCode = FontsContract.Columns.RESULT_CODE_OK;
+ private MatrixCursor mCustomCursor = null;
+
+ /**
+ * Used by tests to modify the result code that should be returned.
+ */
+ void setResultCode(int resultCode) {
+ mResultCode = resultCode;
+ }
/**
* Used by tests to switch whether all fields should be returned or not.
@@ -49,6 +58,13 @@
mReturnAllFields = returnAllFields;
}
+ /**
+ * Used by tests to control what values are returned.
+ */
+ void setCustomCursor(MatrixCursor cursor) {
+ mCustomCursor = cursor;
+ }
+
@Override
public boolean onCreate() {
mPfd = createFontFile();
@@ -58,12 +74,15 @@
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
@Nullable String[] selectionArgs, @Nullable String sortOrder) {
+ if (mCustomCursor != null) {
+ return mCustomCursor;
+ }
MatrixCursor cursor;
if (mReturnAllFields) {
cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
- FontsContract.Columns.STYLE });
- cursor.addRow(new Object[] { 1, TTC_INDEX, VARIATION_SETTINGS, STYLE });
+ FontsContract.Columns.STYLE, FontsContract.Columns.RESULT_CODE });
+ cursor.addRow(new Object[] { 1, TTC_INDEX, VARIATION_SETTINGS, STYLE, mResultCode });
} else {
cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID });
cursor.addRow(new Object[] { 1 });
diff --git a/data/sounds/AudioTv.mk b/data/sounds/AudioTv.mk
new file mode 100644
index 0000000..ee37cb9
--- /dev/null
+++ b/data/sounds/AudioTv.mk
@@ -0,0 +1,125 @@
+# Copyright 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := frameworks/base/data/sounds
+
+PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/Alarm_Beep_01.ogg:system/media/audio/alarms/Alarm_Beep_01.ogg \
+ $(LOCAL_PATH)/Alarm_Beep_02.ogg:system/media/audio/alarms/Alarm_Beep_02.ogg \
+ $(LOCAL_PATH)/Alarm_Beep_03.ogg:system/media/audio/alarms/Alarm_Beep_03.ogg \
+ $(LOCAL_PATH)/Alarm_Buzzer.ogg:system/media/audio/alarms/Alarm_Buzzer.ogg \
+ $(LOCAL_PATH)/Alarm_Classic.ogg:system/media/audio/alarms/Alarm_Classic.ogg \
+ $(LOCAL_PATH)/Alarm_Rooster_02.ogg:system/media/audio/alarms/Alarm_Rooster_02.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Argon.ogg:system/media/audio/alarms/Argon.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Barium.ogg:system/media/audio/alarms/Barium.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Carbon.ogg:system/media/audio/alarms/Carbon.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Cesium.ogg:system/media/audio/alarms/Cesium.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Fermium.ogg:system/media/audio/alarms/Fermium.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Hassium.ogg:system/media/audio/alarms/Hassium.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Helium.ogg:system/media/audio/alarms/Helium.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Krypton.ogg:system/media/audio/alarms/Krypton.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Neon.ogg:system/media/audio/alarms/Neon.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Neptunium.ogg:system/media/audio/alarms/Neptunium.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Nobelium.ogg:system/media/audio/alarms/Nobelium.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Osmium.ogg:system/media/audio/alarms/Osmium.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Oxygen.ogg:system/media/audio/alarms/Oxygen.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Platinum.ogg:system/media/audio/alarms/Platinum.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Plutonium.ogg:system/media/audio/alarms/Plutonium.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Promethium.ogg:system/media/audio/alarms/Promethium.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Scandium.ogg:system/media/audio/alarms/Scandium.ogg \
+ $(LOCAL_PATH)/effects/ogg/camera_click_48k.ogg:system/media/audio/ui/camera_click.ogg \
+ $(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
+ $(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
+ $(LOCAL_PATH)/effects/ogg/Effect_Tick_48k.ogg:system/media/audio/ui/Effect_Tick.ogg \
+ $(LOCAL_PATH)/effects/ogg/KeypressDelete_120_48k.ogg:system/media/audio/ui/KeypressDelete.ogg \
+ $(LOCAL_PATH)/effects/ogg/KeypressInvalid_120_48k.ogg:system/media/audio/ui/KeypressInvalid.ogg \
+ $(LOCAL_PATH)/effects/ogg/KeypressReturn_120_48k.ogg:system/media/audio/ui/KeypressReturn.ogg \
+ $(LOCAL_PATH)/effects/ogg/KeypressSpacebar_120_48k.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
+ $(LOCAL_PATH)/effects/ogg/KeypressStandard_120_48k.ogg:system/media/audio/ui/KeypressStandard.ogg \
+ $(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
+ $(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+ $(LOCAL_PATH)/effects/ogg/Trusted_48k.ogg:system/media/audio/ui/Trusted.ogg \
+ $(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
+ $(LOCAL_PATH)/effects/ogg/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
+ $(LOCAL_PATH)/effects/ogg/VideoRecord_48k.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/ogg/VideoStop_48k.ogg:system/media/audio/ui/VideoStop.ogg \
+ $(LOCAL_PATH)/effects/ogg/WirelessChargingStarted.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \
+ $(LOCAL_PATH)/F1_MissedCall.ogg:system/media/audio/notifications/F1_MissedCall.ogg \
+ $(LOCAL_PATH)/F1_New_MMS.ogg:system/media/audio/notifications/F1_New_MMS.ogg \
+ $(LOCAL_PATH)/F1_New_SMS.ogg:system/media/audio/notifications/F1_New_SMS.ogg \
+ $(LOCAL_PATH)/notifications/Aldebaran.ogg:system/media/audio/notifications/Aldebaran.ogg \
+ $(LOCAL_PATH)/notifications/Altair.ogg:system/media/audio/notifications/Altair.ogg \
+ $(LOCAL_PATH)/notifications/Antares.ogg:system/media/audio/notifications/Antares.ogg \
+ $(LOCAL_PATH)/notifications/arcturus.ogg:system/media/audio/notifications/arcturus.ogg \
+ $(LOCAL_PATH)/notifications/Beat_Box_Android.ogg:system/media/audio/notifications/Beat_Box_Android.ogg \
+ $(LOCAL_PATH)/notifications/Betelgeuse.ogg:system/media/audio/notifications/Betelgeuse.ogg \
+ $(LOCAL_PATH)/notifications/Canopus.ogg:system/media/audio/notifications/Canopus.ogg \
+ $(LOCAL_PATH)/notifications/Castor.ogg:system/media/audio/notifications/Castor.ogg \
+ $(LOCAL_PATH)/notifications/Cricket.ogg:system/media/audio/notifications/Cricket.ogg \
+ $(LOCAL_PATH)/notifications/Deneb.ogg:system/media/audio/notifications/Deneb.ogg \
+ $(LOCAL_PATH)/notifications/Doink.ogg:system/media/audio/notifications/Doink.ogg \
+ $(LOCAL_PATH)/notifications/Drip.ogg:system/media/audio/notifications/Drip.ogg \
+ $(LOCAL_PATH)/notifications/Electra.ogg:system/media/audio/notifications/Electra.ogg \
+ $(LOCAL_PATH)/notifications/Fomalhaut.ogg:system/media/audio/notifications/Fomalhaut.ogg \
+ $(LOCAL_PATH)/notifications/Heaven.ogg:system/media/audio/notifications/Heaven.ogg \
+ $(LOCAL_PATH)/notifications/Merope.ogg:system/media/audio/notifications/Merope.ogg \
+ $(LOCAL_PATH)/notifications/moonbeam.ogg:system/media/audio/notifications/moonbeam.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Adara.ogg:system/media/audio/notifications/Adara.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Alya.ogg:system/media/audio/notifications/Alya.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Antimony.ogg:system/media/audio/notifications/Antimony.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Arcturus.ogg:system/media/audio/notifications/Arcturus.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Argon.ogg:system/media/audio/notifications/Argon.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Bellatrix.ogg:system/media/audio/notifications/Bellatrix.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Beryllium.ogg:system/media/audio/notifications/Beryllium.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Capella.ogg:system/media/audio/notifications/Capella.ogg \
+ $(LOCAL_PATH)/notifications/ogg/CetiAlpha.ogg:system/media/audio/notifications/CetiAlpha.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Cobalt.ogg:system/media/audio/notifications/Cobalt.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Fluorine.ogg:system/media/audio/notifications/Fluorine.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Gallium.ogg:system/media/audio/notifications/Gallium.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Helium.ogg:system/media/audio/notifications/Helium.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Hojus.ogg:system/media/audio/notifications/Hojus.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Iridium.ogg:system/media/audio/notifications/Iridium.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Krypton.ogg:system/media/audio/notifications/Krypton.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Lalande.ogg:system/media/audio/notifications/Lalande.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Mira.ogg:system/media/audio/notifications/Mira.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Palladium.ogg:system/media/audio/notifications/Palladium.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Polaris.ogg:system/media/audio/notifications/Polaris.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Pollux.ogg:system/media/audio/notifications/Pollux.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Procyon.ogg:system/media/audio/notifications/Procyon.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Proxima.ogg:system/media/audio/notifications/Proxima.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Radon.ogg:system/media/audio/notifications/Radon.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Rubidium.ogg:system/media/audio/notifications/Rubidium.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Selenium.ogg:system/media/audio/notifications/Selenium.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Shaula.ogg:system/media/audio/notifications/Shaula.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Spica.ogg:system/media/audio/notifications/Spica.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Strontium.ogg:system/media/audio/notifications/Strontium.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Syrma.ogg:system/media/audio/notifications/Syrma.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Talitha.ogg:system/media/audio/notifications/Talitha.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Tejat.ogg:system/media/audio/notifications/Tejat.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Thallium.ogg:system/media/audio/notifications/Thallium.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Upsilon.ogg:system/media/audio/notifications/Upsilon.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Vega.ogg:system/media/audio/notifications/Vega.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Xenon.ogg:system/media/audio/notifications/Xenon.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Zirconium.ogg:system/media/audio/notifications/Zirconium.ogg \
+ $(LOCAL_PATH)/notifications/pixiedust.ogg:system/media/audio/notifications/pixiedust.ogg \
+ $(LOCAL_PATH)/notifications/pizzicato.ogg:system/media/audio/notifications/pizzicato.ogg \
+ $(LOCAL_PATH)/notifications/Plastic_Pipe.ogg:system/media/audio/notifications/Plastic_Pipe.ogg \
+ $(LOCAL_PATH)/notifications/regulus.ogg:system/media/audio/notifications/regulus.ogg \
+ $(LOCAL_PATH)/notifications/sirius.ogg:system/media/audio/notifications/sirius.ogg \
+ $(LOCAL_PATH)/notifications/Sirrah.ogg:system/media/audio/notifications/Sirrah.ogg \
+ $(LOCAL_PATH)/notifications/SpaceSeed.ogg:system/media/audio/notifications/SpaceSeed.ogg \
+ $(LOCAL_PATH)/notifications/TaDa.ogg:system/media/audio/notifications/TaDa.ogg \
+ $(LOCAL_PATH)/notifications/Tinkerbell.ogg:system/media/audio/notifications/Tinkerbell.ogg \
+ $(LOCAL_PATH)/notifications/tweeters.ogg:system/media/audio/notifications/tweeters.ogg \
+ $(LOCAL_PATH)/notifications/vega.ogg:system/media/audio/notifications/vega.ogg
diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java
index 9211225..7e6756e 100644
--- a/graphics/java/android/graphics/BitmapShader.java
+++ b/graphics/java/android/graphics/BitmapShader.java
@@ -28,23 +28,56 @@
* @hide
*/
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
- public final Bitmap mBitmap;
+ public Bitmap mBitmap;
- private TileMode mTileX;
- private TileMode mTileY;
+ private int mTileX;
+ private int mTileY;
/**
* Call this to create a new shader that will draw with a bitmap.
*
- * @param bitmap The bitmap to use inside the shader
- * @param tileX The tiling mode for x to draw the bitmap in.
- * @param tileY The tiling mode for y to draw the bitmap in.
+ * @param bitmap The bitmap to use inside the shader
+ * @param tileX The tiling mode for x to draw the bitmap in.
+ * @param tileY The tiling mode for y to draw the bitmap in.
*/
- public BitmapShader(@NonNull Bitmap bitmap, TileMode tileX, TileMode tileY) {
+ public BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY) {
+ set(bitmap, tileX, tileY);
+ }
+
+ private BitmapShader(Bitmap bitmap, int tileX, int tileY) {
+ setInternal(bitmap, tileX, tileY);
+ }
+
+ /**
+ * Reinitialize the BitmapShader's Bitmap and tile modes.
+ *
+ * @param bitmap The bitmap to use inside the shader
+ * @param tileX The tiling mode for x to draw the bitmap in.
+ * @param tileY The tiling mode for y to draw the bitmap in.
+ */
+ public void set(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY) {
+ if (tileX == null || tileY == null) {
+ throw new IllegalArgumentException();
+ }
+ setInternal(bitmap, tileX.nativeInt, tileY.nativeInt);
+ }
+
+ private void setInternal(Bitmap bitmap, int tileX, int tileY) {
+ if (bitmap == null) {
+ throw new IllegalArgumentException("Bitmap must be non-null");
+ }
+ if (bitmap == mBitmap && tileX == mTileX && tileY == mTileY) {
+ return;
+ }
+ discardNativeInstance();
mBitmap = bitmap;
mTileX = tileX;
mTileY = tileY;
- init(nativeCreate(bitmap, tileX.nativeInt, tileY.nativeInt));
+ }
+
+ @Override
+ long createNativeInstance(long nativeMatrix) {
+ return nativeCreate(nativeMatrix, mBitmap, mTileX, mTileY);
}
/**
@@ -57,6 +90,6 @@
return copy;
}
- private static native long nativeCreate(Bitmap bitmap, int shaderTileModeX,
- int shaderTileModeY);
+ private static native long nativeCreate(long nativeMatrix, Bitmap bitmap,
+ int shaderTileModeX, int shaderTileModeY);
}
diff --git a/graphics/java/android/graphics/ComposeShader.java b/graphics/java/android/graphics/ComposeShader.java
index 36fc596..8438bf2 100644
--- a/graphics/java/android/graphics/ComposeShader.java
+++ b/graphics/java/android/graphics/ComposeShader.java
@@ -16,44 +16,107 @@
package android.graphics;
+
+import android.annotation.NonNull;
+
/** A subclass of shader that returns the composition of two other shaders, combined by
an {@link android.graphics.Xfermode} subclass.
*/
public class ComposeShader extends Shader {
+ Shader mShaderA;
+ private long mNativeInstanceShaderA;
+ Shader mShaderB;
+ private long mNativeInstanceShaderB;
private int mPorterDuffMode;
- final Shader mShaderA;
- final Shader mShaderB;
- /** Create a new compose shader, given shaders A, B, and a combining mode.
- When the mode is applied, it will be given the result from shader A as its
- "dst", and the result from shader B as its "src".
- @param shaderA The colors from this shader are seen as the "dst" by the mode
- @param shaderB The colors from this shader are seen as the "src" by the mode
- @param mode The mode that combines the colors from the two shaders. If mode
- is null, then SRC_OVER is assumed.
+ /**
+ * Create a new compose shader, given shaders A, B, and a combining mode.
+ * When the mode is applied, it will be given the result from shader A as its
+ * "dst", and the result from shader B as its "src".
+ *
+ * @param shaderA The colors from this shader are seen as the "dst" by the mode
+ * @param shaderB The colors from this shader are seen as the "src" by the mode
+ * @param mode The mode that combines the colors from the two shaders. If mode
+ * is null, then SRC_OVER is assumed.
*/
- public ComposeShader(Shader shaderA, Shader shaderB, Xfermode mode) {
+ public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull Xfermode mode) {
this(shaderA, shaderB, mode.porterDuffMode);
}
- /** Create a new compose shader, given shaders A, B, and a combining PorterDuff mode.
- When the mode is applied, it will be given the result from shader A as its
- "dst", and the result from shader B as its "src".
- @param shaderA The colors from this shader are seen as the "dst" by the mode
- @param shaderB The colors from this shader are seen as the "src" by the mode
- @param mode The PorterDuff mode that combines the colors from the two shaders.
+ /**
+ * Create a new compose shader, given shaders A, B, and a combining PorterDuff mode.
+ * When the mode is applied, it will be given the result from shader A as its
+ * "dst", and the result from shader B as its "src".
+ *
+ * @param shaderA The colors from this shader are seen as the "dst" by the mode
+ * @param shaderB The colors from this shader are seen as the "src" by the mode
+ * @param mode The PorterDuff mode that combines the colors from the two shaders.
*/
- public ComposeShader(Shader shaderA, Shader shaderB, PorterDuff.Mode mode) {
+ public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB,
+ @NonNull PorterDuff.Mode mode) {
this(shaderA, shaderB, mode.nativeInt);
}
private ComposeShader(Shader shaderA, Shader shaderB, int nativeMode) {
+ setInternal(shaderA, shaderB, nativeMode);
+ }
+
+ /**
+ * Reinitialize the ComposeShader's component Shaders and blend mode.
+ *
+ * @param shaderA The colors from this shader are seen as the "dst" by the mode
+ * @param shaderB The colors from this shader are seen as the "src" by the mode
+ * @param mode The PorterDuff mode that combines the colors from the two shaders.
+ */
+ public void set(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull Xfermode mode) {
+ setInternal(shaderA, shaderB, mode.porterDuffMode);
+ }
+
+ /**
+ * Reinitialize the ComposeShader's component Shaders and blend mode.
+ *
+ * @param shaderA The colors from this shader are seen as the "dst" by the mode
+ * @param shaderB The colors from this shader are seen as the "src" by the mode
+ * @param mode The PorterDuff mode that combines the colors from the two shaders.
+ */
+ public void set(@NonNull Shader shaderA, @NonNull Shader shaderB,
+ @NonNull PorterDuff.Mode mode) {
+ setInternal(shaderA, shaderB, mode.nativeInt);
+ }
+
+ private void setInternal(Shader shaderA, Shader shaderB, int nativeMode) {
+ if (shaderA == null || shaderB == null) {
+ throw new IllegalArgumentException("Shader parameters must not be null");
+ }
+
+ if (shaderA == mShaderA && shaderB == mShaderB && mPorterDuffMode == nativeMode) {
+ // no work to do...
+ return;
+ }
+
+ discardNativeInstance();
mShaderA = shaderA;
mShaderB = shaderB;
mPorterDuffMode = nativeMode;
- init(nativeCreate(shaderA.getNativeInstance(), shaderB.getNativeInstance(),
- nativeMode));
+ }
+
+ @Override
+ long createNativeInstance(long nativeMatrix) {
+ mNativeInstanceShaderA = mShaderA.getNativeInstance();
+ mNativeInstanceShaderB = mShaderB.getNativeInstance();
+ return nativeCreate(nativeMatrix,
+ mShaderA.getNativeInstance(), mShaderB.getNativeInstance(), mPorterDuffMode);
+ }
+
+ @Override
+ void verifyNativeInstance() {
+ if (mShaderA.getNativeInstance() != mNativeInstanceShaderA
+ || mShaderB.getNativeInstance() != mNativeInstanceShaderB) {
+ // Child shader native instance has been updated,
+ // so our cached native instance is no longer valid - discard it
+ discardNativeInstance();
+ }
}
/**
@@ -67,6 +130,6 @@
return copy;
}
- private static native long nativeCreate(long native_shaderA, long native_shaderB,
- int porterDuffMode);
+ private static native long nativeCreate(long nativeMatrix,
+ long nativeShaderA, long nativeShaderB, int porterDuffMode);
}
diff --git a/graphics/java/android/graphics/LinearGradient.java b/graphics/java/android/graphics/LinearGradient.java
index 7b1145c..0e4cd0a 100644
--- a/graphics/java/android/graphics/LinearGradient.java
+++ b/graphics/java/android/graphics/LinearGradient.java
@@ -16,6 +16,10 @@
package android.graphics;
+import android.annotation.ColorInt;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
public class LinearGradient extends Shader {
private static final int TYPE_COLORS_AND_POSITIONS = 1;
@@ -38,47 +42,88 @@
private TileMode mTileMode;
- /** Create a shader that draws a linear gradient along a line.
- @param x0 The x-coordinate for the start of the gradient line
- @param y0 The y-coordinate for the start of the gradient line
- @param x1 The x-coordinate for the end of the gradient line
- @param y1 The y-coordinate for the end of the gradient line
- @param colors The colors to be distributed along the gradient line
- @param positions May be null. The relative positions [0..1] of
- each corresponding color in the colors array. If this is null,
- the the colors are distributed evenly along the gradient line.
- @param tile The Shader tiling mode
+ /**
+ * Create a shader that draws a linear gradient along a line.
+ *
+ * @param x0 The x-coordinate for the start of the gradient line
+ * @param y0 The y-coordinate for the start of the gradient line
+ * @param x1 The x-coordinate for the end of the gradient line
+ * @param y1 The y-coordinate for the end of the gradient line
+ * @param colors The colors to be distributed along the gradient line
+ * @param positions May be null. The relative positions [0..1] of
+ * each corresponding color in the colors array. If this is null,
+ * the the colors are distributed evenly along the gradient line.
+ * @param tile The Shader tiling mode
*/
- public LinearGradient(float x0, float y0, float x1, float y1, int colors[], float positions[],
- TileMode tile) {
+ public LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[],
+ @Nullable float positions[], @NonNull TileMode tile) {
+ set(x0, y0, x1, y1, colors, positions, tile);
+ }
+
+ /**
+ * Create a shader that draws a linear gradient along a line.
+ *
+ * @param x0 The x-coordinate for the start of the gradient line
+ * @param y0 The y-coordinate for the start of the gradient line
+ * @param x1 The x-coordinate for the end of the gradient line
+ * @param y1 The y-coordinate for the end of the gradient line
+ * @param color0 The color at the start of the gradient line.
+ * @param color1 The color at the end of the gradient line.
+ * @param tile The Shader tiling mode
+ */
+ public LinearGradient(float x0, float y0, float x1, float y1,
+ @ColorInt int color0, @ColorInt int color1,
+ @NonNull TileMode tile) {
+ set(x0, y0, x1, y1, color0, color1, tile);
+ }
+
+ /**
+ * Reinitialize the shader.
+ *
+ * @param x0 The x-coordinate for the start of the gradient line
+ * @param y0 The y-coordinate for the start of the gradient line
+ * @param x1 The x-coordinate for the end of the gradient line
+ * @param y1 The y-coordinate for the end of the gradient line
+ * @param colors The colors to be distributed along the gradient line
+ * @param positions May be null. The relative positions [0..1] of
+ * each corresponding color in the colors array. If this is null,
+ * the the colors are distributed evenly along the gradient line.
+ * @param tile The Shader tiling mode
+ */
+ public void set(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[],
+ @Nullable float positions[], @NonNull TileMode tile) {
if (colors.length < 2) {
throw new IllegalArgumentException("needs >= 2 number of colors");
}
if (positions != null && colors.length != positions.length) {
throw new IllegalArgumentException("color and position arrays must be of equal length");
}
+ discardNativeInstance();
mType = TYPE_COLORS_AND_POSITIONS;
mX0 = x0;
mY0 = y0;
mX1 = x1;
mY1 = y1;
- mColors = colors;
- mPositions = positions;
+ mColors = colors.clone();
+ mPositions = positions != null ? positions.clone() : null;
mTileMode = tile;
- init(nativeCreate1(x0, y0, x1, y1, colors, positions, tile.nativeInt));
}
- /** Create a shader that draws a linear gradient along a line.
- @param x0 The x-coordinate for the start of the gradient line
- @param y0 The y-coordinate for the start of the gradient line
- @param x1 The x-coordinate for the end of the gradient line
- @param y1 The y-coordinate for the end of the gradient line
- @param color0 The color at the start of the gradient line.
- @param color1 The color at the end of the gradient line.
- @param tile The Shader tiling mode
+ /**
+ * Reinitialize the shader.
+ *
+ * @param x0 The x-coordinate for the start of the gradient line
+ * @param y0 The y-coordinate for the start of the gradient line
+ * @param x1 The x-coordinate for the end of the gradient line
+ * @param y1 The y-coordinate for the end of the gradient line
+ * @param color0 The color at the start of the gradient line.
+ * @param color1 The color at the end of the gradient line.
+ * @param tile The Shader tiling mode
*/
- public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1,
- TileMode tile) {
+ public void set(float x0, float y0, float x1, float y1,
+ @ColorInt int color0, @ColorInt int color1,
+ @NonNull TileMode tile) {
+ discardNativeInstance();
mType = TYPE_COLOR_START_AND_COLOR_END;
mX0 = x0;
mY0 = y0;
@@ -86,8 +131,20 @@
mY1 = y1;
mColor0 = color0;
mColor1 = color1;
+ mColors = null;
+ mPositions = null;
mTileMode = tile;
- init(nativeCreate2(x0, y0, x1, y1, color0, color1, tile.nativeInt));
+ }
+
+ @Override
+ long createNativeInstance(long nativeMatrix) {
+ if (mType == TYPE_COLORS_AND_POSITIONS) {
+ return nativeCreate1(nativeMatrix, mX0, mY0, mX1, mY1,
+ mColors, mPositions, mTileMode.nativeInt);
+ } else { // TYPE_COLOR_START_AND_COLOR_END
+ return nativeCreate2(nativeMatrix, mX0, mY0, mX1, mY1,
+ mColor0, mColor1, mTileMode.nativeInt);
+ }
}
/**
@@ -96,24 +153,18 @@
@Override
protected Shader copy() {
final LinearGradient copy;
- switch (mType) {
- case TYPE_COLORS_AND_POSITIONS:
- copy = new LinearGradient(mX0, mY0, mX1, mY1, mColors.clone(),
- mPositions != null ? mPositions.clone() : null, mTileMode);
- break;
- case TYPE_COLOR_START_AND_COLOR_END:
- copy = new LinearGradient(mX0, mY0, mX1, mY1, mColor0, mColor1, mTileMode);
- break;
- default:
- throw new IllegalArgumentException("LinearGradient should be created with either " +
- "colors and positions or start color and end color");
+ if (mType == TYPE_COLORS_AND_POSITIONS) {
+ copy = new LinearGradient(mX0, mY0, mX1, mY1, mColors.clone(),
+ mPositions != null ? mPositions.clone() : null, mTileMode);
+ } else { // TYPE_COLOR_START_AND_COLOR_END
+ copy = new LinearGradient(mX0, mY0, mX1, mY1, mColor0, mColor1, mTileMode);
}
copyLocalMatrix(copy);
return copy;
}
- private native long nativeCreate1(float x0, float y0, float x1, float y1,
+ private native long nativeCreate1(long matrix, float x0, float y0, float x1, float y1,
int colors[], float positions[], int tileMode);
- private native long nativeCreate2(float x0, float y0, float x1, float y1,
+ private native long nativeCreate2(long matrix, float x0, float y0, float x1, float y1,
int color0, int color1, int tileMode);
}
diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java
index ade14c64..ae8f7da 100644
--- a/graphics/java/android/graphics/RadialGradient.java
+++ b/graphics/java/android/graphics/RadialGradient.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.ColorInt;
public class RadialGradient extends Shader {
@@ -40,19 +41,55 @@
private TileMode mTileMode;
- /** Create a shader that draws a radial gradient given the center and radius.
- @param centerX The x-coordinate of the center of the radius
- @param centerY The y-coordinate of the center of the radius
- @param radius Must be positive. The radius of the circle for this gradient.
- @param colors The colors to be distributed between the center and edge of the circle
- @param stops May be <code>null</code>. Valid values are between <code>0.0f</code> and
- <code>1.0f</code>. The relative position of each corresponding color in
- the colors array. If <code>null</code>, colors are distributed evenly
- between the center and edge of the circle.
- @param tileMode The Shader tiling mode
- */
+ /**
+ * Create a shader that draws a radial gradient given the center and radius.
+ *
+ * @param centerX The x-coordinate of the center of the radius
+ * @param centerY The y-coordinate of the center of the radius
+ * @param radius Must be positive. The radius of the circle for this gradient.
+ * @param colors The colors to be distributed between the center and edge of the circle
+ * @param stops May be <code>null</code>. Valid values are between <code>0.0f</code> and
+ * <code>1.0f</code>. The relative position of each corresponding color in
+ * the colors array. If <code>null</code>, colors are distributed evenly
+ * between the center and edge of the circle.
+ * @param tileMode The Shader tiling mode
+ */
public RadialGradient(float centerX, float centerY, float radius,
- @NonNull int colors[], @Nullable float stops[], @NonNull TileMode tileMode) {
+ @NonNull @ColorInt int colors[], @Nullable float stops[],
+ @NonNull TileMode tileMode) {
+ set(centerX, centerY, radius, colors, stops, tileMode);
+ }
+
+ /**
+ * Create a shader that draws a radial gradient given the center and radius.
+ *
+ * @param centerX The x-coordinate of the center of the radius
+ * @param centerY The y-coordinate of the center of the radius
+ * @param radius Must be positive. The radius of the circle for this gradient
+ * @param centerColor The color at the center of the circle.
+ * @param edgeColor The color at the edge of the circle.
+ * @param tileMode The Shader tiling mode
+ */
+ public RadialGradient(float centerX, float centerY, float radius,
+ @ColorInt int centerColor, @ColorInt int edgeColor, @NonNull TileMode tileMode) {
+ set(centerX, centerY, radius, centerColor, edgeColor, tileMode);
+ }
+
+ /**
+ * Reinitialize the shader.
+ *
+ * @param centerX The x-coordinate of the center of the radius
+ * @param centerY The y-coordinate of the center of the radius
+ * @param radius Must be positive. The radius of the circle for this gradient.
+ * @param colors The colors to be distributed between the center and edge of the circle
+ * @param stops May be <code>null</code>. Valid values are between <code>0.0f</code> and
+ * <code>1.0f</code>. The relative position of each corresponding color in
+ * the colors array. If <code>null</code>, colors are distributed evenly
+ * between the center and edge of the circle.
+ * @param tileMode The Shader tiling mode
+ */
+ public void set(float centerX, float centerY, float radius,
+ @NonNull @ColorInt int colors[], @Nullable float stops[], @NonNull TileMode tileMode) {
if (radius <= 0) {
throw new IllegalArgumentException("radius must be > 0");
}
@@ -62,29 +99,32 @@
if (stops != null && colors.length != stops.length) {
throw new IllegalArgumentException("color and position arrays must be of equal length");
}
+ discardNativeInstance();
mType = TYPE_COLORS_AND_POSITIONS;
mX = centerX;
mY = centerY;
mRadius = radius;
- mColors = colors;
- mPositions = stops;
+ mColors = colors.clone();
+ mPositions = stops != null ? stops.clone() : null;
mTileMode = tileMode;
- init(nativeCreate1(centerX, centerY, radius, colors, stops, tileMode.nativeInt));
}
- /** Create a shader that draws a radial gradient given the center and radius.
- @param centerX The x-coordinate of the center of the radius
- @param centerY The y-coordinate of the center of the radius
- @param radius Must be positive. The radius of the circle for this gradient
- @param centerColor The color at the center of the circle.
- @param edgeColor The color at the edge of the circle.
- @param tileMode The Shader tiling mode
- */
- public RadialGradient(float centerX, float centerY, float radius,
- int centerColor, int edgeColor, @NonNull TileMode tileMode) {
+ /**
+ * Reinitialize the shader.
+ *
+ * @param centerX The x-coordinate of the center of the radius
+ * @param centerY The y-coordinate of the center of the radius
+ * @param radius Must be positive. The radius of the circle for this gradient
+ * @param centerColor The color at the center of the circle.
+ * @param edgeColor The color at the edge of the circle.
+ * @param tileMode The Shader tiling mode
+ */
+ public void set(float centerX, float centerY, float radius,
+ @ColorInt int centerColor, @ColorInt int edgeColor, @NonNull TileMode tileMode) {
if (radius <= 0) {
throw new IllegalArgumentException("radius must be > 0");
}
+ discardNativeInstance();
mType = TYPE_COLOR_CENTER_AND_COLOR_EDGE;
mX = centerX;
mY = centerY;
@@ -92,7 +132,17 @@
mCenterColor = centerColor;
mEdgeColor = edgeColor;
mTileMode = tileMode;
- init(nativeCreate2(centerX, centerY, radius, centerColor, edgeColor, tileMode.nativeInt));
+ }
+
+ @Override
+ long createNativeInstance(long nativeMatrix) {
+ if (mType == TYPE_COLORS_AND_POSITIONS) {
+ return nativeCreate1(nativeMatrix, mX, mY, mRadius,
+ mColors, mPositions, mTileMode.nativeInt);
+ } else { // TYPE_COLOR_CENTER_AND_COLOR_EDGE
+ return nativeCreate2(nativeMatrix, mX, mY, mRadius,
+ mCenterColor, mEdgeColor, mTileMode.nativeInt);
+ }
}
/**
@@ -101,25 +151,19 @@
@Override
protected Shader copy() {
final RadialGradient copy;
- switch (mType) {
- case TYPE_COLORS_AND_POSITIONS:
- copy = new RadialGradient(mX, mY, mRadius, mColors.clone(),
- mPositions != null ? mPositions.clone() : null, mTileMode);
- break;
- case TYPE_COLOR_CENTER_AND_COLOR_EDGE:
- copy = new RadialGradient(mX, mY, mRadius, mCenterColor, mEdgeColor, mTileMode);
- break;
- default:
- throw new IllegalArgumentException("RadialGradient should be created with either " +
- "colors and positions or center color and edge color");
+ if (mType == TYPE_COLORS_AND_POSITIONS) {
+ copy = new RadialGradient(mX, mY, mRadius, mColors.clone(),
+ mPositions != null ? mPositions.clone() : null, mTileMode);
+ } else { // TYPE_COLOR_CENTER_AND_COLOR_EDGE
+ copy = new RadialGradient(mX, mY, mRadius, mCenterColor, mEdgeColor, mTileMode);
}
copyLocalMatrix(copy);
return copy;
}
- private static native long nativeCreate1(float x, float y, float radius,
+ private static native long nativeCreate1(long matrix, float x, float y, float radius,
int colors[], float positions[], int tileMode);
- private static native long nativeCreate2(float x, float y, float radius,
+ private static native long nativeCreate2(long matrix, float x, float y, float radius,
int color0, int color1, int tileMode);
}
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index 94983b3..a91b410 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -16,6 +16,9 @@
package android.graphics;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
/**
* Shader is the based class for objects that return horizontal spans of colors
* during drawing. A subclass of Shader is installed in a Paint calling
@@ -24,18 +27,16 @@
*/
public class Shader {
/**
- * This is set by subclasses, but don't make it public.
+ * @deprecated Use subclass constructors directly instead.
*/
- private long native_instance;
+ @Deprecated
+ public Shader() {}
/**
- * Initialization step that should be called by subclasses in their
- * constructors. Calling again may result in memory leaks.
- * @hide
+ * Current native shader instance. Created and updated lazily when {@link #getNativeInstance()}
+ * is called - otherwise may be out of date with java setters/properties.
*/
- protected void init(long ni) {
- native_instance = ni;
- }
+ private long mNativeInstance;
private Matrix mLocalMatrix;
@@ -63,13 +64,13 @@
/**
* Return true if the shader has a non-identity local matrix.
- * @param localM If not null, it is set to the shader's local matrix.
+ * @param localM Set to the local matrix of the shader, if the shader's matrix is non-null.
* @return true if the shader has a non-identity local matrix
*/
- public boolean getLocalMatrix(Matrix localM) {
+ public boolean getLocalMatrix(@NonNull Matrix localM) {
if (mLocalMatrix != null) {
localM.set(mLocalMatrix);
- return !mLocalMatrix.isIdentity();
+ return true;
}
return false;
}
@@ -80,18 +81,46 @@
*
* @param localM The shader's new local matrix, or null to specify identity
*/
- public void setLocalMatrix(Matrix localM) {
- mLocalMatrix = localM;
- native_instance = nativeSetLocalMatrix(native_instance,
- localM == null ? 0 : localM.native_instance);
+ public void setLocalMatrix(@Nullable Matrix localM) {
+ if (localM == null || localM.isIdentity()) {
+ if (mLocalMatrix != null) {
+ mLocalMatrix = null;
+ discardNativeInstance();
+ }
+ } else {
+ if (mLocalMatrix == null) {
+ mLocalMatrix = new Matrix(localM);
+ discardNativeInstance();
+ } else if (!mLocalMatrix.equals(localM)) {
+ mLocalMatrix.set(localM);
+ discardNativeInstance();
+ }
+ }
}
+ long createNativeInstance(long nativeMatrix) {
+ return 0;
+ }
+
+ void discardNativeInstance() {
+ nativeSafeUnref(mNativeInstance);
+ mNativeInstance = 0;
+ }
+
+ /**
+ * Callback for subclasses to call {@link #discardNativeInstance()} if the most recently
+ * constructed native instance is no longer valid.
+ */
+ void verifyNativeInstance() {
+ }
+
+ @Override
protected void finalize() throws Throwable {
try {
- super.finalize();
+ nativeSafeUnref(mNativeInstance);
+ mNativeInstance = -1;
} finally {
- nativeDestructor(native_instance);
- native_instance = 0; // Other finalizers can still call us.
+ super.finalize();
}
}
@@ -108,22 +137,26 @@
* @hide
*/
protected void copyLocalMatrix(Shader dest) {
- if (mLocalMatrix != null) {
- final Matrix lm = new Matrix();
- getLocalMatrix(lm);
- dest.setLocalMatrix(lm);
- } else {
- dest.setLocalMatrix(null);
- }
+ dest.mLocalMatrix.set(mLocalMatrix);
}
/**
* @hide
*/
public long getNativeInstance() {
- return native_instance;
+ if (mNativeInstance == -1) {
+ throw new IllegalStateException("attempting to use a finalized Shader");
+ }
+
+ // verify mNativeInstance is valid
+ verifyNativeInstance();
+
+ if (mNativeInstance == 0) {
+ mNativeInstance = createNativeInstance(mLocalMatrix == null
+ ? 0 : mLocalMatrix.native_instance);
+ }
+ return mNativeInstance;
}
- private static native void nativeDestructor(long native_shader);
- private static native long nativeSetLocalMatrix(long native_shader, long matrix_instance);
+ private static native void nativeSafeUnref(long nativeInstance);
}
diff --git a/graphics/java/android/graphics/SweepGradient.java b/graphics/java/android/graphics/SweepGradient.java
index 008891d..0a1aef6 100644
--- a/graphics/java/android/graphics/SweepGradient.java
+++ b/graphics/java/android/graphics/SweepGradient.java
@@ -16,6 +16,10 @@
package android.graphics;
+import android.annotation.ColorInt;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
public class SweepGradient extends Shader {
private static final int TYPE_COLORS_AND_POSITIONS = 1;
@@ -35,7 +39,7 @@
private int mColor1;
/**
- * A subclass of Shader that draws a sweep gradient around a center point.
+ * A Shader that draws a sweep gradient around a center point.
*
* @param cx The x-coordinate of the center
* @param cy The y-coordinate of the center
@@ -49,37 +53,79 @@
* spaced evenly.
*/
public SweepGradient(float cx, float cy,
- int colors[], float positions[]) {
- if (colors.length < 2) {
- throw new IllegalArgumentException("needs >= 2 number of colors");
- }
- if (positions != null && colors.length != positions.length) {
- throw new IllegalArgumentException(
- "color and position arrays must be of equal length");
- }
- mType = TYPE_COLORS_AND_POSITIONS;
- mCx = cx;
- mCy = cy;
- mColors = colors;
- mPositions = positions;
- init(nativeCreate1(cx, cy, colors, positions));
+ @NonNull @ColorInt int colors[], @Nullable float positions[]) {
+ set(cx, cy, colors, positions);
}
/**
- * A subclass of Shader that draws a sweep gradient around a center point.
+ * A Shader that draws a sweep gradient around a center point.
*
* @param cx The x-coordinate of the center
* @param cy The y-coordinate of the center
* @param color0 The color to use at the start of the sweep
* @param color1 The color to use at the end of the sweep
*/
- public SweepGradient(float cx, float cy, int color0, int color1) {
+ public SweepGradient(float cx, float cy, @ColorInt int color0, @ColorInt int color1) {
+ set(cx, cy, color0, color1);
+ }
+
+ /**
+ * Reinitialize the shader.
+ *
+ * @param cx The x-coordinate of the center
+ * @param cy The y-coordinate of the center
+ * @param colors The colors to be distributed between around the center.
+ * There must be at least 2 colors in the array.
+ * @param positions May be NULL. The relative position of
+ * each corresponding color in the colors array, beginning
+ * with 0 and ending with 1.0. If the values are not
+ * monotonic, the drawing may produce unexpected results.
+ * If positions is NULL, then the colors are automatically
+ * spaced evenly.
+ */
+ public void set(float cx, float cy,
+ @NonNull @ColorInt int colors[], @Nullable float positions[]) {
+ if (colors.length < 2) {
+ throw new IllegalArgumentException("needs >= 2 number of colors");
+ }
+ if (positions != null && colors.length != positions.length) {
+ throw new IllegalArgumentException(
+ "color and position arrays must be of equal length");
+ }
+ discardNativeInstance();
+ mType = TYPE_COLORS_AND_POSITIONS;
+ mCx = cx;
+ mCy = cy;
+ mColors = colors.clone();
+ mPositions = positions != null ? positions.clone() : null;
+ }
+
+ /**
+ * Reinitialize the shader.
+ *
+ * @param cx The x-coordinate of the center
+ * @param cy The y-coordinate of the center
+ * @param color0 The color to use at the start of the sweep
+ * @param color1 The color to use at the end of the sweep
+ */
+ public void set(float cx, float cy, @ColorInt int color0, @ColorInt int color1) {
+ discardNativeInstance();
mType = TYPE_COLOR_START_AND_COLOR_END;
mCx = cx;
mCy = cy;
mColor0 = color0;
mColor1 = color1;
- init(nativeCreate2(cx, cy, color0, color1));
+ mColors = null;
+ mPositions = null;
+ }
+
+ @Override
+ long createNativeInstance(long nativeMatrix) {
+ if (mType == TYPE_COLORS_AND_POSITIONS) {
+ return nativeCreate1(nativeMatrix, mCx, mCy, mColors, mPositions);
+ } else { // TYPE_COLOR_START_AND_COLOR_END
+ return nativeCreate2(nativeMatrix, mCx, mCy, mColor0, mColor1);
+ }
}
/**
@@ -88,23 +134,19 @@
@Override
protected Shader copy() {
final SweepGradient copy;
- switch (mType) {
- case TYPE_COLORS_AND_POSITIONS:
- copy = new SweepGradient(mCx, mCy, mColors.clone(),
- mPositions != null ? mPositions.clone() : null);
- break;
- case TYPE_COLOR_START_AND_COLOR_END:
- copy = new SweepGradient(mCx, mCy, mColor0, mColor1);
- break;
- default:
- throw new IllegalArgumentException("SweepGradient should be created with either " +
- "colors and positions or start color and end color");
+ if (mType == TYPE_COLORS_AND_POSITIONS) {
+ copy = new SweepGradient(mCx, mCy, mColors.clone(),
+ mPositions != null ? mPositions.clone() : null);
+ } else { // TYPE_COLOR_START_AND_COLOR_END
+ copy = new SweepGradient(mCx, mCy, mColor0, mColor1);
}
copyLocalMatrix(copy);
return copy;
}
- private static native long nativeCreate1(float x, float y, int colors[], float positions[]);
- private static native long nativeCreate2(float x, float y, int color0, int color1);
+ private static native long nativeCreate1(long matrix, float x, float y,
+ int colors[], float positions[]);
+ private static native long nativeCreate2(long matrix, float x, float y,
+ int color0, int color1);
}
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 8b30903..6de19cb 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -32,7 +32,6 @@
import android.util.LongSparseArray;
import android.util.LruCache;
import android.util.SparseArray;
-import android.graphics.FontListParser;
import com.android.internal.annotations.GuardedBy;
@@ -287,13 +286,11 @@
callback.onTypefaceRetrieved(cachedTypeface);
return;
}
- if (resultCode == FontsContract.RESULT_CODE_PROVIDER_NOT_FOUND) {
- callback.onTypefaceRequestFailed(
- FontRequestCallback.FAIL_REASON_PROVIDER_NOT_FOUND);
+ if (resultCode != FontsContract.Columns.RESULT_CODE_OK) {
+ callback.onTypefaceRequestFailed(resultCode);
return;
}
- if (resultCode == FontsContract.RESULT_CODE_FONT_NOT_FOUND
- || resultData == null) {
+ if (resultData == null) {
callback.onTypefaceRequestFailed(
FontRequestCallback.FAIL_REASON_FONT_NOT_FOUND);
return;
@@ -356,21 +353,37 @@
* Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
* provider was not found on the device.
*/
- int FAIL_REASON_PROVIDER_NOT_FOUND = 0;
+ int FAIL_REASON_PROVIDER_NOT_FOUND = FontsContract.RESULT_CODE_PROVIDER_NOT_FOUND;
+ /**
+ * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
+ * provider must be authenticated and the given certificates do not match its signature.
+ */
+ int FAIL_REASON_WRONG_CERTIFICATES = FontsContract.RESULT_CODE_WRONG_CERTIFICATES;
/**
* Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
* returned by the provider was not loaded properly.
*/
- int FAIL_REASON_FONT_LOAD_ERROR = 1;
+ int FAIL_REASON_FONT_LOAD_ERROR = -3;
/**
- * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
+ * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
* provider did not return any results for the given query.
*/
- int FAIL_REASON_FONT_NOT_FOUND = 2;
+ int FAIL_REASON_FONT_NOT_FOUND = FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND;
+ /**
+ * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
+ * provider found the queried font, but it is currently unavailable.
+ */
+ int FAIL_REASON_FONT_UNAVAILABLE = FontsContract.Columns.RESULT_CODE_FONT_UNAVAILABLE;
+ /**
+ * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
+ * query was not supported by the provider.
+ */
+ int FAIL_REASON_MALFORMED_QUERY = FontsContract.Columns.RESULT_CODE_MALFORMED_QUERY;
/** @hide */
- @IntDef({FAIL_REASON_PROVIDER_NOT_FOUND, FAIL_REASON_FONT_LOAD_ERROR,
- FAIL_REASON_FONT_NOT_FOUND})
+ @IntDef({ FAIL_REASON_PROVIDER_NOT_FOUND, FAIL_REASON_FONT_LOAD_ERROR,
+ FAIL_REASON_FONT_NOT_FOUND, FAIL_REASON_FONT_UNAVAILABLE,
+ FAIL_REASON_MALFORMED_QUERY })
@Retention(RetentionPolicy.SOURCE)
@interface FontRequestFailReason {}
@@ -386,8 +399,10 @@
* Called when a Typeface request done via {@link Typeface#create(FontRequest,
* FontRequestCallback)} fails.
* @param reason One of {@link #FAIL_REASON_PROVIDER_NOT_FOUND},
- * {@link #FAIL_REASON_FONT_NOT_FOUND} or
- * {@link #FAIL_REASON_FONT_LOAD_ERROR}.
+ * {@link #FAIL_REASON_FONT_NOT_FOUND},
+ * {@link #FAIL_REASON_FONT_LOAD_ERROR},
+ * {@link #FAIL_REASON_FONT_UNAVAILABLE} or
+ * {@link #FAIL_REASON_MALFORMED_QUERY}.
*/
void onTypefaceRequestFailed(@FontRequestFailReason int reason);
}
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index c6fbe2bd5..e39614b 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -91,8 +91,6 @@
LayerUpdateQueue* layerUpdateQueue = nullptr;
ErrorHandler* errorHandler = nullptr;
- int32_t windowInsetLeft = 0;
- int32_t windowInsetTop = 0;
bool updateWindowPositions = false;
struct Out {
diff --git a/media/java/android/media/AudioFocusRequest.java b/media/java/android/media/AudioFocusRequest.java
index 1b75a78..73f912b 100644
--- a/media/java/android/media/AudioFocusRequest.java
+++ b/media/java/android/media/AudioFocusRequest.java
@@ -303,12 +303,12 @@
* by this {@code Builder}'s configuration methods.
* @return the {@code AudioFocusRequest} instance qualified by all the properties set
* on this {@code Builder}.
- * @throws IllegalArgumentException thrown when focus request is set to accept delayed
- * focus, or to pause on duck, but no focus change listener was set.
+ * @throws IllegalStateException thrown when attempting to build a focus request that is set
+ * to accept delayed focus, or to pause on duck, but no focus change listener was set.
*/
public AudioFocusRequest build() {
if ((mDelayedFocus || mPausesOnDuck) && (mFocusListener == null)) {
- throw new IllegalArgumentException(
+ throw new IllegalStateException(
"Can't use delayed focus or pause on duck without a listener");
}
final int flags = 0
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index dc69a69..f13ccc1 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2234,8 +2234,11 @@
* Use {@link #AUDIOFOCUS_GAIN} for a focus request of unknown duration such
* as the playback of a song or a video.
* @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED}
+ * @deprecated use {@link #requestAudioFocus(AudioFocusRequest)}
*/
public int requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint) {
+ PlayerBase.deprecateStreamTypeForPlayback(streamType,
+ "AudioManager", "requestAudioFocus()");
int status = AUDIOFOCUS_REQUEST_FAILED;
try {
@@ -2502,6 +2505,7 @@
* Abandon audio focus. Causes the previous focus owner, if any, to receive focus.
* @param l the listener with which focus was requested.
* @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED}
+ * @deprecated use {@link #abandonAudioFocusRequest(AudioFocusRequest)}
*/
public int abandonAudioFocus(OnAudioFocusChangeListener l) {
return abandonAudioFocus(l, null /*AudioAttributes, legacy behavior*/);
diff --git a/media/java/android/media/VolumeShaper.java b/media/java/android/media/VolumeShaper.java
index 796d6f3..af11e07 100644
--- a/media/java/android/media/VolumeShaper.java
+++ b/media/java/android/media/VolumeShaper.java
@@ -431,8 +431,8 @@
dest.writeDouble(mDurationMs);
// this needs to match the native Interpolator parceling
dest.writeInt(mInterpolatorType);
- dest.writeFloat(0.f); // first slope
- dest.writeFloat(0.f); // last slope
+ dest.writeFloat(0.f); // first slope (specifying for native side)
+ dest.writeFloat(0.f); // last slope (specifying for native side)
// mTimes and mVolumes should have the same length.
dest.writeInt(mTimes.length);
for (int i = 0; i < mTimes.length; ++i) {
@@ -456,8 +456,8 @@
final double durationMs = p.readDouble();
// this needs to match the native Interpolator parceling
final int interpolatorType = p.readInt();
- final float firstSlope = p.readFloat(); // ignored
- final float lastSlope = p.readFloat(); // ignored
+ final float firstSlope = p.readFloat(); // ignored on the Java side
+ final float lastSlope = p.readFloat(); // ignored on the Java side
final int length = p.readInt();
final float[] times = new float[length];
final float[] volumes = new float[length];
@@ -593,6 +593,10 @@
* {@code times[]} and {@code volumes[]} are two arrays representing points
* for the volume curve.
*
+ * Note that {@code times[]} and {@code volumes[]} are explicitly checked against
+ * null here to provide the proper error string - those are legitimate
+ * arguments to this method.
+ *
* @param times the x coordinates for the points,
* must be between 0.f and 1.f and be monotonic.
* @param volumes the y coordinates for the points,
@@ -644,10 +648,14 @@
}
private static void checkCurveForErrorsAndThrowException(
- @Nullable float[] times, @Nullable float[] volumes, boolean log) {
+ @Nullable float[] times, @Nullable float[] volumes, boolean log, boolean ise) {
final String error = checkCurveForErrors(times, volumes, log);
if (error != null) {
- throw new IllegalArgumentException(error);
+ if (ise) {
+ throw new IllegalStateException(error);
+ } else {
+ throw new IllegalArgumentException(error);
+ }
}
}
@@ -840,8 +848,8 @@
*/
public @NonNull Builder setCurve(@NonNull float[] times, @NonNull float[] volumes) {
- checkCurveForErrorsAndThrowException(
- times, volumes, (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0);
+ final boolean log = (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0;
+ checkCurveForErrorsAndThrowException(times, volumes, log, false /* ise */);
mTimes = times.clone();
mVolumes = volumes.clone();
return this;
@@ -853,11 +861,11 @@
* to the start.
*
* @return the same {@code Builder} instance.
- * @throws IllegalArgumentException if curve has not been set.
+ * @throws IllegalStateException if curve has not been set.
*/
public @NonNull Builder reflectTimes() {
- checkCurveForErrorsAndThrowException(
- mTimes, mVolumes, (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0);
+ final boolean log = (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0;
+ checkCurveForErrorsAndThrowException(mTimes, mVolumes, log, true /* ise */);
int i;
for (i = 0; i < mTimes.length / 2; ++i) {
float temp = mTimes[i];
@@ -878,11 +886,11 @@
* becomes the min volume and vice versa.
*
* @return the same {@code Builder} instance.
- * @throws IllegalArgumentException if curve has not been set.
+ * @throws IllegalStateException if curve has not been set.
*/
public @NonNull Builder invertVolumes() {
- checkCurveForErrorsAndThrowException(
- mTimes, mVolumes, (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0);
+ final boolean log = (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0;
+ checkCurveForErrorsAndThrowException(mTimes, mVolumes, log, true /* ise */);
float min = mVolumes[0];
float max = mVolumes[0];
for (int i = 1; i < mVolumes.length; ++i) {
@@ -908,12 +916,12 @@
*
* @param volume the target end volume to use.
* @return the same {@code Builder} instance.
- * @throws IllegalArgumentException if {@code volume}
- * is not valid or if curve has not been set.
+ * @throws IllegalArgumentException if {@code volume} is not valid.
+ * @throws IllegalStateException if curve has not been set.
*/
public @NonNull Builder scaleToEndVolume(float volume) {
final boolean log = (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0;
- checkCurveForErrorsAndThrowException(mTimes, mVolumes, log);
+ checkCurveForErrorsAndThrowException(mTimes, mVolumes, log, true /* ise */);
checkValidVolumeAndThrowException(volume, log);
final float startVolume = mVolumes[0];
final float endVolume = mVolumes[mVolumes.length - 1];
@@ -942,12 +950,12 @@
*
* @param volume the target start volume to use.
* @return the same {@code Builder} instance.
- * @throws IllegalArgumentException if {@code volume}
- * is not valid or if curve has not been set.
+ * @throws IllegalArgumentException if {@code volume} is not valid.
+ * @throws IllegalStateException if curve has not been set.
*/
public @NonNull Builder scaleToStartVolume(float volume) {
final boolean log = (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0;
- checkCurveForErrorsAndThrowException(mTimes, mVolumes, log);
+ checkCurveForErrorsAndThrowException(mTimes, mVolumes, log, true /* ise */);
checkValidVolumeAndThrowException(volume, log);
final float startVolume = mVolumes[0];
final float endVolume = mVolumes[mVolumes.length - 1];
@@ -971,11 +979,11 @@
* Builds a new {@link VolumeShaper} object.
*
* @return a new {@link VolumeShaper} object.
- * @throws IllegalArgumentException if curve is not properly set.
+ * @throws IllegalStateException if curve is not properly set.
*/
public @NonNull Configuration build() {
- checkCurveForErrorsAndThrowException(
- mTimes, mVolumes, (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0);
+ final boolean log = (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0;
+ checkCurveForErrorsAndThrowException(mTimes, mVolumes, log, true /* ise */);
return new Configuration(mType, mId, mOptionFlags, mDurationMs,
mInterpolatorType, mTimes, mVolumes);
}
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index 81db37e..7122eaf 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -471,6 +471,7 @@
* @param extras The bundle of service-specific arguments to send to the media browser
* service. The contents of this bundle may affect the search result.
* @param callback The callback to receive the search result.
+ * @throws IllegalStateException if the browser is not connected to the media browser service.
*/
public void search(@NonNull final String query, final Bundle extras, SearchCallback callback) {
if (TextUtils.isEmpty(query)) {
@@ -480,14 +481,8 @@
throw new IllegalArgumentException("callback cannot be null.");
}
if (mState != CONNECT_STATE_CONNECTED) {
- Log.i(TAG, "Not connected, unable to search.");
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- callback.onError(query, extras);
- }
- });
- return;
+ throw new IllegalStateException("search() called while not connected (state="
+ + getStateLabel(mState) + ")");
}
ResultReceiver receiver = new ResultReceiver(mHandler) {
@Override
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index aee9d38e..e5af357 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -776,8 +776,8 @@
mSurface = null;
mSurfaceView = new SurfaceView(getContext(), mAttrs, mDefStyleAttr) {
@Override
- protected void updateWindow() {
- super.updateWindow();
+ protected void updateSurface() {
+ super.updateSurface();
relayoutSessionOverlayView();
}};
// The surface view's content should be treated as secure all the time.
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index b00f5a5..f5e19f9 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -722,6 +722,9 @@
LockedImage lockedImg = LockedImage();
Image_getLockedImage(env, thiz, &lockedImg);
+ if (env->ExceptionCheck()) {
+ return NULL;
+ }
// Create all SurfacePlanes
for (int i = 0; i < numPlanes; i++) {
Image_getLockedImageInfo(env, &lockedImg, i, halReaderFormat,
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index 9a78544..476f016 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -45,8 +45,8 @@
import com.android.mediaframeworktest.MediaFrameworkIntegrationTestRunner;
-import org.mockito.ArgumentMatcher;
import org.mockito.ArgumentCaptor;
+import org.mockito.compat.ArgumentMatcher;
import static org.mockito.Mockito.*;
public class CameraDeviceBinderTest extends AndroidTestCase {
@@ -168,7 +168,7 @@
class IsMetadataNotEmpty extends ArgumentMatcher<CameraMetadataNative> {
@Override
- public boolean matches(Object obj) {
+ public boolean matchesObject(Object obj) {
return !((CameraMetadataNative) obj).isEmpty();
}
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java
index 86c2284..712039d 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java
@@ -37,9 +37,9 @@
import android.test.suitebuilder.annotation.SmallTest;
import org.hamcrest.Description;
-import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.compat.ArgumentMatcher;
public class MediaInserterTest extends InstrumentationTestCase {
@@ -67,7 +67,7 @@
}
@Override
- public boolean matches(Object argument) {
+ public boolean matchesObject(Object argument) {
if (!(argument instanceof Uri)) {
return false;
}
@@ -79,13 +79,9 @@
}
@Override
- public void describeTo(Description description) {
- description
- .appendText("expected a TableUri '")
- .appendText(mUri.toString())
- .appendText("'");
+ public String toString() {
+ return "expected a TableUri '" + mUri.toString() + "'";
}
-
}
private static Uri eqUri(Uri in) {
diff --git a/packages/CarrierDefaultApp/AndroidManifest.xml b/packages/CarrierDefaultApp/AndroidManifest.xml
index d910920..2e642ec 100644
--- a/packages/CarrierDefaultApp/AndroidManifest.xml
+++ b/packages/CarrierDefaultApp/AndroidManifest.xml
@@ -17,16 +17,16 @@
*/
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.carrierdefaultapp"
- android:sharedUserId="android.uid.phone" >
+ package="com.android.carrierdefaultapp">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
- <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+ <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
<uses-permission android:name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+ <uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
<application android:label="@string/app_name" >
<receiver android:name="com.android.carrierdefaultapp.CarrierDefaultBroadcastReceiver">
diff --git a/packages/CarrierDefaultApp/res/drawable/ic_sim_card.xml b/packages/CarrierDefaultApp/res/drawable/ic_sim_card.xml
index 5896757..dc54fe2 100644
--- a/packages/CarrierDefaultApp/res/drawable/ic_sim_card.xml
+++ b/packages/CarrierDefaultApp/res/drawable/ic_sim_card.xml
@@ -14,13 +14,12 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="@dimen/glif_icon_size"
- android:height="@dimen/glif_icon_size"
- android:viewportWidth="48"
- android:viewportHeight="48">
- <path
- android:fillColor="?android:attr/colorPrimary"
- android:pathData="M39.98,8c0,-2.21 -1.77,-4 -3.98,-4L20,4L8,16v24c0,2.21 1.79,4 4,4h24.02c2.21,0 3.98,-1.79 3.98,-4l-0.02,-32zM18,38h-4v-4h4v4zM34,38h-4v-4h4v4zM18,30h-4v-8h4v8zM26,38h-4v-8h4v8zM26,26h-4v-4h4v4zM34,30h-4v-8h4v8z" />
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+<path
+ android:fillColor="#757575"
+ android:pathData="M18,2h-8L4.02,8 4,20c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,4c0,-1.1 -0.9,-2 -2,-2zM13,17h-2v-2h2v2zM13,13h-2L11,8h2v5z"/>
</vector>
\ No newline at end of file
diff --git a/packages/CarrierDefaultApp/res/values/strings.xml b/packages/CarrierDefaultApp/res/values/strings.xml
index 838ff39..fe5669d 100644
--- a/packages/CarrierDefaultApp/res/values/strings.xml
+++ b/packages/CarrierDefaultApp/res/values/strings.xml
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">CarrierDefaultApp</string>
- <string name="portal_notification_id">Activate your service</string>
- <string name="no_data_notification_id">No data service</string>
- <string name="portal_notification_detail">Tap to activate your service</string>
- <string name="no_data_notification_detail">No Service, please contact your service provider</string>
+ <string name="android_system_label">Android System</string>
+ <string name="portal_notification_id">Mobile data has run out</string>
+ <string name="no_data_notification_id">No Mobile data service</string>
+ <string name="portal_notification_detail">Tap to add funds to your %s SIM</string>
+ <string name="no_data_notification_detail">Please contact your service provider %s</string>
<string name="progress_dialogue_network_connection">Connecting to captive portal...</string>
<string name="alert_dialogue_network_timeout">Network timeout, would you like to retry?</string>
<string name="alert_dialogue_network_timeout_title">Network unavailable</string>
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
index db4890f..d9bd2fc 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.os.Bundle;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;
@@ -146,18 +147,25 @@
private static Notification getNotification(Context context, int titleId, int textId,
PendingIntent pendingIntent) {
- Resources resources = context.getResources();
+ final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
+ final Resources resources = context.getResources();
+ final Bundle extras = Bundle.forPair(Notification.EXTRA_SUBSTITUTE_APP_NAME,
+ resources.getString(R.string.android_system_label));
Notification.Builder builder = new Notification.Builder(context)
.setContentTitle(resources.getString(titleId))
- .setContentText(resources.getString(textId))
+ .setContentText(String.format(resources.getString(textId),
+ telephonyMgr.getNetworkOperatorName()))
.setSmallIcon(R.drawable.ic_sim_card)
+ .setColor(context.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
.setOngoing(true)
.setPriority(Notification.PRIORITY_HIGH)
.setDefaults(Notification.DEFAULT_ALL)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setLocalOnly(true)
.setWhen(System.currentTimeMillis())
- .setShowWhen(false);
+ .setShowWhen(false)
+ .setExtras(extras);
if (pendingIntent != null) {
builder.setContentIntent(pendingIntent);
diff --git a/packages/CompanionDeviceManager/AndroidManifest.xml b/packages/CompanionDeviceManager/AndroidManifest.xml
index 65cac09..34bc4eb 100644
--- a/packages/CompanionDeviceManager/AndroidManifest.xml
+++ b/packages/CompanionDeviceManager/AndroidManifest.xml
@@ -26,6 +26,8 @@
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+ <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<application
android:allowClearUserData="true"
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
index 12bab18..14b9de5 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
@@ -16,10 +16,9 @@
package com.android.companiondevicemanager;
-import static android.companion.BluetoothDeviceFilterUtils.getDeviceDisplayName;
+import static android.companion.BluetoothDeviceFilterUtils.getDeviceMacAddress;
import android.app.Activity;
-import android.bluetooth.BluetoothDevice;
import android.companion.CompanionDeviceManager;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -34,6 +33,8 @@
import android.widget.ProgressBar;
import android.widget.TextView;
+import com.android.companiondevicemanager.DeviceDiscoveryService.DeviceFilterPair;
+
public class DeviceChooserActivity extends Activity {
private static final boolean DEBUG = false;
@@ -55,11 +56,11 @@
if (getService().mRequest.isSingleDevice()) {
setContentView(R.layout.device_confirmation);
- final BluetoothDevice selectedDevice = getService().mDevicesFound.get(0);
+ final DeviceFilterPair selectedDevice = getService().mDevicesFound.get(0);
setTitle(Html.fromHtml(getString(
R.string.confirmation_title,
getCallingAppName(),
- getDeviceDisplayName(selectedDevice)), 0));
+ selectedDevice.getDisplayName()), 0));
getService().mSelectedDevice = selectedDevice;
} else {
setContentView(R.layout.device_chooser);
@@ -127,10 +128,11 @@
return DeviceDiscoveryService.sInstance;
}
- protected void onPairTapped(BluetoothDevice selectedDevice) {
- getService().onDeviceSelected(getCallingPackage(), selectedDevice.getAddress());
+ protected void onPairTapped(DeviceFilterPair selectedDevice) {
+ getService().onDeviceSelected(
+ getCallingPackage(), getDeviceMacAddress(selectedDevice.device));
setResult(RESULT_OK,
- new Intent().putExtra(CompanionDeviceManager.EXTRA_DEVICE, selectedDevice));
+ new Intent().putExtra(CompanionDeviceManager.EXTRA_DEVICE, selectedDevice.device));
finish();
}
}
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index f0f9108..e1e60bb 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -16,8 +16,10 @@
package com.android.companiondevicemanager;
-import static android.companion.BluetoothDeviceFilterUtils.getDeviceDisplayName;
-import static android.companion.BluetoothLEDeviceFilter.nullsafe;
+import static android.companion.BluetoothDeviceFilterUtils.getDeviceDisplayNameInternal;
+import static android.companion.BluetoothDeviceFilterUtils.getDeviceMacAddress;
+
+import static com.android.internal.util.ArrayUtils.isEmpty;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -32,28 +34,38 @@
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.companion.AssociationRequest;
+import android.companion.BluetoothDeviceFilter;
+import android.companion.BluetoothDeviceFilterUtils;
import android.companion.BluetoothLEDeviceFilter;
import android.companion.CompanionDeviceManager;
+import android.companion.DeviceFilter;
import android.companion.ICompanionDeviceDiscoveryService;
import android.companion.ICompanionDeviceDiscoveryServiceCallback;
import android.companion.IFindDeviceCallback;
+import android.companion.WifiDeviceFilter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
+import android.net.wifi.WifiManager;
import android.os.IBinder;
+import android.os.Parcelable;
import android.os.RemoteException;
+import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.Preconditions;
+
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
+import java.util.Objects;
public class DeviceDiscoveryService extends Service {
@@ -63,12 +75,16 @@
static DeviceDiscoveryService sInstance;
private BluetoothAdapter mBluetoothAdapter;
- private BluetoothLEDeviceFilter mFilter;
- private ScanFilter mScanFilter;
+ private WifiManager mWifiManager;
private ScanSettings mDefaultScanSettings = new ScanSettings.Builder().build();
- AssociationRequest<?> mRequest;
- List<BluetoothDevice> mDevicesFound;
- BluetoothDevice mSelectedDevice;
+ private List<DeviceFilter<?>> mFilters;
+ private List<BluetoothLEDeviceFilter> mBLEFilters;
+ private List<BluetoothDeviceFilter> mBluetoothFilters;
+ private List<WifiDeviceFilter> mWifiFilters;
+ private List<ScanFilter> mBLEScanFilters;
+ AssociationRequest mRequest;
+ List<DeviceFilterPair> mDevicesFound;
+ DeviceFilterPair mSelectedDevice;
DevicesAdapter mDevicesAdapter;
IFindDeviceCallback mFindCallback;
ICompanionDeviceDiscoveryServiceCallback mServiceCallback;
@@ -95,11 +111,13 @@
private final ScanCallback mBLEScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
- final BluetoothDevice device = result.getDevice();
+ final DeviceFilterPair<ScanResult> deviceFilterPair
+ = DeviceFilterPair.findMatch(result, mBLEFilters);
+ if (deviceFilterPair == null) return;
if (callbackType == ScanSettings.CALLBACK_TYPE_MATCH_LOST) {
- onDeviceLost(device);
+ onDeviceLost(deviceFilterPair);
} else {
- onDeviceFound(device);
+ onDeviceFound(deviceFilterPair);
}
}
};
@@ -109,18 +127,38 @@
private BroadcastReceiver mBluetoothDeviceFoundBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- final BluetoothDevice device = intent.getParcelableExtra(
- BluetoothDevice.EXTRA_DEVICE);
- if (!mFilter.matches(device)) return; // ignore device
-
+ final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+ final DeviceFilterPair<BluetoothDevice> deviceFilterPair
+ = DeviceFilterPair.findMatch(device, mBluetoothFilters);
+ if (deviceFilterPair == null) return;
if (intent.getAction().equals(BluetoothDevice.ACTION_FOUND)) {
- onDeviceFound(device);
+ onDeviceFound(deviceFilterPair);
} else {
- onDeviceLost(device);
+ onDeviceLost(deviceFilterPair);
}
}
};
+ private BroadcastReceiver mWifiDeviceFoundBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
+ List<android.net.wifi.ScanResult> scanResults = mWifiManager.getScanResults();
+
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Wifi scan results: " + TextUtils.join("\n", scanResults));
+ }
+
+ for (int i = 0; i < scanResults.size(); i++) {
+ DeviceFilterPair<android.net.wifi.ScanResult> deviceFilterPair =
+ DeviceFilterPair.findMatch(scanResults.get(i), mWifiFilters);
+ if (deviceFilterPair != null) onDeviceFound(deviceFilterPair);
+ }
+ }
+
+ }
+ };
+
@Override
public IBinder onBind(Intent intent) {
if (DEBUG) Log.i(LOG_TAG, "onBind(" + intent + ")");
@@ -135,6 +173,7 @@
mBluetoothAdapter = getSystemService(BluetoothManager.class).getAdapter();
mBLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
+ mWifiManager = getSystemService(WifiManager.class);
mDevicesFound = new ArrayList<>();
mDevicesAdapter = new DevicesAdapter();
@@ -142,23 +181,39 @@
sInstance = this;
}
- private void startDiscovery(AssociationRequest<?> request) {
- //TODO support other protocols as well
+ private void startDiscovery(AssociationRequest request) {
mRequest = request;
- mFilter = nullsafe((BluetoothLEDeviceFilter) request.getDeviceFilter());
- mScanFilter = mFilter.getScanFilter();
+
+ mFilters = request.getDeviceFilters();
+ mWifiFilters = ArrayUtils.filter(mFilters, WifiDeviceFilter.class);
+ mBluetoothFilters = ArrayUtils.filter(mFilters, BluetoothDeviceFilter.class);
+ mBLEFilters = ArrayUtils.filter(mFilters, BluetoothLEDeviceFilter.class);
+ mBLEScanFilters = ArrayUtils.map(mBLEFilters, BluetoothLEDeviceFilter::getScanFilter);
reset();
- final IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
- intentFilter.addAction(BluetoothDevice.ACTION_DISAPPEARED);
+ if (shouldScan(mBluetoothFilters)) {
+ final IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
+ intentFilter.addAction(BluetoothDevice.ACTION_DISAPPEARED);
- registerReceiver(mBluetoothDeviceFoundBroadcastReceiver, intentFilter);
- mBluetoothAdapter.startDiscovery();
+ registerReceiver(mBluetoothDeviceFoundBroadcastReceiver, intentFilter);
+ mBluetoothAdapter.startDiscovery();
+ }
- mBLEScanner.startScan(
- Collections.singletonList(mScanFilter), mDefaultScanSettings, mBLEScanCallback);
+ if (shouldScan(mBLEFilters)) {
+ mBLEScanner.startScan(mBLEScanFilters, mDefaultScanSettings, mBLEScanCallback);
+ }
+
+ if (shouldScan(mWifiFilters)) {
+ registerReceiver(mWifiDeviceFoundBroadcastReceiver,
+ new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
+ mWifiManager.startScan();
+ }
+ }
+
+ private boolean shouldScan(List<? extends DeviceFilter> mediumSpecificFilters) {
+ return !isEmpty(mediumSpecificFilters) || isEmpty(mFilters);
}
private void reset() {
@@ -178,25 +233,18 @@
mBluetoothAdapter.cancelDiscovery();
mBLEScanner.stopScan(mBLEScanCallback);
unregisterReceiver(mBluetoothDeviceFoundBroadcastReceiver);
+ unregisterReceiver(mWifiDeviceFoundBroadcastReceiver);
stopSelf();
}
- private void onDeviceFound(BluetoothDevice device) {
+ private void onDeviceFound(@Nullable DeviceFilterPair device) {
if (mDevicesFound.contains(device)) {
return;
}
- if (DEBUG) {
- Log.i(LOG_TAG, "Considering device " + getDeviceDisplayName(device));
- }
+ if (DEBUG) Log.i(LOG_TAG, "Found device " + device.getDisplayName() + " "
+ + getDeviceMacAddress(device.device));
- if (!mFilter.matches(device)) {
- return;
- }
-
- if (DEBUG) {
- Log.i(LOG_TAG, "Found device " + getDeviceDisplayName(device));
- }
if (mDevicesFound.isEmpty()) {
onReadyToShowUI();
}
@@ -217,12 +265,10 @@
}
}
- private void onDeviceLost(BluetoothDevice device) {
+ private void onDeviceLost(@Nullable DeviceFilterPair device) {
mDevicesFound.remove(device);
mDevicesAdapter.notifyDataSetChanged();
- if (DEBUG) {
- Log.i(LOG_TAG, "Lost device " + getDeviceDisplayName(device));
- }
+ if (DEBUG) Log.i(LOG_TAG, "Lost device " + device.getDisplayName());
}
void onDeviceSelected(String callingPackage, String deviceAddress) {
@@ -236,7 +282,8 @@
}
}
- class DevicesAdapter extends ArrayAdapter<BluetoothDevice> {
+ class DevicesAdapter extends ArrayAdapter<DeviceFilterPair> {
+ //TODO wifi icon
private Drawable BLUETOOTH_ICON = icon(android.R.drawable.stat_sys_data_bluetooth);
private Drawable icon(int drawableRes) {
@@ -261,8 +308,8 @@
return view;
}
- private void bind(TextView textView, BluetoothDevice device) {
- textView.setText(getDeviceDisplayName(device));
+ private void bind(TextView textView, DeviceFilterPair device) {
+ textView.setText(device.getDisplayName());
textView.setBackgroundColor(
device.equals(mSelectedDevice)
? Color.GRAY
@@ -285,4 +332,62 @@
return textView;
}
}
+
+ /**
+ * A pair of device and a filter that matched this device if any.
+ *
+ * @param <T> device type
+ */
+ static class DeviceFilterPair<T extends Parcelable> {
+ public final T device;
+ @Nullable
+ public final DeviceFilter<T> filter;
+
+ private DeviceFilterPair(T device, @Nullable DeviceFilter<T> filter) {
+ this.device = device;
+ this.filter = filter;
+ }
+
+ /**
+ * {@code (device, null)} if the filters list is empty or null
+ * {@code null} if none of the provided filters match the device
+ * {@code (device, filter)} where filter is among the list of filters and matches the device
+ */
+ @Nullable
+ public static <T extends Parcelable> DeviceFilterPair<T> findMatch(
+ T dev, @Nullable List<? extends DeviceFilter<T>> filters) {
+ if (isEmpty(filters)) return new DeviceFilterPair<>(dev, null);
+ final DeviceFilter<T> matchingFilter = ArrayUtils.find(filters, (f) -> f.matches(dev));
+ return matchingFilter != null ? new DeviceFilterPair<>(dev, matchingFilter) : null;
+ }
+
+ public String getDisplayName() {
+ if (filter == null) {
+ Preconditions.checkNotNull(device);
+ if (device instanceof BluetoothDevice) {
+ return getDeviceDisplayNameInternal((BluetoothDevice) device);
+ } else if (device instanceof android.net.wifi.ScanResult) {
+ return getDeviceDisplayNameInternal((android.net.wifi.ScanResult) device);
+ } else if (device instanceof ScanResult) {
+ return getDeviceDisplayNameInternal(((ScanResult) device).getDevice());
+ } else {
+ throw new IllegalArgumentException("Unknown device type: " + device.getClass());
+ }
+ }
+ return filter.getDeviceDisplayName(device);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ DeviceFilterPair<?> that = (DeviceFilterPair<?>) o;
+ return Objects.equals(getDeviceMacAddress(device), getDeviceMacAddress(that.device));
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getDeviceMacAddress(device));
+ }
+ }
}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 3cc9f65e..8802010 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -19,24 +19,14 @@
import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.Intent;
import android.content.UriPermission;
-import android.content.pm.ParceledListSlice;
-import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.MatrixCursor.RowBuilder;
-import android.graphics.Point;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
-import android.os.CancellationSignal;
import android.os.Environment;
-import android.os.FileObserver;
-import android.os.FileUtils;
-import android.os.Handler;
-import android.os.ParcelFileDescriptor;
-import android.os.ParcelFileDescriptor.OnCloseListener;
import android.os.UserHandle;
import android.os.storage.DiskInfo;
import android.os.storage.StorageManager;
@@ -45,15 +35,12 @@
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Path;
import android.provider.DocumentsContract.Root;
-import android.provider.DocumentsProvider;
-import android.provider.MediaStore;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.DebugUtils;
import android.util.Log;
import android.util.Pair;
-import android.webkit.MimeTypeMap;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.FileSystemProvider;
@@ -62,10 +49,8 @@
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
-import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
-import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
@@ -408,7 +393,7 @@
}
@Override
- public Path findDocumentPath(String childDocId, @Nullable String parentDocId)
+ public Path findDocumentPath(@Nullable String parentDocId, String childDocId)
throws FileNotFoundException {
final Pair<RootInfo, File> resolvedDocId = resolveDocId(childDocId, false);
final RootInfo root = resolvedDocId.first;
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index b8c10a6..e60b5a9 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -435,7 +435,7 @@
}
@Override
- public Path findDocumentPath(String childDocumentId, String parentDocumentId)
+ public Path findDocumentPath(String parentDocumentId, String childDocumentId)
throws FileNotFoundException {
final LinkedList<String> ids = new LinkedList<>();
final Identifier childIdentifier = mDatabase.createIdentifier(childDocumentId);
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index 491e24d..29783e4 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -35,7 +35,6 @@
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
-import java.util.Objects;
import java.util.Queue;
import java.util.concurrent.TimeoutException;
@@ -802,7 +801,7 @@
setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
setupHierarchyDocuments("1");
- final Path path = mProvider.findDocumentPath("15", null);
+ final Path path = mProvider.findDocumentPath(null, "15");
assertEquals("1", path.getRootId());
assertEquals(4, path.getPath().size());
assertEquals("1", path.getPath().get(0));
@@ -816,7 +815,7 @@
setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
setupHierarchyDocuments("1");
- final Path path = mProvider.findDocumentPath("18", "3");
+ final Path path = mProvider.findDocumentPath("3", "18");
assertNull(path.getRootId());
assertEquals(3, path.getPath().size());
assertEquals("3", path.getPath().get(0));
@@ -831,7 +830,7 @@
new MtpRoot(0, 1, "Storage B", 1000, 1000, "") });
setupHierarchyDocuments("2");
- final Path path = mProvider.findDocumentPath("16", null);
+ final Path path = mProvider.findDocumentPath(null, "16");
assertEquals("2", path.getRootId());
assertEquals(4, path.getPath().size());
assertEquals("2", path.getPath().get(0));
@@ -847,7 +846,7 @@
new MtpRoot(0, 1, "Storage B", 1000, 1000, "") });
setupHierarchyDocuments("2");
- final Path path = mProvider.findDocumentPath("19", "4");
+ final Path path = mProvider.findDocumentPath("4", "19");
assertNull(path.getRootId());
assertEquals(3, path.getPath().size());
assertEquals("4", path.getPath().get(0));
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java
index 8cfec7a..594a294 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java
@@ -44,10 +44,9 @@
import android.view.inputmethod.InputMethodInfo;
import com.android.settingslib.BaseTest;
-import org.hamcrest.Description;
-import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.compat.ArgumentMatcher;
import java.util.ArrayList;
import java.util.List;
@@ -249,7 +248,7 @@
}
@Override
- public boolean matches(Object argument) {
+ public boolean matchesObject(Object argument) {
if (argument instanceof Intent) {
return ((Intent) argument).filterEquals(mIntent);
}
@@ -257,8 +256,8 @@
}
@Override
- public void describeTo(Description description) {
- description.appendText("Expected: " + mIntent);
+ public String toString() {
+ return "Expected: " + mIntent;
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 0676efd..1fe3c48 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -976,8 +976,8 @@
Settings.Secure.VOICE_INTERACTION_SERVICE,
SecureSettingsProto.VOICE_INTERACTION_SERVICE);
dumpSetting(s, p,
- Settings.Secure.AUTO_FILL_SERVICE,
- SecureSettingsProto.AUTO_FILL_SERVICE);
+ Settings.Secure.AUTOFILL_SERVICE,
+ SecureSettingsProto.AUTOFILL_SERVICE);
dumpSetting(s, p,
Settings.Secure.BLUETOOTH_HCI_LOG,
SecureSettingsProto.BLUETOOTH_HCI_LOG);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 0916abe..91a4e79 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1578,8 +1578,14 @@
}
private List<String> getSettingsNamesLocked(int settingsType, int userId) {
- ApplicationInfo ai = getCallingApplicationInfoOrThrow(userId);
- if (ai.isInstantApp()) {
+ boolean instantApp;
+ if (UserHandle.getAppId(Binder.getCallingUid()) < Process.FIRST_APPLICATION_UID) {
+ instantApp = false;
+ } else {
+ ApplicationInfo ai = getCallingApplicationInfoOrThrow();
+ instantApp = ai.isInstantApp();
+ }
+ if (instantApp) {
return new ArrayList<String>(getInstantAppAccessibleSettings(settingsType));
} else {
return mSettingsRegistry.getSettingsNamesLocked(settingsType, userId);
@@ -1590,7 +1596,7 @@
if (UserHandle.getAppId(Binder.getCallingUid()) < Process.FIRST_APPLICATION_UID) {
return;
}
- ApplicationInfo ai = getCallingApplicationInfoOrThrow(userId);
+ ApplicationInfo ai = getCallingApplicationInfoOrThrow();
if (!ai.isInstantApp()) {
return;
}
@@ -1600,10 +1606,16 @@
}
}
- private ApplicationInfo getCallingApplicationInfoOrThrow(int userId) {
+ private ApplicationInfo getCallingApplicationInfoOrThrow() {
+ // We always use the callingUid for this lookup. This means that if hypothetically an
+ // app was installed in user A with cross user and in user B as an Instant App
+ // the app in A would be able to see all the settings in user B. However since cross
+ // user is a system permission and the app must be uninstalled in B and then installed as
+ // an Instant App that situation is not realistic or supported.
ApplicationInfo ai = null;
try {
- ai = mPackageManager.getApplicationInfo(getCallingPackage(), 0 , userId);
+ ai = mPackageManager.getApplicationInfo(getCallingPackage(), 0
+ , UserHandle.getCallingUserId());
} catch (RemoteException ignored) {
}
if (ai == null) {
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index b2e2a2c..dcc5501 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -177,6 +177,9 @@
<uses-permission android:name="android.permission.MODIFY_THEME_OVERLAY" />
+ <!-- accessibility -->
+ <uses-permission android:name="android.permission.MODIFY_ACCESSIBILITY_DATA" />
+
<application
android:name=".SystemUIApplication"
android:persistent="true"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
index fc0b568..51adc1e 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
@@ -28,25 +28,42 @@
androidprv:layout_maxWidth="@dimen/keyguard_security_width"
androidprv:layout_maxHeight="@dimen/keyguard_security_height"
android:gravity="center_horizontal|top">
- <LinearLayout
+ <RelativeLayout
android:id="@+id/keyguard_clock_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal|top"
- android:orientation="vertical" >
+ android:layout_gravity="center_horizontal|top">
<TextClock
android:id="@+id/clock_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
+ android:layout_centerHorizontal="true"
+ android:layout_alignParentTop="true"
android:textColor="@color/clock_white"
android:singleLine="true"
style="@style/widget_big_thin"
android:format12Hour="@string/keyguard_widget_12_hours_format"
android:format24Hour="@string/keyguard_widget_24_hours_format"
android:layout_marginBottom="@dimen/bottom_text_spacing_digital" />
+ <com.android.systemui.ChargingView
+ android:id="@+id/battery_doze"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignTop="@id/clock_view"
+ android:layout_alignBottom="@id/clock_view"
+ android:layout_toEndOf="@id/clock_view"
+ android:visibility="invisible"
+ android:src="@drawable/ic_aod_charging_24dp"
+ android:contentDescription="@string/accessibility_ambient_display_charging"
+ />
- <include layout="@layout/keyguard_status_area" />
+ <include layout="@layout/keyguard_status_area"
+ android:id="@+id/keyguard_status_area"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/clock_view" />
+
<TextView
android:id="@+id/owner_info"
android:layout_marginLeft="16dp"
@@ -54,12 +71,13 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/date_owner_info_margin"
- android:layout_gravity="center_horizontal"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@id/keyguard_status_area"
android:textColor="@color/clock_gray"
android:textSize="@dimen/widget_label_font_size"
android:letterSpacing="0.05"
android:ellipsize="marquee"
android:singleLine="true" />
- </LinearLayout>
+ </RelativeLayout>
</com.android.keyguard.KeyguardStatusView>
diff --git a/packages/SystemUI/res/drawable/ic_aod_charging_24dp.xml b/packages/SystemUI/res/drawable/ic_aod_charging_24dp.xml
new file mode 100644
index 0000000..6134b8f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_aod_charging_24dp.xml
@@ -0,0 +1,24 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M11.0,22.98l0.0,-8.98 -4.0,0.0 6.0,-13.0 0.0,9.0 4.0,0.0z"
+ android:fillColor="#ffffff"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/pip_expand_ll.xml b/packages/SystemUI/res/drawable/pip_expand_ll.xml
new file mode 100644
index 0000000..a8b82b5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pip_expand_ll.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="60dp"
+ android:height="60dp"
+ android:viewportWidth="60"
+ android:viewportHeight="60">
+
+ <path
+ android:fillColor="#fff"
+ android:pathData="M7.5,52h45a5,5,0,0,0,5-5V12.95A5,5,0,0,0,52.5,8H7.5a5,5,0,0,0-5,4.95V47A5,5,0,0,0,7.5,52Zm-1-5V13a1,1,0,0,1,1-1h45a1,1,0,0,1,1,1V47a1,1,0,0,1-1,1H7.5A1,1,0,0,1,6.5,47Z" />
+ <path
+ android:pathData="M0,0V60H60V0H0Z" />
+ <path
+ android:fillColor="#fff"
+ android:pathData="M35,39.14v2a1,1,0,0,0,1,1H46.5a1,1,0,0,0,1-1V30.64a1,1,0,0,0-1-1h-2a1,1,0,0,0-1,1v7.5H36A1,1,0,0,0,35,39.14Z" />
+ <path
+ android:fillColor="#fff"
+ android:pathData="M13.5,30.36h2a1,1,0,0,0,1-1v-7.5H24a1,1,0,0,0,1-1v-2a1,1,0,0,0-1-1H13.5a1,1,0,0,0-1,1v10.5A1,1,0,0,0,13.5,30.36Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pip_expand_lr.xml b/packages/SystemUI/res/drawable/pip_expand_lr.xml
new file mode 100644
index 0000000..44d97ef
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pip_expand_lr.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="60dp"
+ android:height="60dp"
+ android:viewportWidth="60"
+ android:viewportHeight="60">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M57.5,47V12.95c0-2.75-2.25-4.95-5-4.95h-45c-2.75,0-5,2.2-5,4.95V47c0,2.75,2.25,5,5,5h45
+C55.25,52,57.5,49.75,57.5,47z
+M52.5,48h-45c-0.55,0-1-0.45-1-1V13c0-0.55,0.45-1,1-1h45c0.55,0,1,0.45,1,1v34
+C53.5,47.55,53.05,48,52.5,48z" />
+ <path
+ android:pathData="M60,0v60H0L0,0L60,0z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M25,39.14v2c0,0.55-0.45,1-1,1H13.5c-0.55,0-1-0.45-1-1v-10.5c0-0.55,0.45-1,1-1h2c0.55,0,1,0.45,1,1v7.5
+H24C24.55,38.14,25,38.59,25,39.14z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M46.5,30.36h-2c-0.55,0-1-0.45-1-1v-7.5H36c-0.55,0-1-0.45-1-1v-2c0-0.55,0.45-1,1-1h10.5
+c0.55,0,1,0.45,1,1v10.5C47.5,29.91,47.05,30.36,46.5,30.36z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pip_expand_pl.xml b/packages/SystemUI/res/drawable/pip_expand_pl.xml
new file mode 100644
index 0000000..57b9358
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pip_expand_pl.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="60dp"
+ android:height="60dp"
+ android:viewportWidth="60"
+ android:viewportHeight="60">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M47,2.5H12.95C10.2,2.5,8,4.75,8,7.5v45c0,2.75,2.2,5,4.95,5H47c2.75,0,5-2.25,5-5v-45
+C52,4.75,49.75,2.5,47,2.5z
+M48,7.5v45c0,0.55-0.45,1-1,1H13c-0.55,0-1-0.45-1-1v-45c0-0.55,0.45-1,1-1h34
+C47.55,6.5,48,6.95,48,7.5z" />
+ <path
+ android:pathData="M0,0l60,0v60H0L0,0z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M39.14,35h2c0.55,0,1,0.45,1,1v10.5c0,0.55-0.45,1-1,1h-10.5c-0.55,0-1-0.45-1-1v-2c0-0.55,0.45-1,1-1h7.5
+V36C38.14,35.45,38.59,35,39.14,35z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M30.36,13.5v2c0,0.55-0.45,1-1,1h-7.5V24c0,0.55-0.45,1-1,1h-2c-0.55,0-1-0.45-1-1V13.5c0-0.55,0.45-1,1-1
+h10.5C29.91,12.5,30.36,12.95,30.36,13.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pip_expand.xml b/packages/SystemUI/res/drawable/pip_expand_pr.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/pip_expand.xml
rename to packages/SystemUI/res/drawable/pip_expand_pr.xml
diff --git a/packages/SystemUI/res/layout/pip_menu_action.xml b/packages/SystemUI/res/layout/pip_menu_action.xml
index 9b954f7..77efc9b 100644
--- a/packages/SystemUI/res/layout/pip_menu_action.xml
+++ b/packages/SystemUI/res/layout/pip_menu_action.xml
@@ -15,7 +15,7 @@
-->
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:padding="10dp"
+ 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
diff --git a/packages/SystemUI/res/layout/pip_menu_activity.xml b/packages/SystemUI/res/layout/pip_menu_activity.xml
index f38c8ff..5e49d05 100644
--- a/packages/SystemUI/res/layout/pip_menu_activity.xml
+++ b/packages/SystemUI/res/layout/pip_menu_activity.xml
@@ -18,38 +18,39 @@
android:id="@+id/menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="#00000000">
+ android:background="#4D000000">
<!-- The above background is only for the dismiss button ripple to show. -->
<ImageView
android:id="@+id/dismiss"
- android:layout_width="48dp"
- android:layout_height="48dp"
+ android:layout_width="@dimen/pip_action_size"
+ android:layout_height="@dimen/pip_action_size"
android:layout_gravity="top|end"
- android:padding="10dp"
+ android:padding="@dimen/pip_action_padding"
android:contentDescription="@string/pip_phone_close"
android:src="@drawable/ic_close_white"
android:background="?android:selectableItemBackgroundBorderless" />
+ <!-- The margins for this container is calculated in the code depending on whether the
+ actions_container is visible. -->
<FrameLayout
android:id="@+id/expand_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
- android:layout_width="64dp"
- android:layout_height="64dp"
+ android:id="@+id/expand_button"
+ android:layout_width="60dp"
+ android:layout_height="60dp"
android:layout_gravity="center"
android:contentDescription="@string/pip_phone_expand"
- android:src="@drawable/pip_expand"
android:background="?android:selectableItemBackgroundBorderless" />
</FrameLayout>
<FrameLayout
android:id="@+id/actions_container"
android:layout_width="match_parent"
- android:layout_height="48dp"
+ android:layout_height="@dimen/pip_action_size"
android:layout_gravity="bottom"
- android:background="#66000000"
android:visibility="invisible">
<LinearLayout
android:id="@+id/actions_group"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index f331d87..ffaa7ba 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -738,6 +738,16 @@
the configuration of the device, so we can't use -land resources. -->
<dimen name="pip_between_action_padding_land">8dp</dimen>
+ <!-- The height of the PiP actions container in which the actions are vertically centered. -->
+ <dimen name="pip_action_size">48dp</dimen>
+
+ <!-- The padding around a PiP actions. -->
+ <dimen name="pip_action_padding">12dp</dimen>
+
+ <!-- The bottom margin of the expand container when there are actions.
+ Equal to pip_action_size - pip_action_padding. -->
+ <dimen name="pip_expand_container_edge_margin">36dp</dimen>
+
<dimen name="default_gear_space">18dp</dimen>
<dimen name="cell_overlay_padding">18dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 93ae763..1541649 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -565,6 +565,9 @@
<!-- Content description of the display brightness slider (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_brightness">Display brightness</string>
+ <!-- Content description of the charging indicator on Ambient Display (lower-power version of the lock screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_ambient_display_charging">Charging</string>
+
<!-- Title of dialog shown when 2G-3G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
<string name="data_usage_disabled_dialog_3g_title">2G-3G data is paused</string>
<!-- Title of dialog shown when 4G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
@@ -1815,6 +1818,9 @@
<!-- App label of the instant apps notification [CHAR LIMIT=60] -->
<string name="instant_apps">Instant Apps</string>
+ <!-- Title of menu shown over picture-in-picture. Used for accessibility. -->
+ <string name="pip_menu_title">Picture in picture menu</string>
+
<!-- Message of the instant apps notification indicating they don't need install [CHAR LIMIT=NONE] -->
<string name="instant_apps_message">Instant apps don\'t require installation.</string>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index f8f4f2a..2655837 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -35,6 +35,7 @@
import android.widget.TextView;
import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.ChargingView;
import java.util.Locale;
@@ -50,6 +51,7 @@
private TextClock mClockView;
private TextView mOwnerInfo;
private ViewGroup mClockContainer;
+ private ChargingView mBatteryDoze;
private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
@@ -114,6 +116,7 @@
mDateView.setShowCurrentUserTime(true);
mClockView.setShowCurrentUserTime(true);
mOwnerInfo = (TextView) findViewById(R.id.owner_info);
+ mBatteryDoze = (ChargingView) findViewById(R.id.battery_doze);
boolean shouldMarquee = KeyguardUpdateMonitor.getInstance(mContext).isDeviceInteractive();
setEnableMarquee(shouldMarquee);
@@ -273,10 +276,11 @@
final int N = mClockContainer.getChildCount();
for (int i = 0; i < N; i++) {
View child = mClockContainer.getChildAt(i);
- if (child == mClockView) {
+ if (child == mClockView || child == mBatteryDoze) {
continue;
}
child.setAlpha(dark ? 0 : 1);
}
+ mBatteryDoze.setDark(dark);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ChargingView.java b/packages/SystemUI/src/com/android/systemui/ChargingView.java
new file mode 100644
index 0000000..555cc74
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ChargingView.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+
+/**
+ * A view that only shows its drawable while the phone is charging.
+ *
+ * Also reloads its drawable upon density changes.
+ */
+public class ChargingView extends ImageView implements
+ BatteryController.BatteryStateChangeCallback,
+ ConfigurationController.ConfigurationListener {
+
+ private BatteryController mBatteryController;
+ private int mImageResource;
+ private boolean mCharging;
+ private boolean mDark;
+
+ public ChargingView(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.src});
+ int srcResId = a.getResourceId(0, 0);
+
+ if (srcResId != 0) {
+ mImageResource = srcResId;
+ }
+
+ a.recycle();
+
+ updateVisibility();
+ }
+
+ @Override
+ public void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mBatteryController = Dependency.get(BatteryController.class);
+ mBatteryController.addCallback(this);
+ Dependency.get(ConfigurationController.class).addCallback(this);
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mBatteryController.removeCallback(this);
+ Dependency.get(ConfigurationController.class).removeCallback(this);
+ }
+
+ @Override
+ public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+ mCharging = charging;
+ updateVisibility();
+ }
+
+ @Override
+ public void onDensityOrFontScaleChanged() {
+ setImageResource(mImageResource);
+ }
+
+ public void setDark(boolean dark) {
+ mDark = dark;
+ updateVisibility();
+ }
+
+ private void updateVisibility() {
+ setVisibility(mCharging && mDark ? VISIBLE : INVISIBLE);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 5d57daa..ba8e54a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -22,12 +22,12 @@
import android.content.Context;
import android.hardware.SensorManager;
import android.os.Handler;
-import android.os.PowerManager;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.systemui.SystemUIApplication;
import com.android.systemui.plugins.doze.DozeProvider;
import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.util.wakelock.WakeLock;
public class DozeFactory {
@@ -41,19 +41,17 @@
public DozeMachine assembleMachine(DozeService dozeService) {
Context context = dozeService;
SensorManager sensorManager = context.getSystemService(SensorManager.class);
- PowerManager powerManager = context.getSystemService(PowerManager.class);
AlarmManager alarmManager = context.getSystemService(AlarmManager.class);
DozeHost host = getHost(dozeService);
AmbientDisplayConfiguration config = new AmbientDisplayConfiguration(context);
DozeParameters params = new DozeParameters(context);
Handler handler = new Handler();
- DozeFactory.WakeLock wakeLock = new DozeFactory.WakeLock(powerManager.newWakeLock(
- PowerManager.PARTIAL_WAKE_LOCK, "Doze"));
+ WakeLock wakeLock = WakeLock.createPartial(context, "Doze");
DozeMachine machine = new DozeMachine(
DozeScreenStatePreventingAdapter.wrapIfNeeded(dozeService, params),
- params,
+ config,
wakeLock);
machine.setParts(new DozeMachine.Part[]{
createDozeTriggers(context, sensorManager, host, config, params, handler, wakeLock,
@@ -157,28 +155,4 @@
final SystemUIApplication app = (SystemUIApplication) appCandidate;
return app.getComponent(DozeHost.class);
}
-
- /** A wrapper around {@link PowerManager.WakeLock} for testability. */
- public static class WakeLock implements DozeProvider.WakeLock {
- private final PowerManager.WakeLock mInner;
-
- public WakeLock(PowerManager.WakeLock inner) {
- mInner = inner;
- }
-
- /** @see PowerManager.WakeLock#acquire() */
- public void acquire() {
- mInner.acquire();
- }
-
- /** @see PowerManager.WakeLock#release() */
- public void release() {
- mInner.release();
- }
-
- /** @see PowerManager.WakeLock#wrap(Runnable) */
- public Runnable wrap(Runnable runnable) {
- return mInner.wrap(runnable);
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index c9eb790..f27521e 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -17,12 +17,14 @@
package com.android.systemui.doze;
import android.annotation.MainThread;
+import android.os.UserHandle;
import android.util.Log;
import android.view.Display;
+import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.internal.util.Preconditions;
-import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.Assert;
+import com.android.systemui.util.wakelock.WakeLock;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -94,17 +96,18 @@
}
private final Service mDozeService;
- private final DozeFactory.WakeLock mWakeLock;
- private final DozeParameters mParams;
+ private final WakeLock mWakeLock;
+ private final AmbientDisplayConfiguration mConfig;
private Part[] mParts;
private final ArrayList<State> mQueuedRequests = new ArrayList<>();
private State mState = State.UNINITIALIZED;
private boolean mWakeLockHeldForCurrentState = false;
- public DozeMachine(Service service, DozeParameters params, DozeFactory.WakeLock wakeLock) {
+ public DozeMachine(Service service, AmbientDisplayConfiguration config,
+ WakeLock wakeLock) {
mDozeService = service;
- mParams = params;
+ mConfig = config;
mWakeLock = wakeLock;
}
@@ -267,7 +270,7 @@
switch (state) {
case INITIALIZED:
case DOZE_PULSE_DONE:
- transitionTo(mParams.getAlwaysOn()
+ transitionTo(mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT)
? DozeMachine.State.DOZE_AOD : DozeMachine.State.DOZE);
break;
default:
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 9cc927d..2ac0657 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -36,6 +36,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.util.wakelock.WakeLock;
import java.io.PrintWriter;
import java.util.List;
@@ -53,14 +54,14 @@
private final TriggerSensor mPickupSensor;
private final DozeParameters mDozeParameters;
private final AmbientDisplayConfiguration mConfig;
- private final DozeFactory.WakeLock mWakeLock;
+ private final WakeLock mWakeLock;
private final Callback mCallback;
private final Handler mHandler = new Handler();
public DozeSensors(Context context, SensorManager sensorManager, DozeParameters dozeParameters,
- AmbientDisplayConfiguration config, DozeFactory.WakeLock wakeLock, Callback callback) {
+ AmbientDisplayConfiguration config, WakeLock wakeLock, Callback callback) {
mContext = context;
mSensorManager = sensorManager;
mDozeParameters = dozeParameters;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index b5c7dd3..1b9bf73 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -36,6 +36,7 @@
import com.android.internal.util.Preconditions;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.Assert;
+import com.android.systemui.util.wakelock.WakeLock;
import java.io.PrintWriter;
@@ -57,7 +58,7 @@
private final DozeParameters mDozeParameters;
private final SensorManager mSensorManager;
private final Handler mHandler;
- private final DozeFactory.WakeLock mWakeLock;
+ private final WakeLock mWakeLock;
private final boolean mAllowPulseTriggers;
private final UiModeManager mUiModeManager;
private final TriggerReceiver mBroadcastReceiver = new TriggerReceiver();
@@ -69,7 +70,7 @@
public DozeTriggers(Context context, DozeMachine machine, DozeHost dozeHost,
AmbientDisplayConfiguration config,
DozeParameters dozeParameters, SensorManager sensorManager, Handler handler,
- DozeFactory.WakeLock wakeLock, boolean allowPulseTriggers) {
+ WakeLock wakeLock, boolean allowPulseTriggers) {
mContext = context;
mMachine = machine;
mDozeHost = dozeHost;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 76e0283..f577654 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -21,6 +21,8 @@
import android.os.Handler;
import android.os.SystemClock;
+import com.android.systemui.util.wakelock.WakeLock;
+
import java.util.Calendar;
import java.util.GregorianCalendar;
@@ -33,14 +35,14 @@
private final AlarmManager mAlarmManager;
private final DozeHost mHost;
private final Handler mHandler;
- private final DozeFactory.WakeLock mWakeLock;
+ private final WakeLock mWakeLock;
private final DozeMachine mMachine;
private final AlarmManager.OnAlarmListener mTimeTick;
private boolean mTimeTickScheduled = false;
public DozeUi(Context context, AlarmManager alarmManager, DozeMachine machine,
- DozeFactory.WakeLock wakeLock, DozeHost host, Handler handler) {
+ WakeLock wakeLock, DozeHost host, Handler handler) {
mContext = context;
mAlarmManager = alarmManager;
mMachine = machine;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/InputConsumerController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/InputConsumerController.java
index 7a1849e..762d6bc 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/InputConsumerController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/InputConsumerController.java
@@ -44,6 +44,14 @@
}
/**
+ * Listener interface for callers to learn when this class is registered or unregistered with
+ * window manager
+ */
+ public interface RegistrationListener {
+ void onRegistrationChanged(boolean isRegistered);
+ }
+
+ /**
* Input handler used for the PiP input consumer.
*/
private final class PipInputEventReceiver extends InputEventReceiver {
@@ -71,6 +79,7 @@
private PipInputEventReceiver mInputEventReceiver;
private TouchListener mListener;
+ private RegistrationListener mRegistrationListener;
public InputConsumerController(IWindowManager windowManager) {
mWindowManager = windowManager;
@@ -85,6 +94,22 @@
}
/**
+ * Sets the registration listener.
+ */
+ public void setRegistrationListener(RegistrationListener listener) {
+ mRegistrationListener = listener;
+ }
+
+ /**
+ * Check if the InputConsumer is currently registered with WindowManager
+ *
+ * @return {@code true} if registered, {@code false} if not.
+ */
+ public boolean isRegistered() {
+ return mInputEventReceiver != null;
+ }
+
+ /**
* Registers the input consumer.
*/
public void registerInputConsumer() {
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 65de22e..86e2c49 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -16,6 +16,11 @@
package com.android.systemui.pip.phone;
+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 android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
@@ -26,20 +31,25 @@
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.Icon;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
+import android.util.Pair;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager.LayoutParams;
+import android.view.accessibility.AccessibilityManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -71,6 +81,7 @@
private View mMenuContainer;
private LinearLayout mActionsGroup;
private View mDismissButton;
+ private ImageView mExpandButton;
private int mBetweenActionPaddingLand;
private ObjectAnimator mMenuContainerAnimator;
@@ -85,7 +96,8 @@
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_SHOW_MENU:
- showMenu();
+ Pair<Rect, Rect> bounds = (Pair<Rect, Rect>) msg.obj;
+ showMenu(bounds.first, bounds.second);
break;
case MESSAGE_POKE_MENU:
cancelDelayedFinish();
@@ -94,7 +106,8 @@
hideMenu();
break;
case MESSAGE_UPDATE_ACTIONS:
- setActions(((ParceledListSlice) msg.obj).getList());
+ Pair<Rect, ParceledListSlice> data = (Pair<Rect, ParceledListSlice>) msg.obj;
+ setActions(data.first, data.second.getList());
break;
}
}
@@ -117,15 +130,6 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.pip_menu_activity);
- Intent startingIntent = getIntent();
- mToControllerMessenger = startingIntent.getParcelableExtra(
- PipMenuActivityController.EXTRA_CONTROLLER_MESSENGER);
- ParceledListSlice actions = startingIntent.getParcelableExtra(
- PipMenuActivityController.EXTRA_ACTIONS);
- if (actions != null) {
- setActions(actions.getList());
- }
-
mMenuContainer = findViewById(R.id.menu);
mMenuContainer.setOnClickListener((v) -> {
expandPip();
@@ -137,15 +141,17 @@
mActionsGroup = (LinearLayout) findViewById(R.id.actions_group);
mBetweenActionPaddingLand = getResources().getDimensionPixelSize(
R.dimen.pip_between_action_padding_land);
+ mExpandButton = (ImageView) findViewById(R.id.expand_button);
+ updateFromIntent(getIntent());
+ setTitle(R.string.pip_menu_title);
notifyActivityCallback(mMessenger);
- showMenu();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
- showMenu();
+ updateFromIntent(intent);
}
@Override
@@ -214,13 +220,14 @@
// Do nothing
}
- private void showMenu() {
+ private void showMenu(Rect stackBounds, Rect movementBounds) {
if (!mMenuVisible) {
if (mMenuContainerAnimator != null) {
mMenuContainerAnimator.cancel();
}
notifyMenuVisibility(true);
+ updateExpandButtonFromBounds(stackBounds, movementBounds);
mMenuContainerAnimator = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
mMenuContainer.getAlpha(), 1f);
mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_IN);
@@ -257,19 +264,52 @@
if (animationFinishedRunnable != null) {
animationFinishedRunnable.run();
}
+ if (getSystemService(AccessibilityManager.class).isEnabled()) {
+ finish();
+ }
}
});
mMenuContainerAnimator.start();
}
}
- private void setActions(List<RemoteAction> actions) {
- mActions.clear();
- mActions.addAll(actions);
- updateActionViews();
+ private void updateFromIntent(Intent intent) {
+ Rect stackBounds = Rect.unflattenFromString(intent.getStringExtra(EXTRA_STACK_BOUNDS));
+ Rect movementBounds = Rect.unflattenFromString(intent.getStringExtra(
+ EXTRA_MOVEMENT_BOUNDS));
+ mToControllerMessenger = intent.getParcelableExtra(EXTRA_CONTROLLER_MESSENGER);
+ ParceledListSlice actions = intent.getParcelableExtra(EXTRA_ACTIONS);
+ if (actions != null) {
+ setActions(stackBounds, actions.getList());
+ }
+ showMenu(stackBounds, movementBounds);
}
- private void updateActionViews() {
+ private void updateExpandButtonFromBounds(Rect stackBounds, Rect movementBounds) {
+ if (stackBounds == null) {
+ return;
+ }
+
+ boolean isLandscapePip = stackBounds.width() > stackBounds.height();
+ boolean left = stackBounds.left < movementBounds.centerX();
+ boolean top = stackBounds.top < movementBounds.centerY();
+ boolean expandL = (left && top) || (!left && !top);
+ int iconResId;
+ if (isLandscapePip) {
+ iconResId = expandL ? R.drawable.pip_expand_ll : R.drawable.pip_expand_lr;
+ } else {
+ iconResId = expandL ? R.drawable.pip_expand_pl : R.drawable.pip_expand_pr;
+ }
+ mExpandButton.setImageResource(iconResId);
+ }
+
+ private void setActions(Rect stackBounds, List<RemoteAction> actions) {
+ mActions.clear();
+ mActions.addAll(actions);
+ updateActionViews(stackBounds);
+ }
+
+ private void updateActionViews(Rect stackBounds) {
ViewGroup expandContainer = (ViewGroup) findViewById(R.id.expand_container);
ViewGroup actionsContainer = (ViewGroup) findViewById(R.id.actions_container);
actionsContainer.setOnTouchListener((v, ev) -> {
@@ -277,7 +317,6 @@
return true;
});
- int actionsContainerHeight = 0;
if (mActions.isEmpty()) {
actionsContainer.setVisibility(View.INVISIBLE);
} else {
@@ -286,9 +325,8 @@
mActionsGroup.removeAllViews();
// Recreate the layout
- final View decorView = getWindow().getDecorView();
- final boolean isLandscapePip = decorView.getMeasuredWidth()
- > decorView.getMeasuredHeight();
+ final boolean isLandscapePip = stackBounds != null &&
+ (stackBounds.width() > stackBounds.height());
final LayoutInflater inflater = LayoutInflater.from(this);
for (int i = 0; i < mActions.size(); i++) {
final RemoteAction action = mActions.get(i);
@@ -314,13 +352,17 @@
mActionsGroup.addView(actionView);
}
}
- actionsContainerHeight = actionsContainer.getLayoutParams().height;
- }
- // Update the expand container margin to account for the existence of the action container
- ((FrameLayout.LayoutParams) expandContainer.getLayoutParams()).bottomMargin =
- actionsContainerHeight;
- expandContainer.requestLayout();
+ // Update the expand container margin to adjust the center of the expand button to
+ // account for the existence of the action container
+ FrameLayout.LayoutParams expandedLp =
+ (FrameLayout.LayoutParams) expandContainer.getLayoutParams();
+ expandedLp.topMargin = getResources().getDimensionPixelSize(
+ R.dimen.pip_action_padding);
+ expandedLp.bottomMargin = getResources().getDimensionPixelSize(
+ R.dimen.pip_expand_container_edge_margin);
+ expandContainer.requestLayout();
+ }
}
private void notifyRegisterInputConsumer() {
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 0b1c3ec..badf64b 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -25,12 +25,14 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
+import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
+import android.util.Pair;
import android.view.IWindowManager;
import com.android.systemui.pip.phone.PipMediaController.ActionListener;
@@ -51,6 +53,8 @@
public static final String EXTRA_CONTROLLER_MESSENGER = "messenger";
public static final String EXTRA_ACTIONS = "actions";
+ public static final String EXTRA_STACK_BOUNDS = "stack_bounds";
+ public static final String EXTRA_MOVEMENT_BOUNDS = "movement_bounds";
public static final int MESSAGE_MENU_VISIBILITY_CHANGED = 100;
public static final int MESSAGE_EXPAND_PIP = 101;
@@ -177,10 +181,11 @@
/**
* Shows the menu activity.
*/
- public void showMenu() {
+ public void showMenu(Rect stackBounds, Rect movementBounds) {
if (mToActivityMessenger != null) {
Message m = Message.obtain();
m.what = PipMenuActivity.MESSAGE_SHOW_MENU;
+ m.obj = new Pair<>(stackBounds, movementBounds);
try {
mToActivityMessenger.send(m);
} catch (RemoteException e) {
@@ -195,6 +200,8 @@
Intent intent = new Intent(mContext, PipMenuActivity.class);
intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger);
intent.putExtra(EXTRA_ACTIONS, resolveMenuActions());
+ intent.putExtra(EXTRA_STACK_BOUNDS, stackBounds.flattenToString());
+ intent.putExtra(EXTRA_MOVEMENT_BOUNDS, movementBounds.flattenToString());
ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
options.setLaunchTaskId(
pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]);
@@ -269,9 +276,20 @@
*/
private void updateMenuActions() {
if (mToActivityMessenger != null) {
+ // Fetch the pinned stack bounds
+ Rect stackBounds = null;
+ try {
+ StackInfo pinnedStackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
+ if (pinnedStackInfo != null) {
+ stackBounds = pinnedStackInfo.bounds;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error showing PIP menu activity", e);
+ }
+
Message m = Message.obtain();
m.what = PipMenuActivity.MESSAGE_UPDATE_ACTIONS;
- m.obj = resolveMenuActions();
+ m.obj = new Pair<>(stackBounds, resolveMenuActions());
try {
mToActivityMessenger.send(m);
} catch (RemoteException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index 20c1136..49d89a2 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -56,7 +56,8 @@
private static final int DEFAULT_MOVE_STACK_DURATION = 225;
private static final int SNAP_STACK_DURATION = 225;
- private static final int DISMISS_STACK_DURATION = 375;
+ private static final int DRAG_TO_TARGET_DISMISS_STACK_DURATION = 375;
+ private static final int DRAG_TO_DISMISS_STACK_DURATION = 175;
private static final int SHRINK_STACK_FROM_MENU_DURATION = 250;
private static final int EXPAND_STACK_TO_MENU_DURATION = 250;
private static final int EXPAND_STACK_TO_FULLSCREEN_DURATION = 300;
@@ -65,6 +66,8 @@
// The fraction of the stack width that the user has to drag offscreen to minimize the PiP
private static final float MINIMIZE_OFFSCREEN_FRACTION = 0.2f;
+ // The fraction of the stack height that the user has to drag offscreen to minimize the PiP
+ private static final float DISMISS_OFFSCREEN_FRACTION = 0.35f;
private Context mContext;
private IActivityManager mActivityManager;
@@ -194,6 +197,19 @@
}
/**
+ * @return whether the PiP at the current bounds should be dismissed.
+ */
+ boolean shouldDismissPip() {
+ Point displaySize = new Point();
+ mContext.getDisplay().getRealSize(displaySize);
+ if (mBounds.bottom > displaySize.y) {
+ float offscreenFraction = (float) (mBounds.bottom - displaySize.y) / mBounds.height();
+ return offscreenFraction >= DISMISS_OFFSCREEN_FRACTION;
+ }
+ return false;
+ }
+
+ /**
* Flings the minimized PiP to the closest minimized snap target.
*/
Rect flingToMinimizedState(float velocityY, Rect movementBounds) {
@@ -298,15 +314,37 @@
}
/**
+ * Animates the dismissal of the PiP off the edge of the screen.
+ */
+ Rect animateDragToEdgeDismiss(Rect pipBounds) {
+ cancelAnimations();
+ Point displaySize = new Point();
+ mContext.getDisplay().getRealSize(displaySize);
+ Rect toBounds = new Rect(pipBounds);
+ toBounds.offset(0, displaySize.y - pipBounds.top);
+ mBoundsAnimator = createAnimationToBounds(mBounds, toBounds, DRAG_TO_DISMISS_STACK_DURATION,
+ FAST_OUT_LINEAR_IN, mUpdateBoundsListener);
+ mBoundsAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ dismissPip();
+ }
+ });
+ mBoundsAnimator.start();
+ return toBounds;
+ }
+
+ /**
* Animates the dismissal of the PiP over the dismiss target bounds.
*/
- Rect animateDismissFromDrag(Rect dismissBounds) {
+ Rect animateDragToTargetDismiss(Rect dismissBounds) {
cancelAnimations();
Rect toBounds = new Rect(dismissBounds.centerX(),
dismissBounds.centerY(),
dismissBounds.centerX() + 1,
dismissBounds.centerY() + 1);
- mBoundsAnimator = createAnimationToBounds(mBounds, toBounds, DISMISS_STACK_DURATION,
+ mBoundsAnimator = createAnimationToBounds(mBounds, toBounds,
+ DRAG_TO_TARGET_DISMISS_STACK_DURATION,
FAST_OUT_LINEAR_IN, mUpdateBoundsListener);
mBoundsAnimator.addListener(new AnimatorListenerAdapter() {
@Override
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 010522d..17c3448 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -21,14 +21,22 @@
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
+import android.graphics.Region;
+import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
import android.util.Size;
import android.view.IPinnedStackController;
-import android.view.IWindowManager;
+import android.view.MagnificationSpec;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityWindowInfo;
+import android.view.accessibility.IAccessibilityInteractionConnection;
+import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -37,6 +45,8 @@
import com.android.systemui.statusbar.FlingAnimationUtils;
import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
/**
* Manages all the touch handling for PIP on the Phone, including moving, dismissing and expanding
@@ -52,7 +62,8 @@
private static final int SHOW_DISMISS_AFFORDANCE_DELAY = 200;
// Allow dragging the PIP to a location to close it
- private static final boolean ENABLE_DRAG_TO_DISMISS = false;
+ private static final boolean ENABLE_DISMISS_DRAG_TO_TARGET = false;
+ private static final boolean ENABLE_DISMISS_DRAG_TO_EDGE = false;
private final Context mContext;
private final IActivityManager mActivityManager;
@@ -63,6 +74,7 @@
private final PipMenuActivityController mMenuController;
private final PipDismissViewController mDismissViewController;
private final PipSnapAlgorithm mSnapAlgorithm;
+ private final AccessibilityManager mAccessibilityManager;
// The current movement bounds
private Rect mMovementBounds = new Rect();
@@ -78,18 +90,26 @@
private Runnable mShowDismissAffordance = new Runnable() {
@Override
public void run() {
- if (ENABLE_DRAG_TO_DISMISS) {
+ if (ENABLE_DISMISS_DRAG_TO_TARGET) {
mDismissViewController.showDismissTarget(mMotionHelper.getBounds());
}
}
};
+ private Runnable mShowMenuRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mMenuController.showMenu(mMotionHelper.getBounds(), mMovementBounds);
+ }
+ };
+
// Behaviour states
private boolean mIsMenuVisible;
private boolean mIsMinimized;
private boolean mIsImeShowing;
private int mImeHeight;
private float mSavedSnapFraction = -1f;
+ private boolean mSendingHoverAccessibilityEvents;
// Touch state
private final PipTouchState mTouchState;
@@ -137,6 +157,7 @@
// Initialize the Pip input consumer
mContext = context;
mActivityManager = activityManager;
+ mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
mViewConfig = ViewConfiguration.get(context);
mMenuController = menuController;
mMenuController.addListener(mMenuListener);
@@ -154,6 +175,8 @@
// Register the listener for input consumer touch events
inputConsumerController.setTouchListener(this::handleTouchEvent);
+ inputConsumerController.setRegistrationListener(this::onRegistrationChanged);
+ onRegistrationChanged(inputConsumerController.isRegistered());
}
public void setTouchEnabled(boolean enabled) {
@@ -238,6 +261,11 @@
updateMovementBounds(mIsMenuVisible);
}
+ private void onRegistrationChanged(boolean isRegistered) {
+ mAccessibilityManager.setPictureInPictureActionReplacingConnection(isRegistered
+ ? new AccessibilityInteractionConnection() : null);
+ }
+
private boolean handleTouchEvent(MotionEvent ev) {
// Skip touch handling until we are bound to the controller
if (mPinnedStackController == null) {
@@ -281,6 +309,31 @@
mTouchState.reset();
break;
}
+ case MotionEvent.ACTION_HOVER_ENTER:
+ case MotionEvent.ACTION_HOVER_MOVE: {
+ if (!mSendingHoverAccessibilityEvents) {
+ AccessibilityEvent event = AccessibilityEvent.obtain(
+ AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
+ AccessibilityNodeInfo info = obtainRootAccessibilityNodeInfo();
+ event.setSource(info);
+ info.recycle();
+ mAccessibilityManager.sendAccessibilityEvent(event);
+ mSendingHoverAccessibilityEvents = true;
+ }
+ break;
+ }
+ case MotionEvent.ACTION_HOVER_EXIT: {
+ if (mSendingHoverAccessibilityEvents) {
+ AccessibilityEvent event = AccessibilityEvent.obtain(
+ AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
+ AccessibilityNodeInfo info = obtainRootAccessibilityNodeInfo();
+ event.setSource(info);
+ info.recycle();
+ mAccessibilityManager.sendAccessibilityEvent(event);
+ mSendingHoverAccessibilityEvents = false;
+ }
+ break;
+ }
}
return !mIsMenuVisible;
}
@@ -378,7 +431,7 @@
mMenuController.pokeMenu();
}
- if (ENABLE_DRAG_TO_DISMISS) {
+ if (ENABLE_DISMISS_DRAG_TO_TARGET) {
mDismissViewController.createDismissTarget();
mHandler.postDelayed(mShowDismissAffordance, SHOW_DISMISS_AFFORDANCE_DELAY);
}
@@ -394,7 +447,7 @@
mSavedSnapFraction = -1f;
}
- if (touchState.startedDragging() && ENABLE_DRAG_TO_DISMISS) {
+ if (touchState.startedDragging() && ENABLE_DISMISS_DRAG_TO_TARGET) {
mHandler.removeCallbacks(mShowDismissAffordance);
mDismissViewController.showDismissTarget(mMotionHelper.getBounds());
}
@@ -408,11 +461,16 @@
if (!touchState.allowDraggingOffscreen()) {
left = Math.max(mMovementBounds.left, Math.min(mMovementBounds.right, left));
}
- top = Math.max(mMovementBounds.top, Math.min(mMovementBounds.bottom, top));
+ if (ENABLE_DISMISS_DRAG_TO_EDGE) {
+ // Allow pip to move past bottom bounds
+ top = Math.max(mMovementBounds.top, top);
+ } else {
+ top = Math.max(mMovementBounds.top, Math.min(mMovementBounds.bottom, top));
+ }
mTmpBounds.offsetTo((int) left, (int) top);
mMotionHelper.movePip(mTmpBounds);
- if (ENABLE_DRAG_TO_DISMISS) {
+ if (ENABLE_DISMISS_DRAG_TO_TARGET) {
mDismissViewController.updateDismissTarget(mTmpBounds);
}
return true;
@@ -427,7 +485,7 @@
}
try {
- if (ENABLE_DRAG_TO_DISMISS) {
+ if (ENABLE_DISMISS_DRAG_TO_TARGET) {
mHandler.removeCallbacks(mShowDismissAffordance);
PointF vel = mTouchState.getVelocity();
final float velocity = PointF.length(vel.x, vel.y);
@@ -435,7 +493,7 @@
&& velocity < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
if (mDismissViewController.shouldDismiss(mMotionHelper.getBounds())) {
Rect dismissBounds = mDismissViewController.getDismissBounds();
- mMotionHelper.animateDismissFromDrag(dismissBounds);
+ mMotionHelper.animateDragToTargetDismiss(dismissBounds);
MetricsLogger.action(mContext,
MetricsEvent.ACTION_PICTURE_IN_PICTURE_DISMISSED,
METRIC_VALUE_DISMISSED_BY_DRAG);
@@ -448,9 +506,17 @@
}
if (touchState.isDragging()) {
- PointF vel = mTouchState.getVelocity();
- if (!mIsMinimized && (mMotionHelper.shouldMinimizePip()
- || isHorizontalFlingTowardsCurrentEdge(vel))) {
+ final boolean onLeft = mMotionHelper.getBounds().left < mMovementBounds.centerX();
+ boolean isFlingToBot = isFlingTowardsEdge(touchState, 4 /* bottom */);
+ if (ENABLE_DISMISS_DRAG_TO_EDGE
+ && (mMotionHelper.shouldDismissPip() || isFlingToBot)) {
+ mMotionHelper.animateDragToEdgeDismiss(mMotionHelper.getBounds());
+ MetricsLogger.action(mContext,
+ MetricsEvent.ACTION_PICTURE_IN_PICTURE_DISMISSED,
+ METRIC_VALUE_DISMISSED_BY_DRAG);
+ return true;
+ } else if (!mIsMinimized && (mMotionHelper.shouldMinimizePip()
+ || isFlingTowardsEdge(touchState, onLeft ? 2 : 3))) {
// Pip should be minimized
setMinimizedStateInternal(true);
if (mMenuController.isMenuVisible()) {
@@ -472,9 +538,10 @@
// If the menu is still visible, and we aren't minimized, then just poke the menu
// so that it will timeout after the user stops touching it
if (mMenuController.isMenuVisible()) {
- mMenuController.showMenu();
+ mMenuController.showMenu(mMotionHelper.getBounds(), mMovementBounds);
}
+ final PointF vel = mTouchState.getVelocity();
final float velocity = PointF.length(vel.x, vel.y);
if (velocity > mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
mMotionHelper.flingToSnapTarget(velocity, vel.x, vel.y, mMovementBounds);
@@ -486,7 +553,7 @@
mMotionHelper.animateToClosestSnapTarget(mMovementBounds);
setMinimizedStateInternal(false);
} else if (!mIsMenuVisible) {
- mMenuController.showMenu();
+ mMenuController.showMenu(mMotionHelper.getBounds(), mMovementBounds);
} else {
mMotionHelper.expandPip();
}
@@ -495,29 +562,39 @@
};
/**
- * @return whether the gesture ending in the {@param vel} is fast enough to be a fling towards
- * the same edge the PIP is on. Used to identify a minimize gesture.
+ * @return whether the gesture ending in {@param vel} is fast enough to be a fling and towards
+ * the provided {@param edge} where:
+ *
+ * 1 = top
+ * 2 = left
+ * 3 = right
+ * 4 = bottom
*/
- private boolean isHorizontalFlingTowardsCurrentEdge(PointF vel) {
- final boolean isHorizontal = Math.abs(vel.x) > Math.abs(vel.y);
- final boolean isFling = PointF.length(vel.x, vel.y) > mFlingAnimationUtils
- .getMinVelocityPxPerSecond();
- final boolean towardsCurrentEdge = isOverEdge(true /* left */) && vel.x < 0
- || isOverEdge(false /* right */) && vel.x > 0;
- return towardsCurrentEdge && isHorizontal && isFling;
- }
-
- /**
- * @return whether the given bounds are on the left or right edge (depending on
- * {@param checkLeft})
- */
- private boolean isOverEdge(boolean checkLeft) {
+ private boolean isFlingTowardsEdge(PipTouchState touchState, int edge) {
+ final PointF vel = touchState.getVelocity();
+ final PointF downPos = touchState.getDownTouchPosition();
final Rect bounds = mMotionHelper.getBounds();
- if (checkLeft) {
- return bounds.left <= mMovementBounds.left;
- } else {
- return bounds.right >= mMovementBounds.right + bounds.width();
+ final boolean isHorizontal = Math.abs(vel.x) > Math.abs(vel.y);
+ final boolean isFling =
+ PointF.length(vel.x, vel.y) > mFlingAnimationUtils.getMinVelocityPxPerSecond();
+ if (!isFling) {
+ return false;
}
+ switch (edge) {
+ case 1: // top
+ return !isHorizontal && vel.y < 0
+ && downPos.y <= mMovementBounds.top + bounds.height();
+ case 2: // left
+ return isHorizontal && vel.x < 0
+ && downPos.x <= mMovementBounds.left + bounds.width();
+ case 3: // right
+ return isHorizontal && vel.x > 0
+ && downPos.x >= mMovementBounds.right;
+ case 4: // bottom
+ return !isHorizontal && vel.y > 0
+ && downPos.y >= mMovementBounds.bottom;
+ }
+ return false;
}
/**
@@ -542,9 +619,149 @@
pw.println(innerPrefix + "mIsImeShowing=" + mIsImeShowing);
pw.println(innerPrefix + "mImeHeight=" + mImeHeight);
pw.println(innerPrefix + "mSavedSnapFraction=" + mSavedSnapFraction);
- pw.println(innerPrefix + "mEnableDragToDismiss=" + ENABLE_DRAG_TO_DISMISS);
+ pw.println(innerPrefix + "mEnableDragToDismiss=" + ENABLE_DISMISS_DRAG_TO_TARGET);
mSnapAlgorithm.dump(pw, innerPrefix);
mTouchState.dump(pw, innerPrefix);
mMotionHelper.dump(pw, innerPrefix);
}
+
+ private static AccessibilityNodeInfo obtainRootAccessibilityNodeInfo() {
+ AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
+ info.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID,
+ AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK);
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_DISMISS);
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_MOVE_WINDOW);
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
+ info.setImportantForAccessibility(true);
+ info.setClickable(true);
+ info.setVisibleToUser(true);
+ return info;
+ }
+
+ /**
+ * Expose the touch actions to accessibility as if this object were a window with a single view.
+ * That pseudo-view exposes all of the actions this object can perform.
+ */
+ class AccessibilityInteractionConnection extends IAccessibilityInteractionConnection.Stub {
+ static final long ACCESSIBILITY_NODE_ID = 1;
+ List<AccessibilityNodeInfo> mAccessibilityNodeInfoList;
+
+ @Override
+ public void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId,
+ Region interactiveRegion, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, int flags,
+ int interrogatingPid, long interrogatingTid, MagnificationSpec spec, Bundle args) {
+ try {
+ callback.setFindAccessibilityNodeInfosResult(
+ (accessibilityNodeId == AccessibilityNodeInfo.ROOT_NODE_ID)
+ ? getNodeList() : null, interactionId);
+ } catch (RemoteException re) {
+ /* best effort - ignore */
+ }
+ }
+
+ @Override
+ public void performAccessibilityAction(long accessibilityNodeId, int action,
+ Bundle arguments, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, int flags,
+ int interrogatingPid, long interrogatingTid) {
+ // We only support one view. A request for anything else is invalid
+ boolean result = false;
+ if (accessibilityNodeId == AccessibilityNodeInfo.ROOT_NODE_ID) {
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_CLICK:
+ mHandler.post(mShowMenuRunnable);
+ result = true;
+ break;
+ case AccessibilityNodeInfo.ACTION_DISMISS:
+ mMotionHelper.dismissPip();
+ result = true;
+ break;
+ case com.android.internal.R.id.accessibilityActionMoveWindow:
+ int newX = arguments.getInt(
+ AccessibilityNodeInfo.ACTION_ARGUMENT_MOVE_WINDOW_X);
+ int newY = arguments.getInt(
+ AccessibilityNodeInfo.ACTION_ARGUMENT_MOVE_WINDOW_Y);
+ Rect pipBounds = new Rect();
+ pipBounds.set(mMotionHelper.getBounds());
+ mTmpBounds.offsetTo(newX, newY);
+ mMotionHelper.movePip(mTmpBounds);
+ result = true;
+ break;
+ case AccessibilityNodeInfo.ACTION_EXPAND:
+ mMotionHelper.expandPip();
+ result = true;
+ break;
+ default:
+ // Leave result as false
+ }
+ }
+ try {
+ callback.setPerformAccessibilityActionResult(result, interactionId);
+ } catch (RemoteException re) {
+ /* best effort - ignore */
+ }
+ }
+
+ @Override
+ public void findAccessibilityNodeInfosByViewId(long accessibilityNodeId,
+ String viewId, Region interactiveRegion, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, int flags,
+ int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
+ // We have no view with a proper ID
+ try {
+ callback.setFindAccessibilityNodeInfoResult(null, interactionId);
+ } catch (RemoteException re) {
+ /* best effort - ignore */
+ }
+ }
+
+ @Override
+ public void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text,
+ Region interactiveRegion, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, int flags,
+ int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
+ // We have no view with text
+ try {
+ callback.setFindAccessibilityNodeInfoResult(null, interactionId);
+ } catch (RemoteException re) {
+ /* best effort - ignore */
+ }
+ }
+
+ @Override
+ public void findFocus(long accessibilityNodeId, int focusType, Region interactiveRegion,
+ int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
+ int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
+ // We have no view that can take focus
+ try {
+ callback.setFindAccessibilityNodeInfoResult(null, interactionId);
+ } catch (RemoteException re) {
+ /* best effort - ignore */
+ }
+ }
+
+ @Override
+ public void focusSearch(long accessibilityNodeId, int direction, Region interactiveRegion,
+ int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
+ int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
+ // We have no view that can take focus
+ try {
+ callback.setFindAccessibilityNodeInfoResult(null, interactionId);
+ } catch (RemoteException re) {
+ /* best effort - ignore */
+ }
+ }
+
+ private List<AccessibilityNodeInfo> getNodeList() {
+ if (mAccessibilityNodeInfoList == null) {
+ mAccessibilityNodeInfoList = new ArrayList<>(1);
+ }
+ AccessibilityNodeInfo info = obtainRootAccessibilityNodeInfo();
+ mAccessibilityNodeInfoList.clear();
+ mAccessibilityNodeInfoList.add(info);
+ return mAccessibilityNodeInfoList;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
index a317dc3..b34a07d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
@@ -170,6 +170,13 @@
}
/**
+ * @return the down touch position.
+ */
+ public PointF getDownTouchPosition() {
+ return mDownTouch;
+ }
+
+ /**
* @return the movement delta between the last handled touch event and the down touch
* position.
*/
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 12332fb..47468ae 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -22,6 +22,7 @@
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
import android.annotation.NonNull;
@@ -1057,15 +1058,18 @@
}
/**
- * Returns the window rect for the RecentsActivity, based on the dimensions of the home stack.
+ * Returns the window rect for the RecentsActivity, based on the dimensions of the recents stack
*/
public Rect getWindowRect() {
Rect windowRect = new Rect();
if (mIam == null) return windowRect;
try {
- // Use the home stack bounds
- ActivityManager.StackInfo stackInfo = mIam.getStackInfo(HOME_STACK_ID);
+ // Use the recents stack bounds, fallback to fullscreen stack if it is null
+ ActivityManager.StackInfo stackInfo = mIam.getStackInfo(RECENTS_STACK_ID);
+ if (stackInfo == null) {
+ stackInfo = mIam.getStackInfo(FULLSCREEN_WORKSPACE_STACK_ID);
+ }
if (stackInfo != null) {
windowRect.set(stackInfo.bounds);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
index db0c95e..2180ec8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
@@ -160,7 +160,10 @@
EventBus.getDefault().send(new DragStartInitializeDropTargetsEvent(event.task,
event.taskView, this));
if (mDeviceId != -1) {
- InputDevice.getDevice(mDeviceId).setPointerType(PointerIcon.TYPE_GRABBING);
+ InputDevice device = InputDevice.getDevice(mDeviceId);
+ if (device != null) {
+ device.setPointerType(PointerIcon.TYPE_GRABBING);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 6f59fe2..97506e6 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -746,15 +746,18 @@
if (mStableInsets.isEmpty()) {
SystemServicesProxy.getInstance(mContext).getStableInsets(mStableInsets);
}
+ mMinimizedSnapAlgorithm = null;
+ mDockedStackMinimized = minimized;
+ initializeSnapAlgorithm();
if (!mIsInMinimizeInteraction && minimized) {
mIsInMinimizeInteraction = true;
mDividerPositionBeforeMinimized = DockedDividerUtils.calculateMiddlePosition(
isHorizontalDivision(), mStableInsets, mDisplayWidth, mDisplayHeight,
mDividerSize);
+
+ int position = mMinimizedSnapAlgorithm.getMiddleTarget().position;
+ resizeStack(position, position, mMinimizedSnapAlgorithm.getMiddleTarget());
}
- mMinimizedSnapAlgorithm = null;
- mDockedStackMinimized = minimized;
- initializeSnapAlgorithm();
}
}
@@ -1140,7 +1143,7 @@
&& dockSideBottomRight(mDockSide))) {
return StackId.DOCKED_STACK_ID;
} else {
- return StackId.HOME_STACK_ID;
+ return StackId.RECENTS_STACK_ID;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index fb92a67..dceeb74 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -29,6 +29,7 @@
import android.os.BatteryStats;
import android.os.Handler;
import android.os.Message;
+import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -39,6 +40,7 @@
import android.view.View;
import android.view.ViewGroup;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
@@ -49,6 +51,8 @@
import com.android.systemui.statusbar.phone.LockIcon;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.util.wakelock.SettableWakeLock;
+import com.android.systemui.util.wakelock.WakeLock;
/**
* Controls the indications and error messages shown on the Keyguard
@@ -68,6 +72,7 @@
private final KeyguardIndicationTextView mDisclosure;
private final UserManager mUserManager;
private final IBatteryStats mBatteryInfo;
+ private final SettableWakeLock mWakeLock;
private final int mSlowThreshold;
private final int mFastThreshold;
@@ -92,6 +97,13 @@
public KeyguardIndicationController(Context context, ViewGroup indicationArea,
LockIcon lockIcon) {
+ this(context, indicationArea, lockIcon,
+ WakeLock.createPartial(context, "Doze:KeyguardIndication"));
+ }
+
+ @VisibleForTesting
+ KeyguardIndicationController(Context context, ViewGroup indicationArea, LockIcon lockIcon,
+ WakeLock wakeLock) {
mContext = context;
mIndicationArea = indicationArea;
mTextView = (KeyguardIndicationTextView) indicationArea.findViewById(
@@ -99,6 +111,7 @@
mDisclosure = (KeyguardIndicationTextView) indicationArea.findViewById(
R.id.keyguard_indication_enterprise_disclosure);
mLockIcon = lockIcon;
+ mWakeLock = new SettableWakeLock(wakeLock);
Resources res = context.getResources();
mSlowThreshold = res.getInteger(R.integer.config_chargingSlowlyThreshold);
@@ -208,6 +221,11 @@
mTransientIndication = transientIndication;
mTransientTextColor = textColor;
mHandler.removeMessages(MSG_HIDE_TRANSIENT);
+ if (mDozing && !TextUtils.isEmpty(mTransientIndication)) {
+ // Make sure this doesn't get stuck and burns in. Acquire wakelock until its cleared.
+ mWakeLock.setAcquired(true);
+ hideTransientIndicationDelayed(BaseKeyguardCallback.HIDE_DELAY_MS);
+ }
updateIndication();
}
@@ -223,6 +241,10 @@
}
private void updateIndication() {
+ if (TextUtils.isEmpty(mTransientIndication)) {
+ mWakeLock.setAcquired(false);
+ }
+
if (mVisible) {
// Walk down a precedence-ordered list of what should indication
// should be shown based on user or device state
@@ -323,9 +345,8 @@
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
- if (msg.what == MSG_HIDE_TRANSIENT && mTransientIndication != null) {
- mTransientIndication = null;
- updateIndication();
+ if (msg.what == MSG_HIDE_TRANSIENT) {
+ hideTransientIndication();
} else if (msg.what == MSG_CLEAR_FP_MSG) {
mLockIcon.setTransientFpError(false);
hideTransientIndication();
@@ -340,17 +361,27 @@
}
protected class BaseKeyguardCallback extends KeyguardUpdateMonitorCallback {
+ public static final int HIDE_DELAY_MS = 5000;
private int mLastSuccessiveErrorMessage = -1;
@Override
public void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) {
boolean isChargingOrFull = status.status == BatteryManager.BATTERY_STATUS_CHARGING
|| status.status == BatteryManager.BATTERY_STATUS_FULL;
+ boolean wasPluggedIn = mPowerPluggedIn;
mPowerPluggedIn = status.isPluggedIn() && isChargingOrFull;
mPowerCharged = status.isCharged();
mChargingWattage = status.maxChargingWattage;
mChargingSpeed = status.getChargingSpeed(mSlowThreshold, mFastThreshold);
updateIndication();
+ if (mDozing) {
+ if (!wasPluggedIn && mPowerPluggedIn) {
+ showTransientIndication(computePowerIndication());
+ hideTransientIndicationDelayed(HIDE_DELAY_MS);
+ } else if (wasPluggedIn && !mPowerPluggedIn) {
+ hideTransientIndication();
+ }
+ }
}
@Override
@@ -401,8 +432,7 @@
} else if (updateMonitor.isDeviceInteractive()) {
showTransientIndication(errString, errorColor);
// We want to keep this message around in case the screen was off
- mHandler.removeMessages(MSG_HIDE_TRANSIENT);
- hideTransientIndicationDelayed(5000);
+ hideTransientIndicationDelayed(HIDE_DELAY_MS);
} else {
mMessageToShowOnScreenOn = errString;
}
@@ -415,8 +445,7 @@
int errorColor = Utils.getColorError(mContext);
showTransientIndication(mMessageToShowOnScreenOn, errorColor);
// We want to keep this message around in case the screen was off
- mHandler.removeMessages(MSG_HIDE_TRANSIENT);
- hideTransientIndicationDelayed(5000);
+ hideTransientIndicationDelayed(HIDE_DELAY_MS);
mMessageToShowOnScreenOn = null;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 8f8d966..90e908b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -16,11 +16,15 @@
package com.android.systemui.statusbar;
+import android.app.AppGlobals;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
import android.content.Context;
import android.graphics.drawable.Icon;
+import android.os.RemoteException;
import android.os.SystemClock;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.Ranking;
@@ -31,7 +35,9 @@
import android.view.View;
import android.widget.ImageView;
import android.widget.RemoteViews;
+import android.Manifest;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.NotificationColorUtil;
import com.android.systemui.statusbar.notification.InflationException;
@@ -453,13 +459,30 @@
}
// Q: What kinds of notifications should show during setup?
- // A: Almost none! Only things coming from the system (package is "android") that also
- // have special "kind" tags marking them as relevant for setup (see below).
+ // A: Almost none! Only things coming from packages with permission
+ // android.permission.NOTIFICATION_DURING_SETUP that also have special "kind" tags marking them
+ // as relevant for setup (see below).
public static boolean showNotificationEvenIfUnprovisioned(StatusBarNotification sbn) {
- return "android".equals(sbn.getPackageName())
+ return showNotificationEvenIfUnprovisioned(AppGlobals.getPackageManager(), sbn);
+ }
+
+ @VisibleForTesting
+ static boolean showNotificationEvenIfUnprovisioned(IPackageManager packageManager,
+ StatusBarNotification sbn) {
+ return checkUidPermission(packageManager, Manifest.permission.NOTIFICATION_DURING_SETUP,
+ sbn.getUid()) == PackageManager.PERMISSION_GRANTED
&& sbn.getNotification().extras.getBoolean(Notification.EXTRA_ALLOW_DURING_SETUP);
}
+ private static int checkUidPermission(IPackageManager packageManager, String permission,
+ int uid) {
+ try {
+ return packageManager.checkUidPermission(permission, uid);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
public void dump(PrintWriter pw, String indent) {
int N = mSortedAndFiltered.size();
pw.print(indent);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
index 66703ee..73eecbb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
@@ -23,19 +23,19 @@
import android.view.View;
import android.widget.RemoteViews;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.NotificationContentView;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.phone.StatusBar;
-import java.util.Objects;
-
/**
* A utility that inflates the right kind of contentView based on the state
*/
public class NotificationInflater {
- private static final int FLAG_REINFLATE_ALL = ~0;
+ @VisibleForTesting
+ static final int FLAG_REINFLATE_ALL = ~0;
private static final int FLAG_REINFLATE_CONTENT_VIEW = 1<<0;
private static final int FLAG_REINFLATE_EXPANDED_VIEW = 1<<1;
private static final int FLAG_REINFLATE_HEADS_UP_VIEW = 1<<2;
@@ -104,115 +104,12 @@
*/
private void inflateNotificationViews(int reInflateFlags)
throws InflationException {
- NotificationData.Entry entry = mRow.getEntry();
- StatusBarNotification sbn = entry.notification;
- Context context = mRow.getContext();
- NotificationContentView privateLayout = mRow.getPrivateLayout();
+ StatusBarNotification sbn = mRow.getEntry().notification;
try {
final Notification.Builder recoveredBuilder
- = Notification.Builder.recoverBuilder(context, sbn.getNotification());
- boolean isLowPriority = mIsLowPriority && !mIsChildInGroup;
- if ((reInflateFlags & FLAG_REINFLATE_CONTENT_VIEW) != 0) {
- final RemoteViews newContentView = createContentView(recoveredBuilder,
- isLowPriority, mUsesIncreasedHeadsUpHeight);
- if (!compareRemoteViews(newContentView,
- entry.cachedContentView)) {
- View contentViewLocal = newContentView.apply(
- sbn.getPackageContext(context),
- privateLayout,
- mRemoteViewClickHandler);
- contentViewLocal.setIsRootNamespace(true);
- privateLayout.setContractedChild(contentViewLocal);
- } else {
- newContentView.reapply(sbn.getPackageContext(context),
- privateLayout.getContractedChild(),
- mRemoteViewClickHandler);
- }
- entry.cachedContentView = newContentView;
- }
-
- if ((reInflateFlags & FLAG_REINFLATE_EXPANDED_VIEW) != 0) {
- final RemoteViews newBigContentView = createBigContentView(
- recoveredBuilder, isLowPriority);
- if (newBigContentView != null) {
- if (!compareRemoteViews(newBigContentView, entry.cachedBigContentView)) {
- View bigContentViewLocal = newBigContentView.apply(
- sbn.getPackageContext(context),
- privateLayout,
- mRemoteViewClickHandler);
- bigContentViewLocal.setIsRootNamespace(true);
- privateLayout.setExpandedChild(bigContentViewLocal);
- } else {
- newBigContentView.reapply(sbn.getPackageContext(context),
- privateLayout.getExpandedChild(),
- mRemoteViewClickHandler);
- }
- } else if (entry.cachedBigContentView != null) {
- privateLayout.setExpandedChild(null);
- }
- entry.cachedBigContentView = newBigContentView;
- mRow.setExpandable(newBigContentView != null);
- }
-
- if ((reInflateFlags & FLAG_REINFLATE_HEADS_UP_VIEW) != 0) {
- final RemoteViews newHeadsUpContentView =
- recoveredBuilder.createHeadsUpContentView(mUsesIncreasedHeight);
- if (newHeadsUpContentView != null) {
- if (!compareRemoteViews(newHeadsUpContentView,
- entry.cachedHeadsUpContentView)) {
- View headsUpContentViewLocal = newHeadsUpContentView.apply(
- sbn.getPackageContext(context),
- privateLayout,
- mRemoteViewClickHandler);
- headsUpContentViewLocal.setIsRootNamespace(true);
- privateLayout.setHeadsUpChild(headsUpContentViewLocal);
- } else {
- newHeadsUpContentView.reapply(sbn.getPackageContext(context),
- privateLayout.getHeadsUpChild(),
- mRemoteViewClickHandler);
- }
- } else if (entry.cachedHeadsUpContentView != null) {
- privateLayout.setHeadsUpChild(null);
- }
- entry.cachedHeadsUpContentView = newHeadsUpContentView;
- }
-
- if ((reInflateFlags & FLAG_REINFLATE_PUBLIC_VIEW) != 0) {
- NotificationContentView publicLayout = mRow.getPublicLayout();
- final RemoteViews newPublicNotification
- = recoveredBuilder.makePublicContentView();
- if (!compareRemoteViews(newPublicNotification, entry.cachedPublicContentView)) {
- View publicContentView = newPublicNotification.apply(
- sbn.getPackageContext(context),
- publicLayout,
- mRemoteViewClickHandler);
- publicContentView.setIsRootNamespace(true);
- publicLayout.setContractedChild(publicContentView);
- } else {
- newPublicNotification.reapply(sbn.getPackageContext(context),
- publicLayout.getContractedChild(),
- mRemoteViewClickHandler);
- }
- entry.cachedPublicContentView = newPublicNotification;
- }
-
- if ((reInflateFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) {
- final RemoteViews newAmbientNotification
- = recoveredBuilder.makeAmbientNotification();
- if (!compareRemoteViews(newAmbientNotification, entry.cachedAmbientContentView)) {
- View ambientContentView = newAmbientNotification.apply(
- sbn.getPackageContext(context),
- privateLayout,
- mRemoteViewClickHandler);
- ambientContentView.setIsRootNamespace(true);
- privateLayout.setAmbientChild(ambientContentView);
- } else {
- newAmbientNotification.reapply(sbn.getPackageContext(context),
- privateLayout.getAmbientChild(),
- mRemoteViewClickHandler);
- }
- entry.cachedAmbientContentView = newAmbientNotification;
- }
+ = Notification.Builder.recoverBuilder(mRow.getContext(), sbn.getNotification());
+ Context packageContext = sbn.getPackageContext(mRow.getContext());
+ inflateNotificationViews(reInflateFlags, recoveredBuilder, packageContext);
} catch (RuntimeException e) {
final String ident = sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId());
@@ -221,6 +118,115 @@
}
}
+ @VisibleForTesting
+ void inflateNotificationViews(int reInflateFlags,
+ Notification.Builder builder, Context packageContext) {
+ NotificationData.Entry entry = mRow.getEntry();
+ NotificationContentView privateLayout = mRow.getPrivateLayout();
+ boolean isLowPriority = mIsLowPriority && !mIsChildInGroup;
+ if ((reInflateFlags & FLAG_REINFLATE_CONTENT_VIEW) != 0) {
+ final RemoteViews newContentView = createContentView(builder,
+ isLowPriority, mUsesIncreasedHeight);
+ if (!compareRemoteViews(newContentView,
+ entry.cachedContentView)) {
+ View contentViewLocal = newContentView.apply(
+ packageContext,
+ privateLayout,
+ mRemoteViewClickHandler);
+ contentViewLocal.setIsRootNamespace(true);
+ privateLayout.setContractedChild(contentViewLocal);
+ } else {
+ newContentView.reapply(packageContext,
+ privateLayout.getContractedChild(),
+ mRemoteViewClickHandler);
+ }
+ entry.cachedContentView = newContentView;
+ }
+
+ if ((reInflateFlags & FLAG_REINFLATE_EXPANDED_VIEW) != 0) {
+ final RemoteViews newBigContentView = createBigContentView(
+ builder, isLowPriority);
+ if (newBigContentView != null) {
+ if (!compareRemoteViews(newBigContentView, entry.cachedBigContentView)) {
+ View bigContentViewLocal = newBigContentView.apply(
+ packageContext,
+ privateLayout,
+ mRemoteViewClickHandler);
+ bigContentViewLocal.setIsRootNamespace(true);
+ privateLayout.setExpandedChild(bigContentViewLocal);
+ } else {
+ newBigContentView.reapply(packageContext,
+ privateLayout.getExpandedChild(),
+ mRemoteViewClickHandler);
+ }
+ } else if (entry.cachedBigContentView != null) {
+ privateLayout.setExpandedChild(null);
+ }
+ entry.cachedBigContentView = newBigContentView;
+ mRow.setExpandable(newBigContentView != null);
+ }
+
+ if ((reInflateFlags & FLAG_REINFLATE_HEADS_UP_VIEW) != 0) {
+ final RemoteViews newHeadsUpContentView =
+ builder.createHeadsUpContentView(mUsesIncreasedHeadsUpHeight);
+ if (newHeadsUpContentView != null) {
+ if (!compareRemoteViews(newHeadsUpContentView,
+ entry.cachedHeadsUpContentView)) {
+ View headsUpContentViewLocal = newHeadsUpContentView.apply(
+ packageContext,
+ privateLayout,
+ mRemoteViewClickHandler);
+ headsUpContentViewLocal.setIsRootNamespace(true);
+ privateLayout.setHeadsUpChild(headsUpContentViewLocal);
+ } else {
+ newHeadsUpContentView.reapply(packageContext,
+ privateLayout.getHeadsUpChild(),
+ mRemoteViewClickHandler);
+ }
+ } else if (entry.cachedHeadsUpContentView != null) {
+ privateLayout.setHeadsUpChild(null);
+ }
+ entry.cachedHeadsUpContentView = newHeadsUpContentView;
+ }
+
+ if ((reInflateFlags & FLAG_REINFLATE_PUBLIC_VIEW) != 0) {
+ NotificationContentView publicLayout = mRow.getPublicLayout();
+ final RemoteViews newPublicNotification
+ = builder.makePublicContentView();
+ if (!compareRemoteViews(newPublicNotification, entry.cachedPublicContentView)) {
+ View publicContentView = newPublicNotification.apply(
+ packageContext,
+ publicLayout,
+ mRemoteViewClickHandler);
+ publicContentView.setIsRootNamespace(true);
+ publicLayout.setContractedChild(publicContentView);
+ } else {
+ newPublicNotification.reapply(packageContext,
+ publicLayout.getContractedChild(),
+ mRemoteViewClickHandler);
+ }
+ entry.cachedPublicContentView = newPublicNotification;
+ }
+
+ if ((reInflateFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) {
+ final RemoteViews newAmbientNotification
+ = builder.makeAmbientNotification();
+ if (!compareRemoteViews(newAmbientNotification, entry.cachedAmbientContentView)) {
+ View ambientContentView = newAmbientNotification.apply(
+ packageContext,
+ privateLayout,
+ mRemoteViewClickHandler);
+ ambientContentView.setIsRootNamespace(true);
+ privateLayout.setAmbientChild(ambientContentView);
+ } else {
+ newAmbientNotification.reapply(packageContext,
+ privateLayout.getAmbientChild(),
+ mRemoteViewClickHandler);
+ }
+ entry.cachedAmbientContentView = newAmbientNotification;
+ }
+ }
+
private RemoteViews createBigContentView(Notification.Builder builder,
boolean isLowPriority) {
RemoteViews bigContentView = builder.createBigContentView();
@@ -260,6 +266,7 @@
public interface InflationExceptionHandler {
void handleInflationException(StatusBarNotification notification, InflationException e);
}
+
public void onDensityOrFontScaleChanged() {
NotificationData.Entry entry = mRow.getEntry();
entry.cachedAmbientContentView = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 4a2ec88..7b2e997 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
-import android.os.Build;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
@@ -25,6 +24,7 @@
import android.util.MathUtils;
import android.util.SparseBooleanArray;
+import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.systemui.R;
import java.io.PrintWriter;
@@ -32,14 +32,15 @@
public class DozeParameters {
private static final int MAX_DURATION = 60 * 1000;
public static final String DOZE_SENSORS_WAKE_UP_FULLY = "doze_sensors_wake_up_fully";
- public static final boolean ALWAYS_ON_AVAILABLE = Build.IS_DEBUGGABLE;
private final Context mContext;
+ private final AmbientDisplayConfiguration mAmbientDisplayConfiguration;
private static IntInOutMatcher sPickupSubtypePerformsProxMatcher;
public DozeParameters(Context context) {
mContext = context;
+ mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext);
}
public void dump(PrintWriter pw) {
@@ -58,8 +59,7 @@
pw.print(" getPickupVibrationThreshold(): "); pw.println(getPickupVibrationThreshold());
pw.print(" getPickupSubtypePerformsProxCheck(): ");pw.println(
dumpPickupSubtypePerformsProxCheck());
- if (ALWAYS_ON_AVAILABLE) {
- pw.print(" getAlwaysOn(): "); pw.println(getAlwaysOn());
+ if (mAmbientDisplayConfiguration.alwaysOnAvailable()) {
pw.print(" getSensorsWakeUpFully(): "); pw.println(getSensorsWakeUpFully());
}
}
@@ -119,13 +119,11 @@
}
public boolean getAlwaysOn() {
- return ALWAYS_ON_AVAILABLE
- && Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.DOZE_ALWAYS_ON, 0, UserHandle.USER_CURRENT) != 0;
+ return mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT);
}
public boolean getSensorsWakeUpFully() {
- return ALWAYS_ON_AVAILABLE
+ return mAmbientDisplayConfiguration.alwaysOnAvailable()
&& Settings.Secure.getIntForUser(mContext.getContentResolver(),
DOZE_SENSORS_WAKE_UP_FULLY, 1, UserHandle.USER_CURRENT) != 0;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
index 83b96bf..b5f56c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
@@ -19,6 +19,7 @@
import android.metrics.LogMaker;
import android.util.ArrayMap;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.EventLogConstants;
@@ -32,6 +33,7 @@
private ArrayMap<Integer, Integer> mLegacyMap;
private LogMaker mLogMaker = new LogMaker(MetricsEvent.VIEW_UNKNOWN)
.setType(MetricsEvent.TYPE_ACTION);
+ private MetricsLogger mMetricsLogger = new MetricsLogger();
public LockscreenGestureLogger() {
mLegacyMap = new ArrayMap<>(EventLogConstants.METRICS_GESTURE_TYPE_MAP.length);
@@ -41,7 +43,7 @@
}
public void write(int gesture, int length, int velocity) {
- MetricsLogger.action(mLogMaker.setCategory(gesture)
+ mMetricsLogger.write(mLogMaker.setCategory(gesture)
.setType(MetricsEvent.TYPE_ACTION)
.addTaggedData(MetricsEvent.FIELD_GESTURE_LENGTH, length)
.addTaggedData(MetricsEvent.FIELD_GESTURE_VELOCITY, velocity));
@@ -56,4 +58,9 @@
}
return value;
}
+
+ @VisibleForTesting
+ void setMetricsLogger(MetricsLogger metricsLogger) {
+ mMetricsLogger = metricsLogger;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 6c729dc..2c5bd3c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -90,6 +90,7 @@
import android.provider.Settings;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
+import android.support.annotation.VisibleForTesting;
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.EventLog;
@@ -751,6 +752,12 @@
private NavigationBarFragment mNavigationBar;
private View mNavigationBarView;
+ @VisibleForTesting
+ void setMetricsLogger(MetricsLogger metricsLogger) {
+ mMetricsLogger = metricsLogger;
+ mLockscreenGestureLogger.setMetricsLogger(metricsLogger);
+ }
+
@Override
public void start() {
mNetworkController = Dependency.get(NetworkController.class);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 48ff1c1..641fe69 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -45,7 +45,7 @@
* has occurred.
*/
interface BatteryStateChangeCallback {
- void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging);
- void onPowerSaveChanged(boolean isPowerSave);
+ default void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {}
+ default void onPowerSaveChanged(boolean isPowerSave) {}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index 209b439..e7bce708 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -26,11 +26,11 @@
import android.view.MenuInflater;
import android.view.MenuItem;
+import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.plugins.PluginPrefs;
-import com.android.systemui.statusbar.phone.DozeParameters;
public class TunerFragment extends PreferenceFragment {
@@ -65,7 +65,7 @@
if (!PluginPrefs.hasPlugins(getContext())) {
getPreferenceScreen().removePreference(findPreference(KEY_PLUGINS));
}
- if (!DozeParameters.ALWAYS_ON_AVAILABLE) {
+ if (!alwaysOnAvailable()) {
getPreferenceScreen().removePreference(findPreference(KEY_DOZE));
}
@@ -77,6 +77,10 @@
}
}
+ private boolean alwaysOnAvailable() {
+ return new AmbientDisplayConfiguration(getContext()).alwaysOnAvailable();
+ }
+
@Override
public void onResume() {
super.onResume();
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 43727e0..cfe16dd 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.app.Notification;
import android.app.Notification.Action;
+import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -35,6 +36,7 @@
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
+import android.provider.Settings;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
@@ -181,6 +183,11 @@
}
private void updateMissingPrivateVolumes() {
+ if (isTv()) {
+ // On TV, TvSettings displays a modal full-screen activity in this case.
+ return;
+ }
+
final List<VolumeRecord> recs = mStorageManager.getVolumeRecords();
for (VolumeRecord rec : recs) {
if (rec.getType() != VolumeInfo.TYPE_PRIVATE) continue;
@@ -210,7 +217,8 @@
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setLocalOnly(true)
.setCategory(Notification.CATEGORY_SYSTEM)
- .setDeleteIntent(buildSnoozeIntent(fsUuid));
+ .setDeleteIntent(buildSnoozeIntent(fsUuid))
+ .extend(new Notification.TvExtender());
SystemUI.overrideNotificationAppName(mContext, builder);
mNotificationManager.notifyAsUser(fsUuid, SystemMessage.NOTE_STORAGE_PRIVATE,
@@ -237,7 +245,8 @@
.setStyle(new Notification.BigTextStyle().bigText(text))
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setLocalOnly(true)
- .setCategory(Notification.CATEGORY_ERROR);
+ .setCategory(Notification.CATEGORY_ERROR)
+ .extend(new Notification.TvExtender());
SystemUI.overrideNotificationAppName(mContext, builder);
mNotificationManager.notifyAsUser(disk.getId(), SystemMessage.NOTE_STORAGE_DISK,
@@ -378,7 +387,7 @@
.addAction(new Action(R.drawable.ic_eject_24dp,
mContext.getString(R.string.ext_media_unmount_action),
buildUnmountPendingIntent(vol)))
- .setContentIntent(browseIntent)
+ .setContentIntent(buildUnmountPendingIntent(vol))
.setCategory(Notification.CATEGORY_SYSTEM);
// Non-adoptable disks can't be snoozed.
if (disk.isAdoptable()) {
@@ -571,15 +580,21 @@
.setContentText(text)
.setStyle(new Notification.BigTextStyle().bigText(text))
.setVisibility(Notification.VISIBILITY_PUBLIC)
- .setLocalOnly(true);
+ .setLocalOnly(true)
+ .extend(new Notification.TvExtender());
overrideNotificationAppName(mContext, builder);
return builder;
}
private PendingIntent buildInitPendingIntent(DiskInfo disk) {
final Intent intent = new Intent();
- intent.setClassName("com.android.settings",
- "com.android.settings.deviceinfo.StorageWizardInit");
+ if (isTv()) {
+ intent.setPackage("com.android.tv.settings");
+ intent.setAction("com.android.tv.settings.action.NEW_STORAGE");
+ } else {
+ intent.setClassName("com.android.settings",
+ "com.android.settings.deviceinfo.StorageWizardInit");
+ }
intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.getId());
final int requestKey = disk.getId().hashCode();
@@ -589,8 +604,13 @@
private PendingIntent buildInitPendingIntent(VolumeInfo vol) {
final Intent intent = new Intent();
- intent.setClassName("com.android.settings",
- "com.android.settings.deviceinfo.StorageWizardInit");
+ if (isTv()) {
+ intent.setPackage("com.android.tv.settings");
+ intent.setAction("com.android.tv.settings.action.NEW_STORAGE");
+ } else {
+ intent.setClassName("com.android.settings",
+ "com.android.settings.deviceinfo.StorageWizardInit");
+ }
intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
final int requestKey = vol.getId().hashCode();
@@ -600,13 +620,23 @@
private PendingIntent buildUnmountPendingIntent(VolumeInfo vol) {
final Intent intent = new Intent();
- intent.setClassName("com.android.settings",
- "com.android.settings.deviceinfo.StorageUnmountReceiver");
- intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
+ if (isTv()) {
+ intent.setPackage("com.android.tv.settings");
+ intent.setAction("com.android.tv.settings.action.UNMOUNT_STORAGE");
+ intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
- final int requestKey = vol.getId().hashCode();
- return PendingIntent.getBroadcastAsUser(mContext, requestKey, intent,
- PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.CURRENT);
+ final int requestKey = vol.getId().hashCode();
+ return PendingIntent.getActivityAsUser(mContext, requestKey, intent,
+ PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
+ } else {
+ intent.setClassName("com.android.settings",
+ "com.android.settings.deviceinfo.StorageUnmountReceiver");
+ intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
+
+ final int requestKey = vol.getId().hashCode();
+ return PendingIntent.getBroadcastAsUser(mContext, requestKey, intent,
+ PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.CURRENT);
+ }
}
private PendingIntent buildBrowsePendingIntent(VolumeInfo vol) {
@@ -619,17 +649,22 @@
private PendingIntent buildVolumeSettingsPendingIntent(VolumeInfo vol) {
final Intent intent = new Intent();
- switch (vol.getType()) {
- case VolumeInfo.TYPE_PRIVATE:
- intent.setClassName("com.android.settings",
- "com.android.settings.Settings$PrivateVolumeSettingsActivity");
- break;
- case VolumeInfo.TYPE_PUBLIC:
- intent.setClassName("com.android.settings",
- "com.android.settings.Settings$PublicVolumeSettingsActivity");
- break;
- default:
- return null;
+ if (isTv()) {
+ intent.setPackage("com.android.tv.settings");
+ intent.setAction(Settings.ACTION_INTERNAL_STORAGE_SETTINGS);
+ } else {
+ switch (vol.getType()) {
+ case VolumeInfo.TYPE_PRIVATE:
+ intent.setClassName("com.android.settings",
+ "com.android.settings.Settings$PrivateVolumeSettingsActivity");
+ break;
+ case VolumeInfo.TYPE_PUBLIC:
+ intent.setClassName("com.android.settings",
+ "com.android.settings.Settings$PublicVolumeSettingsActivity");
+ break;
+ default:
+ return null;
+ }
}
intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
@@ -648,6 +683,7 @@
}
private PendingIntent buildForgetPendingIntent(VolumeRecord rec) {
+ // Not used on TV
final Intent intent = new Intent();
intent.setClassName("com.android.settings",
"com.android.settings.Settings$PrivateVolumeForgetActivity");
@@ -660,8 +696,13 @@
private PendingIntent buildWizardMigratePendingIntent(MoveInfo move) {
final Intent intent = new Intent();
- intent.setClassName("com.android.settings",
- "com.android.settings.deviceinfo.StorageWizardMigrateProgress");
+ if (isTv()) {
+ intent.setPackage("com.android.tv.settings");
+ intent.setAction("com.android.tv.settings.action.MIGRATE_STORAGE");
+ } else {
+ intent.setClassName("com.android.settings",
+ "com.android.settings.deviceinfo.StorageWizardMigrateProgress");
+ }
intent.putExtra(PackageManager.EXTRA_MOVE_ID, move.moveId);
final VolumeInfo vol = mStorageManager.findVolumeByQualifiedUuid(move.volumeUuid);
@@ -674,8 +715,13 @@
private PendingIntent buildWizardMovePendingIntent(MoveInfo move) {
final Intent intent = new Intent();
- intent.setClassName("com.android.settings",
- "com.android.settings.deviceinfo.StorageWizardMoveProgress");
+ if (isTv()) {
+ intent.setPackage("com.android.tv.settings");
+ intent.setAction("com.android.tv.settings.action.MOVE_APP");
+ } else {
+ intent.setClassName("com.android.settings",
+ "com.android.settings.deviceinfo.StorageWizardMoveProgress");
+ }
intent.putExtra(PackageManager.EXTRA_MOVE_ID, move.moveId);
return PendingIntent.getActivityAsUser(mContext, move.moveId, intent,
@@ -684,12 +730,22 @@
private PendingIntent buildWizardReadyPendingIntent(DiskInfo disk) {
final Intent intent = new Intent();
- intent.setClassName("com.android.settings",
- "com.android.settings.deviceinfo.StorageWizardReady");
+ if (isTv()) {
+ intent.setPackage("com.android.tv.settings");
+ intent.setAction(Settings.ACTION_INTERNAL_STORAGE_SETTINGS);
+ } else {
+ intent.setClassName("com.android.settings",
+ "com.android.settings.deviceinfo.StorageWizardReady");
+ }
intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.getId());
final int requestKey = disk.getId().hashCode();
return PendingIntent.getActivityAsUser(mContext, requestKey, intent,
PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
}
+
+ private boolean isTv() {
+ PackageManager packageManager = mContext.getPackageManager();
+ return packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
index 5911766..5df3beb 100644
--- a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
+++ b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
@@ -18,6 +18,7 @@
import android.app.NotificationManager;
import android.content.Context;
+import android.content.pm.PackageManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
@@ -32,6 +33,7 @@
@VisibleForTesting
static void createAll(Context context) {
+
final NotificationManager nm = context.getSystemService(NotificationManager.class);
nm.createNotificationChannels(Arrays.asList(
new NotificationChannel(
@@ -49,7 +51,9 @@
new NotificationChannel(
STORAGE,
R.string.notification_channel_storage,
- NotificationManager.IMPORTANCE_LOW)
+ isTv(context)
+ ? NotificationManager.IMPORTANCE_DEFAULT
+ : NotificationManager.IMPORTANCE_LOW)
));
}
@@ -57,4 +61,9 @@
public void start() {
createAll(mContext);
}
+
+ private static boolean isTv(Context context) {
+ PackageManager packageManager = context.getPackageManager();
+ return packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
new file mode 100644
index 0000000..f2ed55f3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.util.wakelock;
+
+import android.os.Handler;
+import android.os.PowerManager;
+
+import com.android.internal.util.Preconditions;
+
+public class SettableWakeLock {
+
+ private final WakeLock mInner;
+
+ private boolean mAcquired;
+
+ public SettableWakeLock(WakeLock inner) {
+ Preconditions.checkNotNull(inner, "inner wakelock required");
+
+ mInner = inner;
+ }
+
+ public synchronized boolean isAcquired() {
+ return mAcquired;
+ }
+
+ public synchronized void setAcquired(boolean acquired) {
+ if (mAcquired != acquired) {
+ if (acquired) {
+ mInner.acquire();
+ } else {
+ mInner.release();
+ }
+ mAcquired = acquired;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
new file mode 100644
index 0000000..eea3de3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.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 com.android.systemui.util.wakelock;
+
+import android.content.Context;
+import android.os.PowerManager;
+import android.support.annotation.VisibleForTesting;
+
+import com.android.systemui.plugins.doze.DozeProvider;
+
+/** WakeLock wrapper for testability */
+public interface WakeLock extends DozeProvider.WakeLock {
+
+ static WakeLock createPartial(Context context, String tag) {
+ return wrap(createPartialInner(context, tag));
+ }
+
+ @VisibleForTesting
+ static PowerManager.WakeLock createPartialInner(Context context, String tag) {
+ return context.getSystemService(PowerManager.class)
+ .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, tag);
+ }
+
+ static WakeLock wrap(final PowerManager.WakeLock inner) {
+ return new WakeLock() {
+ /** @see PowerManager.WakeLock#acquire() */
+ public void acquire() {
+ inner.acquire();
+ }
+
+ /** @see PowerManager.WakeLock#release() */
+ public void release() {
+ inner.release();
+ }
+
+ /** @see PowerManager.WakeLock#wrap(Runnable) */
+ public Runnable wrap(Runnable runnable) {
+ return inner.wrap(runnable);
+ }
+ };
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index 41b75ff..612a54a 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -36,6 +36,7 @@
<uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
<uses-permission android:name="android.permission.REQUEST_NETWORK_SCORES" />
<uses-permission android:name="android.permission.CONTROL_VPN" />
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java
new file mode 100644
index 0000000..5477afa8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.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 com.android.systemui.doze;
+
+import static org.junit.Assert.assertFalse;
+
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.hardware.AmbientDisplayConfiguration;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DozeConfigurationTest extends SysuiTestCase {
+
+ private AmbientDisplayConfiguration mDozeConfig;
+
+ @Before
+ public void setup() {
+ mDozeConfig = new AmbientDisplayConfiguration(mContext);
+ }
+
+ @Test
+ public void alwaysOn_offByDefault() throws Exception {
+ if (!mDozeConfig.alwaysOnAvailable()) {
+ return;
+ }
+
+ mContext.getSettingsProvider().acquireOverridesBuilder(this)
+ .addSetting("secure", Settings.Secure.DOZE_ALWAYS_ON, null)
+ .build();
+
+ assertFalse(mDozeConfig.alwaysOnEnabled(UserHandle.USER_CURRENT));
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index 0cccbe1..ba39671 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -28,8 +28,9 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -38,12 +39,12 @@
import static org.mockito.Mockito.when;
import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
import android.view.Display;
import com.android.systemui.SysUIRunner;
import com.android.systemui.UiThreadTest;
-import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.internal.hardware.AmbientDisplayConfiguration;
+import com.android.systemui.util.wakelock.WakeLockFake;
import org.junit.Before;
import org.junit.Test;
@@ -58,17 +59,17 @@
private DozeServiceFake mServiceFake;
private WakeLockFake mWakeLockFake;
- private DozeParameters mParamsMock;
+ private AmbientDisplayConfiguration mConfigMock;
private DozeMachine.Part mPartMock;
@Before
public void setUp() {
mServiceFake = new DozeServiceFake();
mWakeLockFake = new WakeLockFake();
- mParamsMock = mock(DozeParameters.class);
+ mConfigMock = mock(AmbientDisplayConfiguration.class);
mPartMock = mock(DozeMachine.Part.class);
- mMachine = new DozeMachine(mServiceFake, mParamsMock, mWakeLockFake);
+ mMachine = new DozeMachine(mServiceFake, mConfigMock, mWakeLockFake);
mMachine.setParts(new DozeMachine.Part[]{mPartMock});
}
@@ -82,7 +83,7 @@
@Test
public void testInitialize_goesToDoze() {
- when(mParamsMock.getAlwaysOn()).thenReturn(false);
+ when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(false);
mMachine.requestState(INITIALIZED);
@@ -92,7 +93,7 @@
@Test
public void testInitialize_goesToAod() {
- when(mParamsMock.getAlwaysOn()).thenReturn(true);
+ when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true);
mMachine.requestState(INITIALIZED);
@@ -102,7 +103,7 @@
@Test
public void testPulseDone_goesToDoze() {
- when(mParamsMock.getAlwaysOn()).thenReturn(false);
+ when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(false);
mMachine.requestState(INITIALIZED);
mMachine.requestState(DOZE_REQUEST_PULSE);
mMachine.requestState(DOZE_PULSING);
@@ -115,7 +116,7 @@
@Test
public void testPulseDone_goesToAoD() {
- when(mParamsMock.getAlwaysOn()).thenReturn(true);
+ when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true);
mMachine.requestState(INITIALIZED);
mMachine.requestState(DOZE_REQUEST_PULSE);
mMachine.requestState(DOZE_PULSING);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 7335af3..6424a0a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -16,19 +16,26 @@
package com.android.systemui.statusbar;
+import static android.support.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+import android.app.Instrumentation;
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.content.Context;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Looper;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.internal.runner.junit4.statement.UiThreadStatement;
import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.SmallTest;
import android.view.View;
import android.view.ViewGroup;
@@ -36,6 +43,7 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
+import com.android.systemui.util.wakelock.WakeLockFake;
import org.junit.Before;
import org.junit.Test;
@@ -54,9 +62,13 @@
private KeyguardIndicationTextView mDisclosure = mock(KeyguardIndicationTextView.class);
private KeyguardIndicationController mController;
+ private WakeLockFake mWakeLock;
+ private Instrumentation mInstrumentation;
@Before
public void setUp() throws Exception {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+
mContext.addMockSystemService(Context.DEVICE_POLICY_SERVICE, mDevicePolicyManager);
mContext.addMockSystemService(Context.TRUST_SERVICE, mock(TrustManager.class));
mContext.addMockSystemService(Context.FINGERPRINT_SERVICE, mock(FingerprintManager.class));
@@ -65,13 +77,15 @@
when(mIndicationArea.findViewById(R.id.keyguard_indication_enterprise_disclosure))
.thenReturn(mDisclosure);
+
+ mWakeLock = new WakeLockFake();
}
private void createController() {
if (Looper.myLooper() == null) {
Looper.prepare();
}
- mController = new KeyguardIndicationController(mContext, mIndicationArea, null);
+ mController = new KeyguardIndicationController(mContext, mIndicationArea, null, mWakeLock);
}
@Test
@@ -139,4 +153,45 @@
verify(mDisclosure).setVisibility(View.GONE);
verifyNoMoreInteractions(mDisclosure);
}
+
+ @Test
+ public void transientIndication_holdsWakeLock_whenDozing() {
+ createController();
+
+ mController.setDozing(true);
+ mController.showTransientIndication("Test");
+
+ assertTrue(mWakeLock.isHeld());
+ }
+
+ @Test
+ public void transientIndication_releasesWakeLock_afterHiding() {
+ createController();
+
+ mController.setDozing(true);
+ mController.showTransientIndication("Test");
+ mController.hideTransientIndication();
+
+ assertFalse(mWakeLock.isHeld());
+ }
+
+ @Test
+ public void transientIndication_releasesWakeLock_afterHidingDelayed() throws Throwable {
+ mInstrumentation.runOnMainSync(() -> {
+ createController();
+
+ mController.setDozing(true);
+ mController.showTransientIndication("Test");
+ mController.hideTransientIndicationDelayed(0);
+ });
+ mInstrumentation.waitForIdleSync();
+
+ boolean[] held = new boolean[2];
+ mInstrumentation.runOnMainSync(() -> {
+ held[0] = mWakeLock.isHeld();
+ held[1] = true;
+ });
+ assertFalse("wake lock still held", held[0]);
+ assertTrue("held was not written yet", held[1]);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java
new file mode 100644
index 0000000..08ac9a9
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.Manifest;
+import android.app.Notification;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.service.notification.StatusBarNotification;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NotificationDataTest extends SysuiTestCase {
+
+ private static final int UID_NORMAL = 123;
+ private static final int UID_ALLOW_DURING_SETUP = 456;
+
+ private final StatusBarNotification mMockStatusBarNotification =
+ mock(StatusBarNotification.class);
+
+ private final IPackageManager mMockPackageManager = mock(IPackageManager.class);
+
+ @Before
+ public void setUp() throws Exception {
+ when(mMockStatusBarNotification.getUid()).thenReturn(UID_NORMAL);
+
+ when(mMockPackageManager.checkUidPermission(
+ eq(Manifest.permission.NOTIFICATION_DURING_SETUP),
+ eq(UID_NORMAL)))
+ .thenReturn(PackageManager.PERMISSION_DENIED);
+ when(mMockPackageManager.checkUidPermission(
+ eq(Manifest.permission.NOTIFICATION_DURING_SETUP),
+ eq(UID_ALLOW_DURING_SETUP)))
+ .thenReturn(PackageManager.PERMISSION_GRANTED);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testShowNotificationEvenIfUnprovisioned_FalseIfNoExtra() {
+ initStatusBarNotification(false);
+ when(mMockStatusBarNotification.getUid()).thenReturn(UID_ALLOW_DURING_SETUP);
+
+ assertFalse(
+ NotificationData.showNotificationEvenIfUnprovisioned(
+ mMockPackageManager,
+ mMockStatusBarNotification));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testShowNotificationEvenIfUnprovisioned_FalseIfNoPermission() {
+ initStatusBarNotification(true);
+
+ assertFalse(
+ NotificationData.showNotificationEvenIfUnprovisioned(
+ mMockPackageManager,
+ mMockStatusBarNotification));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testShowNotificationEvenIfUnprovisioned_TrueIfHasPermissionAndExtra() {
+ initStatusBarNotification(true);
+ when(mMockStatusBarNotification.getUid()).thenReturn(UID_ALLOW_DURING_SETUP);
+
+ assertTrue(
+ NotificationData.showNotificationEvenIfUnprovisioned(
+ mMockPackageManager,
+ mMockStatusBarNotification));
+ }
+
+ private void initStatusBarNotification(boolean allowDuringSetup) {
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, allowDuringSetup);
+ Notification notification = new Notification.Builder(mContext, "test")
+ .addExtras(bundle)
+ .build();
+ when(mMockStatusBarNotification.getNotification()).thenReturn(notification);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
index 96dbdb3..c91b269 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -42,12 +42,6 @@
}
public ExpandableNotificationRow createRow() {
- LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
- mContext.LAYOUT_INFLATER_SERVICE);
- ExpandableNotificationRow row = (ExpandableNotificationRow) inflater.inflate(
- R.layout.status_bar_notification_row,
- null, false);
- row.setGroupManager(mGroupManager);
Notification publicVersion = new Notification.Builder(mContext).setSmallIcon(
R.drawable.ic_person)
.setCustomContentView(new RemoteViews(mContext.getPackageName(),
@@ -59,6 +53,16 @@
.setContentText("Text")
.setPublicVersion(publicVersion)
.build();
+ return createRow(notification);
+ }
+
+ public ExpandableNotificationRow createRow(Notification notification) {
+ LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+ mContext.LAYOUT_INFLATER_SERVICE);
+ ExpandableNotificationRow row = (ExpandableNotificationRow) inflater.inflate(
+ R.layout.status_bar_notification_row,
+ null, false);
+ row.setGroupManager(mGroupManager);
UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
StatusBarNotification sbn = new StatusBarNotification("com.android.systemui",
"com.android.systemui", mId++, null, 1000,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationinflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationinflaterTest.java
new file mode 100644
index 0000000..0ec9c10
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationinflaterTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import static com.android.systemui.statusbar.notification.NotificationInflater.FLAG_REINFLATE_ALL;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.app.Notification;
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.NotificationTestHelper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NotificationinflaterTest {
+
+ private Context mContext;
+ private NotificationInflater mNotificationInflater;
+ private Notification.Builder mBuilder;
+
+ @Before
+ @UiThreadTest
+ public void setUp() {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mBuilder = new Notification.Builder(mContext).setSmallIcon(
+ R.drawable.ic_person)
+ .setContentTitle("Title")
+ .setContentText("Text");
+ ExpandableNotificationRow row = new NotificationTestHelper(mContext).createRow(
+ mBuilder.build());
+ mNotificationInflater = new NotificationInflater(row);
+ }
+
+ @Test
+ public void testIncreasedHeadsUpBeingUsed() {
+ mNotificationInflater.setUsesIncreasedHeadsUpHeight(true);
+ Notification.Builder builder = spy(mBuilder);
+ mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext);
+ verify(builder).createHeadsUpContentView(true);
+ }
+
+ @Test
+ public void testIncreasedHeightBeingUsed() {
+ mNotificationInflater.setUsesIncreasedHeight(true);
+ Notification.Builder builder = spy(mBuilder);
+ mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext);
+ verify(builder).createContentView(true);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 09f6b55..f48af75 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -23,7 +23,6 @@
import static org.mockito.Mockito.when;
import android.metrics.LogMaker;
-import android.support.test.filters.FlakyTest;
import android.support.test.filters.SmallTest;
import android.support.test.metricshelper.MetricsAsserts;
import android.support.test.runner.AndroidJUnit4;
@@ -40,7 +39,6 @@
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -65,7 +63,8 @@
mStackScroller = mock(NotificationStackScrollLayout.class);
mMetricsLogger = new FakeMetricsLogger();
mStatusBar = new TestableStatusBar(mStatusBarKeyguardViewManager, mUnlockMethodCache,
- mKeyguardIndicationController, mStackScroller, mMetricsLogger);
+ mKeyguardIndicationController, mStackScroller);
+ mStatusBar.setMetricsLogger(mMetricsLogger);
doAnswer(invocation -> {
OnDismissAction onDismissAction = (OnDismissAction) invocation.getArguments()[0];
@@ -106,8 +105,6 @@
mStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false);
}
- @Ignore("flaky test")
- @FlakyTest
@Test
public void lockscreenStateMetrics_notShowing() {
// uninteresting state, except that fingerprint must be non-zero
@@ -126,8 +123,6 @@
.setSubtype(0));
}
- @Ignore("flaky test")
- @FlakyTest
@Test
public void lockscreenStateMetrics_notShowing_secure() {
// uninteresting state, except that fingerprint must be non-zero
@@ -147,8 +142,6 @@
.setSubtype(1));
}
- @Ignore("flaky test")
- @FlakyTest
@Test
public void lockscreenStateMetrics_isShowing() {
// uninteresting state, except that fingerprint must be non-zero
@@ -168,8 +161,6 @@
.setSubtype(0));
}
- @Ignore("flaky test")
- @FlakyTest
@Test
public void lockscreenStateMetrics_isShowing_secure() {
// uninteresting state, except that fingerprint must be non-zero
@@ -189,8 +180,6 @@
.setSubtype(1));
}
- @Ignore("flaky test")
- @FlakyTest
@Test
public void lockscreenStateMetrics_isShowingBouncer() {
// uninteresting state, except that fingerprint must be non-zero
@@ -210,8 +199,6 @@
.setSubtype(1));
}
- @Ignore("flaky test")
- @FlakyTest
@Test
public void onActivatedMetrics() {
ActivatableNotificationView view = mock(ActivatableNotificationView.class);
@@ -226,12 +213,11 @@
static class TestableStatusBar extends StatusBar {
public TestableStatusBar(StatusBarKeyguardViewManager man,
UnlockMethodCache unlock, KeyguardIndicationController key,
- NotificationStackScrollLayout stack, MetricsLogger logger) {
+ NotificationStackScrollLayout stack) {
mStatusBarKeyguardViewManager = man;
mUnlockMethodCache = unlock;
mKeyguardIndicationController = key;
mStackScroller = stack;
- mMetricsLogger = logger;
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/SettableWakeLockTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/SettableWakeLockTest.java
new file mode 100644
index 0000000..f6692eb
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/SettableWakeLockTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.util.wakelock;
+
+import static junit.framework.TestCase.assertTrue;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SettableWakeLockTest {
+
+ private WakeLockFake mFake;
+ private SettableWakeLock mSettable;
+
+ @Before
+ public void setup() {
+ mFake = new WakeLockFake();
+ mSettable = new SettableWakeLock(mFake);
+ }
+
+ @Test
+ public void setAcquire_true_acquires() throws Exception {
+ mSettable.setAcquired(true);
+ assertTrue(mFake.isHeld());
+ assertEquals(mFake.isHeld(), mSettable.isAcquired());
+ }
+
+ @Test
+ public void setAcquire_false_releases() throws Exception {
+ mSettable.setAcquired(true);
+ mSettable.setAcquired(false);
+ assertFalse(mFake.isHeld());
+ assertEquals(mFake.isHeld(), mSettable.isAcquired());
+ }
+
+ @Test
+ public void setAcquire_true_multipleTimes_isIdempotent() throws Exception {
+ mSettable.setAcquired(true);
+ mSettable.setAcquired(true);
+ mSettable.setAcquired(true);
+ mSettable.setAcquired(false);
+ assertFalse(mFake.isHeld());
+ assertEquals(mFake.isHeld(), mSettable.isAcquired());
+ }
+
+ @Test
+ public void setAcquire_false_multipleTimes_idempotent() throws Exception {
+ mSettable.setAcquired(true);
+ mSettable.setAcquired(false);
+ mSettable.setAcquired(false);
+ assertFalse(mFake.isHeld());
+ assertEquals(mFake.isHeld(), mSettable.isAcquired());
+ }
+
+ @Test
+ public void setAcquire_false_multipleTimes_idempotent_again() throws Exception {
+ mSettable.setAcquired(true);
+ mSettable.setAcquired(false);
+ mSettable.setAcquired(false);
+ mSettable.setAcquired(true);
+ assertTrue(mFake.isHeld());
+ assertEquals(mFake.isHeld(), mSettable.isAcquired());
+ }
+
+
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/WakeLockFake.java b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockFake.java
similarity index 82%
rename from packages/SystemUI/tests/src/com/android/systemui/doze/WakeLockFake.java
rename to packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockFake.java
index 7c04fe2..4cefb99 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/WakeLockFake.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockFake.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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.
@@ -11,21 +11,17 @@
* 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.
+ * limitations under the License
*/
-package com.android.systemui.doze;
+package com.android.systemui.util.wakelock;
import com.android.internal.util.Preconditions;
-public class WakeLockFake extends DozeFactory.WakeLock {
+public class WakeLockFake implements WakeLock {
private int mAcquired = 0;
- public WakeLockFake() {
- super(null);
- }
-
@Override
public void acquire() {
mAcquired++;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java
new file mode 100644
index 0000000..5394499
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.util.wakelock;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.os.PowerManager;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class WakeLockTest {
+
+ WakeLock mWakeLock;
+ PowerManager.WakeLock mInner;
+
+ @Before
+ public void setUp() {
+ Context context = InstrumentationRegistry.getContext();
+
+ mInner = WakeLock.createPartialInner(context, WakeLockTest.class.getName());
+ mWakeLock = WakeLock.wrap(mInner);
+ }
+
+ @After
+ public void tearDown() {
+ mInner.setReferenceCounted(false);
+ mInner.release();
+ }
+
+ @Test
+ public void createPartialInner_notHeldYet() {
+ assertFalse(mInner.isHeld());
+ }
+
+ @Test
+ public void wakeLock_acquire() {
+ mWakeLock.acquire();
+ assertTrue(mInner.isHeld());
+ }
+
+ @Test
+ public void wakeLock_release() {
+ mWakeLock.acquire();
+ mWakeLock.release();
+ assertFalse(mInner.isHeld());
+ }
+
+ @Test
+ public void wakeLock_refCounted() {
+ mWakeLock.acquire();
+ mWakeLock.acquire();
+ mWakeLock.release();
+ assertTrue(mInner.isHeld());
+ }
+
+ @Test
+ public void wakeLock_wrap() {
+ boolean[] ran = new boolean[1];
+
+ Runnable wrapped = mWakeLock.wrap(() -> {
+ ran[0] = true;
+ });
+
+ assertTrue(mInner.isHeld());
+ assertFalse(ran[0]);
+
+ wrapped.run();
+
+ assertTrue(ran[0]);
+ assertFalse(mInner.isHeld());
+ }
+}
\ No newline at end of file
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index c45de0d..42446d1 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3175,7 +3175,7 @@
DIALOG_SUPPORT_SYSTEM_INFORMATION = 756;
// These values should never appear in log outputs - they are reserved for
- // internal Tron use.
+ // internal platform metrics use.
RESERVED_FOR_LOGBUILDER_CATEGORY = 757;
RESERVED_FOR_LOGBUILDER_TYPE = 758;
RESERVED_FOR_LOGBUILDER_SUBTYPE = 759;
@@ -3282,7 +3282,7 @@
DEFAULT_AUTOFILL_PICKER = 792;
// These values should never appear in log outputs - they are reserved for
- // internal Tron use.
+ // internal platform metrics use.
NOTIFICATION_SINCE_CREATE_MILLIS = 793;
NOTIFICATION_SINCE_VISIBLE_MILLIS = 794;
NOTIFICATION_SINCE_UPDATE_MILLIS = 795;
@@ -3297,7 +3297,7 @@
QS_NFC = 800;
// These values should never appear in log outputs - they are reserved for
- // internal Tron use.
+ // internal platform metrics use.
RESERVED_FOR_LOGBUILDER_BUCKET = 801;
RESERVED_FOR_LOGBUILDER_VALUE = 802;
RESERVED_FOR_LOGBUILDER_COUNTER = 803;
@@ -3540,6 +3540,10 @@
// OS: N
ACTION_GET_CONTACT = 864;
+ // This values should never appear in log outputs - it is reserved for
+ // internal platform metrics use.
+ RESERVED_FOR_LOGBUILDER_PID = 865;
+
// ---- End O Constants, all O constants go above this line ----
// Add new aosp constants above this line.
diff --git a/rs/jni/Android.mk b/rs/jni/Android.mk
index 447a47d..4040db3 100644
--- a/rs/jni/Android.mk
+++ b/rs/jni/Android.mk
@@ -5,6 +5,7 @@
android_renderscript_RenderScript.cpp
LOCAL_SHARED_LIBRARIES := \
+ libandroid \
libandroid_runtime \
libandroidfw \
libnativehelper \
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 2300da3..b4630ef 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -34,6 +34,8 @@
#include "android_runtime/android_view_Surface.h"
#include "android_runtime/android_util_AssetManager.h"
#include "android/graphics/GraphicsJNI.h"
+#include "android/native_window.h"
+#include "android/native_window_jni.h"
#include <rsEnv.h>
#include <rsApiStubs.h>
@@ -1264,10 +1266,10 @@
ALOGD("nAllocationGetSurface, con(%p), a(%p)", (RsContext)con, (RsAllocation)a);
}
- IGraphicBufferProducer *v = (IGraphicBufferProducer *)rsAllocationGetSurface((RsContext)con,
- (RsAllocation)a);
- sp<IGraphicBufferProducer> bp = v;
- v->decStrong(nullptr);
+ ANativeWindow *anw = (ANativeWindow *)rsAllocationGetSurface((RsContext)con, (RsAllocation)a);
+
+ sp<Surface> surface(static_cast<Surface*>(anw));
+ sp<IGraphicBufferProducer> bp = surface->getIGraphicBufferProducer();
jobject o = android_view_Surface_createFromIGraphicBufferProducer(_env, bp);
return o;
@@ -1281,13 +1283,12 @@
(RsAllocation)alloc, (Surface *)sur);
}
- sp<Surface> s;
+ ANativeWindow *anw = nullptr;
if (sur != 0) {
- s = android_view_Surface_getSurface(_env, sur);
+ anw = ANativeWindow_fromSurface(_env, sur);
}
- rsAllocationSetSurface((RsContext)con, (RsAllocation)alloc,
- static_cast<ANativeWindow *>(s.get()));
+ rsAllocationSetSurface((RsContext)con, (RsAllocation)alloc, anw);
}
static void
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 44afe1d..e0d7806 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -82,6 +82,7 @@
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MagnificationSpec;
+import android.view.View;
import android.view.WindowInfo;
import android.view.WindowManager;
import android.view.WindowManagerInternal;
@@ -97,6 +98,7 @@
import android.view.accessibility.IAccessibilityManagerClient;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.SomeArgs;
import com.android.server.LocalServices;
@@ -149,6 +151,9 @@
private static final String GET_WINDOW_TOKEN = "getWindowToken";
+ private static final String SET_PIP_ACTION_REPLACEMENT =
+ "setPictureInPictureActionReplacingConnection";
+
private static final ComponentName sFakeAccessibilityServiceComponentName =
new ComponentName("foo.bar", "FakeService");
@@ -158,8 +163,6 @@
private static final int OWN_PROCESS_ID = android.os.Process.myPid();
- private static final int WINDOW_ID_UNKNOWN = -1;
-
// Each service has an ID. Also provide one for magnification gesture handling
public static final int MAGNIFICATION_GESTURE_HANDLER_ID = 0;
@@ -220,6 +223,8 @@
private final SparseArray<AccessibilityConnectionWrapper> mGlobalInteractionConnections =
new SparseArray<>();
+ private AccessibilityConnectionWrapper mPictureInPictureActionReplacingConnection;
+
private final SparseArray<IBinder> mGlobalWindowTokens = new SparseArray<>();
private final SparseArray<UserState> mUserStates = new SparseArray<>();
@@ -465,6 +470,25 @@
boolean dispatchEvent = false;
synchronized (mLock) {
+ if (event.getWindowId() ==
+ AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID) {
+ // The replacer window isn't shown to services. Move its events into the pip.
+ AccessibilityWindowInfo pip = mSecurityPolicy.getPictureInPictureWindow();
+ if (pip != null) {
+ int pipId = pip.getId();
+ event.setWindowId(pipId);
+ event.setSealed(true);
+ AccessibilityNodeInfo info = event.getSource();
+ info.setSealed(false);
+ event.setSealed(false);
+ if (info != null) {
+ info.setSourceNodeId(info.getSourceNodeId(), pipId);
+ event.setSource(info);
+ info.recycle();
+ }
+ }
+ }
+
// We treat calls from a profile as if made by its parent as profiles
// share the accessibility state of the parent. The call below
// performs the current profile parent resolution..
@@ -694,6 +718,27 @@
}
@Override
+ public void setPictureInPictureActionReplacingConnection(
+ IAccessibilityInteractionConnection connection) throws RemoteException {
+ mSecurityPolicy.enforceCallingPermission(Manifest.permission.MODIFY_ACCESSIBILITY_DATA,
+ SET_PIP_ACTION_REPLACEMENT);
+ synchronized (mLock) {
+ if (mPictureInPictureActionReplacingConnection != null) {
+ mPictureInPictureActionReplacingConnection.unlinkToDeath();
+ mPictureInPictureActionReplacingConnection = null;
+ }
+ if (connection != null) {
+ AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
+ AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID,
+ connection, UserHandle.USER_ALL);
+ mPictureInPictureActionReplacingConnection = wrapper;
+ wrapper.linkToDeath();
+ }
+ mSecurityPolicy.notifyWindowsChanged();
+ }
+ }
+
+ @Override
public void registerUiTestAutomationService(IBinder owner,
IAccessibilityServiceClient serviceClient,
AccessibilityServiceInfo accessibilityServiceInfo,
@@ -1293,9 +1338,10 @@
return false;
}
- if (event.getWindowId() != WINDOW_ID_UNKNOWN && !event.isImportantForAccessibility()
- && (service.mFetchFlags
- & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
+ if ((event.getWindowId() != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)
+ && !event.isImportantForAccessibility()
+ && (service.mFetchFlags & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS)
+ == 0) {
return false;
}
@@ -2035,6 +2081,7 @@
}
}
+ @GuardedBy("mLock")
private MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId) {
IBinder windowToken = mGlobalWindowTokens.get(windowId);
if (windowToken == null) {
@@ -2846,6 +2893,7 @@
final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
Region partialInteractiveRegion = Region.obtain();
+ MagnificationSpec spec;
synchronized (mLock) {
mUsesAccessibilityCache = true;
if (!isCalledForCurrentUserLocked()) {
@@ -2867,10 +2915,12 @@
partialInteractiveRegion.recycle();
partialInteractiveRegion = null;
}
+ spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
}
final int interrogatingPid = Binder.getCallingPid();
+ callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
+ interrogatingPid, interrogatingTid);
final long identityToken = Binder.clearCallingIdentity();
- MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
try {
connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName,
partialInteractiveRegion, interactionId, callback, mFetchFlags,
@@ -2898,6 +2948,7 @@
final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
Region partialInteractiveRegion = Region.obtain();
+ MagnificationSpec spec;
synchronized (mLock) {
mUsesAccessibilityCache = true;
if (!isCalledForCurrentUserLocked()) {
@@ -2919,10 +2970,12 @@
partialInteractiveRegion.recycle();
partialInteractiveRegion = null;
}
+ spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
}
final int interrogatingPid = Binder.getCallingPid();
+ callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
+ interrogatingPid, interrogatingTid);
final long identityToken = Binder.clearCallingIdentity();
- MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
try {
connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
partialInteractiveRegion, interactionId, callback, mFetchFlags,
@@ -2950,6 +3003,7 @@
final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
Region partialInteractiveRegion = Region.obtain();
+ MagnificationSpec spec;
synchronized (mLock) {
mUsesAccessibilityCache = true;
if (!isCalledForCurrentUserLocked()) {
@@ -2971,10 +3025,12 @@
partialInteractiveRegion.recycle();
partialInteractiveRegion = null;
}
+ spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
}
final int interrogatingPid = Binder.getCallingPid();
+ callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
+ interrogatingPid, interrogatingTid);
final long identityToken = Binder.clearCallingIdentity();
- MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
try {
connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId,
partialInteractiveRegion, interactionId, callback, mFetchFlags | flags,
@@ -3002,6 +3058,7 @@
final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
Region partialInteractiveRegion = Region.obtain();
+ MagnificationSpec spec;
synchronized (mLock) {
if (!isCalledForCurrentUserLocked()) {
return false;
@@ -3023,10 +3080,12 @@
partialInteractiveRegion.recycle();
partialInteractiveRegion = null;
}
+ spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
}
final int interrogatingPid = Binder.getCallingPid();
+ callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
+ interrogatingPid, interrogatingTid);
final long identityToken = Binder.clearCallingIdentity();
- MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
try {
connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion,
interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
@@ -3054,6 +3113,7 @@
final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
Region partialInteractiveRegion = Region.obtain();
+ MagnificationSpec spec;
synchronized (mLock) {
if (!isCalledForCurrentUserLocked()) {
return false;
@@ -3074,10 +3134,12 @@
partialInteractiveRegion.recycle();
partialInteractiveRegion = null;
}
+ spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
}
final int interrogatingPid = Binder.getCallingPid();
+ callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
+ interrogatingPid, interrogatingTid);
final long identityToken = Binder.clearCallingIdentity();
- MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
try {
connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion,
interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
@@ -3149,6 +3211,18 @@
if (connection == null) {
return false;
}
+ AccessibilityWindowInfo windowInfo =
+ mSecurityPolicy.findWindowById(resolvedWindowId);
+ if ((windowInfo != null) && windowInfo.inPictureInPicture()) {
+ boolean isA11yFocusAction =
+ (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS)
+ || (action ==
+ AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
+ if ((mPictureInPictureActionReplacingConnection != null)
+ && !isA11yFocusAction) {
+ connection = mPictureInPictureActionReplacingConnection.mConnection;
+ }
+ }
}
}
final int interrogatingPid = Binder.getCallingPid();
@@ -3562,7 +3636,7 @@
if (mSecurityPolicy.canRetrieveWindowContentLocked(this)) {
event.setConnectionId(mId);
} else {
- event.setSource(null);
+ event.setSource((View) null);
}
event.setSealed(true);
}
@@ -3790,17 +3864,17 @@
}
private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) {
- if (accessibilityWindowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) {
+ if (accessibilityWindowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) {
return mSecurityPolicy.getActiveWindowId();
}
return accessibilityWindowId;
}
private int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) {
- if (windowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) {
+ if (windowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) {
return mSecurityPolicy.mActiveWindowId;
}
- if (windowId == AccessibilityNodeInfo.ANY_WINDOW_ID) {
+ if (windowId == AccessibilityWindowInfo.ANY_WINDOW_ID) {
if (focusType == AccessibilityNodeInfo.FOCUS_INPUT) {
return mSecurityPolicy.mFocusedWindowId;
} else if (focusType == AccessibilityNodeInfo.FOCUS_ACCESSIBILITY) {
@@ -3810,6 +3884,20 @@
return windowId;
}
+ private IAccessibilityInteractionConnectionCallback replaceCallbackIfNeeded(
+ IAccessibilityInteractionConnectionCallback originalCallback,
+ int resolvedWindowId, int interactionId, int interrogatingPid,
+ long interrogatingTid) {
+ AccessibilityWindowInfo windowInfo = mSecurityPolicy.findWindowById(resolvedWindowId);
+ if ((windowInfo == null) || !windowInfo.inPictureInPicture()
+ || (mPictureInPictureActionReplacingConnection == null)) {
+ return originalCallback;
+ }
+ return new ActionReplacingCallback(originalCallback,
+ mPictureInPictureActionReplacingConnection.mConnection, interactionId,
+ interrogatingPid, interrogatingTid);
+ }
+
private final class InvocationHandler extends Handler {
public static final int MSG_ON_GESTURE = 1;
public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 2;
@@ -3960,6 +4048,7 @@
reportedWindow.setBoundsInScreen(window.boundsInScreen);
reportedWindow.setTitle(window.title);
reportedWindow.setAnchorId(window.accessibilityIdOfAnchor);
+ reportedWindow.setPictureInPicture(window.inPictureInPicture);
final int parentId = findWindowIdLocked(window.parentToken);
if (parentId >= 0) {
@@ -4157,7 +4246,9 @@
| AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED
| AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
+ // In Z order
public List<AccessibilityWindowInfo> mWindows;
+ public SparseArray<AccessibilityWindowInfo> mWindowsById = new SparseArray<>();
public int mActiveWindowId = INVALID_WINDOW_ID;
public int mFocusedWindowId = INVALID_WINDOW_ID;
@@ -4217,6 +4308,7 @@
for (int i = oldWindowCount - 1; i >= 0; i--) {
mWindows.remove(i).recycle();
}
+ mWindowsById.clear();
mFocusedWindowId = INVALID_WINDOW_ID;
if (!mTouchInteractionInProgress) {
@@ -4245,6 +4337,7 @@
}
}
mWindows.add(window);
+ mWindowsById.put(windowId, window);
}
if (mTouchInteractionInProgress && activeWindowGone) {
@@ -4306,7 +4399,7 @@
public void updateEventSourceLocked(AccessibilityEvent event) {
if ((event.getEventType() & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) {
- event.setSource(null);
+ event.setSource((View) null);
}
}
@@ -4446,7 +4539,7 @@
}
}
- private void notifyWindowsChanged() {
+ public void notifyWindowsChanged() {
if (mWindowsForAccessibilityCallback == null) {
return;
}
@@ -4560,11 +4653,15 @@
}
private AccessibilityWindowInfo findWindowById(int windowId) {
+ return mWindowsById.get(windowId);
+ }
+
+ private AccessibilityWindowInfo getPictureInPictureWindow() {
if (mWindows != null) {
final int windowCount = mWindows.size();
for (int i = 0; i < windowCount; i++) {
AccessibilityWindowInfo window = mWindows.get(i);
- if (window.getId() == windowId) {
+ if (window.inPictureInPicture()) {
return window;
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
new file mode 100644
index 0000000..0e30fb2
--- /dev/null
+++ b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
@@ -0,0 +1,229 @@
+/*
+ * 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.accessibility;
+
+import android.os.Binder;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.MagnificationSpec;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+import android.view.accessibility.IAccessibilityInteractionConnection;
+import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * If we are stripping and/or replacing the actions from a window, we need to intercept the
+ * nodes heading back to the service and swap out the actions.
+ */
+public class ActionReplacingCallback extends IAccessibilityInteractionConnectionCallback.Stub {
+ private static final boolean DEBUG = false;
+ private static final String LOG_TAG = "ActionReplacingCallback";
+
+ private final IAccessibilityInteractionConnectionCallback mServiceCallback;
+ private final IAccessibilityInteractionConnection mConnectionWithReplacementActions;
+ private final int mInteractionId;
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
+ List<AccessibilityNodeInfo> mNodesWithReplacementActions;
+
+ @GuardedBy("mLock")
+ List<AccessibilityNodeInfo> mNodesFromOriginalWindow;
+
+ @GuardedBy("mLock")
+ AccessibilityNodeInfo mNodeFromOriginalWindow;
+
+ // Keep track of whether or not we've been called back for a single node
+ @GuardedBy("mLock")
+ boolean mSingleNodeCallbackHappened;
+
+ // Keep track of whether or not we've been called back for multiple node
+ @GuardedBy("mLock")
+ boolean mMultiNodeCallbackHappened;
+
+ // We shouldn't get any more callbacks after we've called back the original service, but
+ // keep track to make sure we catch such strange things
+ @GuardedBy("mLock")
+ boolean mDone;
+
+ public ActionReplacingCallback(IAccessibilityInteractionConnectionCallback serviceCallback,
+ IAccessibilityInteractionConnection connectionWithReplacementActions,
+ int interactionId, int interrogatingPid, long interrogatingTid) {
+ mServiceCallback = serviceCallback;
+ mConnectionWithReplacementActions = connectionWithReplacementActions;
+ mInteractionId = interactionId;
+
+ // Request the root node of the replacing window
+ final long identityToken = Binder.clearCallingIdentity();
+ try {
+ mConnectionWithReplacementActions.findAccessibilityNodeInfoByAccessibilityId(
+ AccessibilityNodeInfo.ROOT_NODE_ID, null, interactionId + 1, this, 0,
+ interrogatingPid, interrogatingTid, null, null);
+ } catch (RemoteException re) {
+ if (DEBUG) {
+ Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
+ }
+ // Pretend we already got a (null) list of replacement nodes
+ mMultiNodeCallbackHappened = true;
+ } finally {
+ Binder.restoreCallingIdentity(identityToken);
+ }
+ }
+
+ @Override
+ public void setFindAccessibilityNodeInfoResult(AccessibilityNodeInfo info, int interactionId) {
+ boolean readyForCallback;
+ synchronized(mLock) {
+ if (interactionId == mInteractionId) {
+ mNodeFromOriginalWindow = info;
+ } else {
+ Slog.e(LOG_TAG, "Callback with unexpected interactionId");
+ throw new RuntimeException("Callback with unexpected interactionId"); // Remove
+ }
+
+ mSingleNodeCallbackHappened = true;
+ readyForCallback = mMultiNodeCallbackHappened;
+ }
+ if (readyForCallback) {
+ replaceInfoActionsAndCallService();
+ }
+ }
+
+ @Override
+ public void setFindAccessibilityNodeInfosResult(List<AccessibilityNodeInfo> infos,
+ int interactionId) {
+ boolean callbackForSingleNode;
+ boolean callbackForMultipleNodes;
+ synchronized(mLock) {
+ if (interactionId == mInteractionId) {
+ mNodesFromOriginalWindow = infos;
+ } else if (interactionId == mInteractionId + 1) {
+ mNodesWithReplacementActions = infos;
+ } else {
+ Slog.e(LOG_TAG, "Callback with unexpected interactionId");
+ throw new RuntimeException("Callback with unexpected interactionId"); // Remove
+ }
+ callbackForSingleNode = mSingleNodeCallbackHappened;
+ callbackForMultipleNodes = mMultiNodeCallbackHappened;
+ mMultiNodeCallbackHappened = true;
+ }
+ if (callbackForSingleNode) {
+ replaceInfoActionsAndCallService();
+ }
+ if (callbackForMultipleNodes) {
+ replaceInfosActionsAndCallService();
+ }
+ }
+
+ @Override
+ public void setPerformAccessibilityActionResult(boolean succeeded, int interactionId)
+ throws RemoteException {
+ // There's no reason to use this class when performing actions. Do something reasonable.
+ mServiceCallback.setPerformAccessibilityActionResult(succeeded, interactionId);
+ }
+
+ private void replaceInfoActionsAndCallService() {
+ final AccessibilityNodeInfo nodeToReturn;
+ synchronized (mLock) {
+ if (mDone) {
+ if (DEBUG) {
+ Slog.e(LOG_TAG, "Extra callback");
+ }
+ throw new RuntimeException("Extra callback"); // Replace with return before submit
+ }
+ if (mNodeFromOriginalWindow != null) {
+ replaceActionsOnInfoLocked(mNodeFromOriginalWindow);
+ }
+ recycleReplaceActionNodesLocked();
+ nodeToReturn = mNodeFromOriginalWindow;
+ mDone = true;
+ }
+ try {
+ mServiceCallback.setFindAccessibilityNodeInfoResult(nodeToReturn, mInteractionId);
+ } catch (RemoteException re) {
+ if (DEBUG) {
+ Slog.e(LOG_TAG, "Failed to setFindAccessibilityNodeInfoResult");
+ }
+ }
+ }
+
+ private void replaceInfosActionsAndCallService() {
+ final List<AccessibilityNodeInfo> nodesToReturn;
+ synchronized (mLock) {
+ if (mDone) {
+ if (DEBUG) {
+ Slog.e(LOG_TAG, "Extra callback");
+ }
+ throw new RuntimeException("Extra callback"); // Replace with return before submit
+ }
+ if (mNodesFromOriginalWindow != null) {
+ for (int i = 0; i < mNodesFromOriginalWindow.size(); i++) {
+ replaceActionsOnInfoLocked(mNodesFromOriginalWindow.get(i));
+ }
+ }
+ recycleReplaceActionNodesLocked();
+ nodesToReturn = mNodesFromOriginalWindow;
+ mDone = true;
+ }
+ try {
+ mServiceCallback.setFindAccessibilityNodeInfosResult(nodesToReturn, mInteractionId);
+ } catch (RemoteException re) {
+ if (DEBUG) {
+ Slog.e(LOG_TAG, "Failed to setFindAccessibilityNodeInfosResult");
+ }
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void replaceActionsOnInfoLocked(AccessibilityNodeInfo info) {
+ info.removeAllActions();
+ // We currently only replace actions for the root node
+ if ((info.getSourceNodeId() == AccessibilityNodeInfo.ROOT_NODE_ID)
+ && mNodesWithReplacementActions != null) {
+ // This list should always contain a single node with the root ID
+ for (int i = 0; i < mNodesWithReplacementActions.size(); i++) {
+ AccessibilityNodeInfo nodeWithReplacementActions =
+ mNodesWithReplacementActions.get(i);
+ if (nodeWithReplacementActions.getSourceNodeId()
+ == AccessibilityNodeInfo.ROOT_NODE_ID) {
+ List<AccessibilityAction> actions = nodeWithReplacementActions.getActionList();
+ if (actions != null) {
+ for (int j = 0; j < actions.size(); j++) {
+ info.addAction(actions.get(j));
+ }
+ // The PIP needs to be able to take accessibility focus
+ info.addAction(AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS);
+ info.addAction(AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
+ }
+ }
+ }
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void recycleReplaceActionNodesLocked() {
+ for (int i = mNodesWithReplacementActions.size() - 1; i >= 0; i--) {
+ AccessibilityNodeInfo nodeWithReplacementAction = mNodesWithReplacementActions.get(i);
+ nodeWithReplacementAction.recycle();
+ }
+ mNodesWithReplacementActions = null;
+ }
+}
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
index e943c4c..b90a2a2 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
@@ -17,7 +17,7 @@
package com.android.server.autofill;
import static android.Manifest.permission.MANAGE_AUTO_FILL;
-import static android.content.Context.AUTO_FILL_MANAGER_SERVICE;
+import static android.content.Context.AUTOFILL_MANAGER_SERVICE;
import static com.android.server.autofill.Helper.VERBOSE;
import android.Manifest;
@@ -45,8 +45,8 @@
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
-import android.view.autofill.AutoFillId;
-import android.view.autofill.AutoFillValue;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
import android.view.autofill.IAutoFillManager;
import android.view.autofill.IAutoFillManagerClient;
@@ -64,7 +64,7 @@
import java.util.List;
/**
- * Entry point service for auto-fill management.
+ * Entry point service for autofill management.
*
* <p>This service provides the {@link IAutoFillManager} implementation and keeps a list of
* {@link AutoFillManagerServiceImpl} per user; the real work is done by
@@ -91,8 +91,8 @@
* <p>
* Entries on this cache are added on demand and removed when:
* <ol>
- * <li>An auto-fill service app is removed.
- * <li>The {@link android.provider.Settings.Secure#AUTO_FILL_SERVICE} for an user change.\
+ * <li>An autofill service app is removed.
+ * <li>The {@link android.provider.Settings.Secure#AUTOFILL_SERVICE} for an user change.
* </ol>
*/
// TODO(b/33197203): Update the above comment
@@ -128,7 +128,7 @@
@Override
public void onStart() {
- publishBinderService(AUTO_FILL_MANAGER_SERVICE, new AutoFillManagerServiceStub());
+ publishBinderService(AUTOFILL_MANAGER_SERVICE, new AutoFillManagerServiceStub());
}
@Override
@@ -314,20 +314,20 @@
@Override
public void startSession(IBinder activityToken, IBinder windowToken, IBinder appCallback,
- AutoFillId autoFillId, Rect bounds, AutoFillValue value, int userId,
+ AutofillId autofillId, Rect bounds, AutofillValue value, int userId,
boolean hasCallback) {
// TODO(b/33197203): make sure it's called by resumed / focused activity
synchronized (mLock) {
final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
service.startSessionLocked(activityToken, windowToken, appCallback,
- autoFillId, bounds, value, hasCallback);
+ autofillId, bounds, value, hasCallback);
}
}
@Override
- public void updateSession(IBinder activityToken, AutoFillId id, Rect bounds,
- AutoFillValue value, int flags, int userId) {
+ public void updateSession(IBinder activityToken, AutofillId id, Rect bounds,
+ AutofillValue value, int flags, int userId) {
synchronized (mLock) {
final AutoFillManagerServiceImpl service = mServicesCache.get(
UserHandle.getCallingUserId());
@@ -389,7 +389,7 @@
super(handler);
ContentResolver resolver = mContext.getContentResolver();
resolver.registerContentObserver(Settings.Secure.getUriFor(
- Settings.Secure.AUTO_FILL_SERVICE), false, this, UserHandle.USER_ALL);
+ Settings.Secure.AUTOFILL_SERVICE), false, this, UserHandle.USER_ALL);
}
@Override
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
index aa0840c..e691623 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
@@ -16,13 +16,13 @@
package com.android.server.autofill;
-import static android.service.autofill.AutoFillService.EXTRA_ACTIVITY_TOKEN;
+import static android.service.autofill.AutofillService.EXTRA_ACTIVITY_TOKEN;
import static android.service.voice.VoiceInteractionSession.KEY_RECEIVER_EXTRAS;
import static android.service.voice.VoiceInteractionSession.KEY_STRUCTURE;
-import static android.view.autofill.AutoFillManager.FLAG_FOCUS_GAINED;
-import static android.view.autofill.AutoFillManager.FLAG_FOCUS_LOST;
-import static android.view.autofill.AutoFillManager.FLAG_START_SESSION;
-import static android.view.autofill.AutoFillManager.FLAG_VALUE_CHANGED;
+import static android.view.autofill.AutofillManager.FLAG_FOCUS_GAINED;
+import static android.view.autofill.AutofillManager.FLAG_FOCUS_LOST;
+import static android.view.autofill.AutofillManager.FLAG_START_SESSION;
+import static android.view.autofill.AutofillManager.FLAG_VALUE_CHANGED;
import static com.android.server.autofill.Helper.DEBUG;
import static com.android.server.autofill.Helper.VERBOSE;
@@ -51,8 +51,8 @@
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.provider.Settings;
-import android.service.autofill.AutoFillService;
-import android.service.autofill.AutoFillServiceInfo;
+import android.service.autofill.AutofillService;
+import android.service.autofill.AutofillServiceInfo;
import android.service.autofill.Dataset;
import android.service.autofill.FillResponse;
import android.service.autofill.IAutoFillService;
@@ -62,10 +62,9 @@
import android.util.LocalLog;
import android.util.PrintWriterPrinter;
import android.util.Slog;
-import android.view.autofill.AutoFillId;
-import android.view.autofill.AutoFillManager;
-import android.view.autofill.AutoFillValue;
-
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillManager;
+import android.view.autofill.AutofillValue;
import android.view.autofill.IAutoFillManagerClient;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.HandlerCaller;
@@ -94,7 +93,7 @@
private final AutoFillUI mUi;
private RemoteCallbackList<IAutoFillManagerClient> mClients;
- private AutoFillServiceInfo mInfo;
+ private AutofillServiceInfo mInfo;
private final LocalLog mRequestsHistory;
@@ -114,7 +113,7 @@
/**
* Cache of pending {@link Session}s, keyed by {@code activityToken}.
*
- * <p>They're kept until the {@link AutoFillService} finished handling a request, an error
+ * <p>They're kept until the {@link AutofillService} finished handling a request, an error
* occurs, or the session times out.
*/
// TODO(b/33197203): need to make sure service is bound while callback is pending and/or
@@ -205,21 +204,21 @@
ComponentName serviceComponent = null;
ServiceInfo serviceInfo = null;
final String componentName = Settings.Secure.getStringForUser(
- mContext.getContentResolver(), Settings.Secure.AUTO_FILL_SERVICE, mUserId);
+ mContext.getContentResolver(), Settings.Secure.AUTOFILL_SERVICE, mUserId);
if (!TextUtils.isEmpty(componentName)) {
try {
serviceComponent = ComponentName.unflattenFromString(componentName);
serviceInfo = AppGlobals.getPackageManager().getServiceInfo(serviceComponent,
0, mUserId);
} catch (RuntimeException | RemoteException e) {
- Slog.e(TAG, "Bad auto-fill service name " + componentName + ": " + e);
+ Slog.e(TAG, "Bad autofill service name " + componentName + ": " + e);
return;
}
}
try {
final boolean hadService = hasService();
if (serviceInfo != null) {
- mInfo = new AutoFillServiceInfo(mContext.getPackageManager(),
+ mInfo = new AutofillServiceInfo(mContext.getPackageManager(),
serviceComponent, mUserId);
} else {
mInfo = null;
@@ -236,7 +235,7 @@
sendStateToClients();
}
} catch (PackageManager.NameNotFoundException e) {
- Slog.e(TAG, "Bad auto-fill service name " + componentName + ": " + e);
+ Slog.e(TAG, "Bad autofill service name " + componentName + ": " + e);
}
}
@@ -285,14 +284,15 @@
}
void startSessionLocked(IBinder activityToken, IBinder windowToken, IBinder appCallbackToken,
- AutoFillId autoFillId, Rect bounds, AutoFillValue value, boolean hasCallback) {
+ AutofillId autofillId, Rect bounds, AutofillValue value, boolean hasCallback) {
if (!hasService()) {
return;
}
final String historyItem = "s=" + mInfo.getServiceInfo().packageName
+ " u=" + mUserId + " a=" + activityToken
- + " i=" + autoFillId + " b=" + bounds + " hc=" + hasCallback;
+
+ + " i=" + autofillId + " b=" + bounds + " hc=" + hasCallback;
mRequestsHistory.log(historyItem);
// TODO(b/33197203): Handle partitioning
@@ -304,7 +304,7 @@
final Session newSession = createSessionByTokenLocked(activityToken,
windowToken, appCallbackToken, hasCallback);
- newSession.updateLocked(autoFillId, bounds, value, FLAG_START_SESSION);
+ newSession.updateLocked(autofillId, bounds, value, FLAG_START_SESSION);
}
void finishSessionLocked(IBinder activityToken) {
@@ -340,9 +340,9 @@
receiverExtras.putBinder(EXTRA_ACTIVITY_TOKEN, activityToken);
final long identity = Binder.clearCallingIdentity();
try {
- if (!ActivityManager.getService().requestAutoFillData(mAssistReceiver,
+ if (!ActivityManager.getService().requestAutofillData(mAssistReceiver,
receiverExtras, activityToken)) {
- Slog.w(TAG, "failed to request auto-fill data for " + activityToken);
+ Slog.w(TAG, "failed to request autofill data for " + activityToken);
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -353,8 +353,8 @@
return newSession;
}
- void updateSessionLocked(IBinder activityToken, AutoFillId autoFillId, Rect bounds,
- AutoFillValue value, int flags) {
+ 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) {
@@ -364,7 +364,7 @@
return;
}
- session.updateLocked(autoFillId, bounds, value, flags);
+ session.updateLocked(autofillId, bounds, value, flags);
}
private void handleSessionSave(IBinder activityToken) {
@@ -463,7 +463,7 @@
}
/**
- * State for a given view with a AutoFillId.
+ * State for a given view with a AutofillId.
*
* <p>This class holds state about a view and calls its listener when the fill UI is ready to
* be displayed for the view.
@@ -474,10 +474,10 @@
* Called when the fill UI is ready to be shown for this view.
*/
void onFillReady(ViewState viewState, FillResponse fillResponse, Rect bounds,
- AutoFillId focusedId, @Nullable AutoFillValue value);
+ AutofillId focusedId, @Nullable AutofillValue value);
}
- final AutoFillId mId;
+ final AutofillId mId;
private final Listener mListener;
// TODO(b/33197203): would not need a reference to response and session if it was an inner
// class of Session...
@@ -486,12 +486,12 @@
FillResponse mResponse;
Intent mAuthIntent;
- private AutoFillValue mAutoFillValue;
+ private AutofillValue mAutofillValue;
private Rect mBounds;
private boolean mValueUpdated;
- ViewState(Session session, AutoFillId id, Listener listener) {
+ ViewState(Session session, AutofillId id, Listener listener) {
mSession = session;
mId = id;
mListener = listener;
@@ -520,9 +520,9 @@
// TODO(b/33197203): need to refactor / rename / document this method to make it clear that
// it can change the value and update the UI; similarly, should replace code that
// directly sets mAutoFilLValue to use encapsulation.
- void update(@Nullable AutoFillValue autoFillValue, @Nullable Rect bounds) {
- if (autoFillValue != null) {
- mAutoFillValue = autoFillValue;
+ void update(@Nullable AutofillValue autofillValue, @Nullable Rect bounds) {
+ if (autofillValue != null) {
+ mAutofillValue = autofillValue;
}
if (bounds != null) {
mBounds = bounds;
@@ -533,25 +533,25 @@
/**
* Calls {@link
- * Listener#onFillReady(ViewState, FillResponse, Rect, AutoFillId, AutoFillValue)} if the
+ * Listener#onFillReady(ViewState, FillResponse, Rect, AutofillId, AutofillValue)} if the
* fill UI is ready to be displayed (i.e. when response and bounds are set).
*/
void maybeCallOnFillReady() {
if (mResponse != null && (mResponse.getAuthentication() != null
|| mResponse.getDatasets() != null) && mBounds != null) {
- mListener.onFillReady(this, mResponse, mBounds, mId, mAutoFillValue);
+ mListener.onFillReady(this, mResponse, mBounds, mId, mAutofillValue);
}
}
@Override
public String toString() {
- return "ViewState: [id=" + mId + ", value=" + mAutoFillValue + ", bounds=" + mBounds
+ return "ViewState: [id=" + mId + ", value=" + mAutofillValue + ", bounds=" + mBounds
+ ", updated = " + mValueUpdated + "]";
}
void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("id:" ); pw.println(mId);
- pw.print(prefix); pw.print("value:" ); pw.println(mAutoFillValue);
+ pw.print(prefix); pw.print("value:" ); pw.println(mAutofillValue);
pw.print(prefix); pw.print("updated:" ); pw.println(mValueUpdated);
pw.print(prefix); pw.print("bounds:" ); pw.println(mBounds);
pw.print(prefix); pw.print("authIntent:" ); pw.println(mAuthIntent);
@@ -564,7 +564,7 @@
* <p>This class manages the multiple {@link ViewState}s for each view it has, and keeps track
* of the current {@link ViewState} to display the appropriate UI.
*
- * <p>Although the auto-fill requests and callbacks are stateless from the service's point of
+ * <p>Although the autofill requests and callbacks are stateless from the service's point of
* view, we need to keep state in the framework side for cases such as authentication. For
* example, when service return a {@link FillResponse} that contains all the fields needed
* to fill the activity but it requires authentication first, that response need to be held
@@ -580,7 +580,7 @@
private final IBinder mWindowToken;
@GuardedBy("mLock")
- private final Map<AutoFillId, ViewState> mViewStates = new ArrayMap<>();
+ private final Map<AutofillId, ViewState> mViewStates = new ArrayMap<>();
@GuardedBy("mLock")
@Nullable
@@ -604,7 +604,7 @@
/**
* Assist structure sent by the app; it will be updated (sanitized, change values for save)
- * before sent to {@link AutoFillService}.
+ * before sent to {@link AutofillService}.
*/
@GuardedBy("mLock")
private AssistStructure mStructure;
@@ -692,11 +692,11 @@
try {
final String autoFillService = Settings.Secure.getStringForUser(
mContext.getContentResolver(),
- Settings.Secure.AUTO_FILL_SERVICE, mUserId);
+ Settings.Secure.AUTOFILL_SERVICE, mUserId);
if (mInfo.getServiceInfo().getComponentName().equals(
ComponentName.unflattenFromString(autoFillService))) {
Settings.Secure.putStringForUser(mContext.getContentResolver(),
- Settings.Secure.AUTO_FILL_SERVICE, null, mUserId);
+ Settings.Secure.AUTOFILL_SERVICE, null, mUserId);
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -738,7 +738,7 @@
// AutoFillUiCallback
@Override
- public void onEvent(AutoFillId id, int event) {
+ public void onEvent(AutofillId id, int event) {
mHandlerCaller.getHandler().post(() -> {
notifyChangeToClient(id, event);
});
@@ -749,7 +749,7 @@
removeSelf();
} else {
Parcelable result = data.getParcelable(
- AutoFillManager.EXTRA_AUTHENTICATION_RESULT);
+ AutofillManager.EXTRA_AUTHENTICATION_RESULT);
if (result instanceof FillResponse) {
mCurrentResponse = (FillResponse) result;
processResponseLocked(mCurrentResponse);
@@ -777,7 +777,7 @@
}
if (mCurrentResponse == null) {
// Happens when the activity / session was finished before the service replied, or
- // when the service cannot auto-fill it (and returned a null response).
+ // when the service cannot autofill it (and returned a null response).
if (DEBUG) {
Slog.d(TAG, "showSaveLocked(): no mCurrentResponse");
}
@@ -795,16 +795,16 @@
final int size = saveInfo.getSavableIds().size();
for (int i = 0; i < size; i++) {
- final AutoFillId id = saveInfo.getSavableIds().valueAt(i);
+ final AutofillId id = saveInfo.getSavableIds().valueAt(i);
final ViewState state = mViewStates.get(id);
if (state != null && state.mValueUpdated) {
- final AutoFillValue filledValue = findValue(mAutoFilledDataset, id);
- if (state.mAutoFillValue == null || state.mAutoFillValue.equals(filledValue)) {
+ final AutofillValue filledValue = findValue(mAutoFilledDataset, id);
+ if (state.mAutofillValue == null || state.mAutofillValue.equals(filledValue)) {
continue;
}
if (DEBUG) {
Slog.d(TAG, "finishSessionLocked(): found a change on " + id + ": "
- + state.mAutoFillValue);
+ + state.mAutofillValue);
}
getUiForShowing().showSaveUi(
mInfo.getServiceInfo().loadLabel(mContext.getPackageManager()),
@@ -829,15 +829,15 @@
final Bundle extras = this.mCurrentResponse.getExtras();
- for (Entry<AutoFillId, ViewState> entry : mViewStates.entrySet()) {
- final AutoFillValue value = entry.getValue().mAutoFillValue;
+ for (Entry<AutofillId, ViewState> entry : mViewStates.entrySet()) {
+ final AutofillValue value = entry.getValue().mAutofillValue;
if (value == null) {
if (VERBOSE) {
Slog.v(TAG, "callSaveLocked(): skipping " + entry.getKey());
}
continue;
}
- final AutoFillId id = entry.getKey();
+ final AutofillId id = entry.getKey();
final ViewNode node = findViewNodeByIdLocked(id);
if (node == null) {
Slog.w(TAG, "callSaveLocked(): did not find node with id " + id);
@@ -847,7 +847,7 @@
Slog.v(TAG, "callSaveLocked(): updating " + id + " to " + value);
}
- node.updateAutoFillValue(value);
+ node.updateAutofillValue(value);
}
// Sanitize structure before it's sent to service.
@@ -861,10 +861,10 @@
mRemoteFillService.onSaveRequest(mStructure, extras);
}
- void updateLocked(AutoFillId id, Rect bounds, AutoFillValue value, int flags) {
+ void updateLocked(AutofillId id, Rect bounds, AutofillValue value, int flags) {
if (mAutoFilledDataset != null && (flags & FLAG_VALUE_CHANGED) == 0) {
// TODO(b/33197203): ignoring because we don't support partitions yet
- Slog.d(TAG, "updateLocked(): ignoring " + flags + " after app was auto-filled");
+ Slog.d(TAG, "updateLocked(): ignoring " + flags + " after app was autofilled");
return;
}
@@ -875,28 +875,28 @@
}
if ((flags & FLAG_START_SESSION) != 0) {
- // View is triggering auto-fill.
+ // View is triggering autofill.
mCurrentViewState = viewState;
viewState.update(value, bounds);
return;
}
if ((flags & FLAG_VALUE_CHANGED) != 0) {
- if (value != null && !value.equals(viewState.mAutoFillValue)) {
+ if (value != null && !value.equals(viewState.mAutofillValue)) {
viewState.mValueUpdated = true;
- // Must check if this update was caused by auto-filling the view, in which
+ // Must check if this update was caused by autofilling the view, in which
// case we just update the value, but not the UI.
if (mAutoFilledDataset != null) {
- final AutoFillValue filledValue = findValue(mAutoFilledDataset, id);
+ final AutofillValue filledValue = findValue(mAutoFilledDataset, id);
if (value.equals(filledValue)) {
- viewState.mAutoFillValue = value;
+ viewState.mAutofillValue = value;
return;
}
}
// Change value
- viewState.mAutoFillValue = value;
+ viewState.mAutofillValue = value;
// Update the chooser UI
getUiForShowing().filterFillUi(value.coerceToString());
@@ -936,10 +936,10 @@
@Override
public void onFillReady(ViewState viewState, FillResponse response, Rect bounds,
- AutoFillId filledId, @Nullable AutoFillValue value) {
+ AutofillId filledId, @Nullable AutofillValue value) {
String filterText = "";
if (value != null) {
- // TODO(b/33197203): Handle other AutoFillValue types
+ // TODO(b/33197203): Handle other AutofillValue types
final CharSequence text = value.getTextValue();
if (text != null) {
filterText = text.toString();
@@ -949,7 +949,7 @@
getUiForShowing().showFillUi(filledId, response, bounds, filterText);
}
- private void notifyChangeToClient(AutoFillId id, int event) {
+ private void notifyChangeToClient(AutofillId id, int event) {
if (!mHasCallback) return;
try {
mClient.onAutofillEvent(mWindowToken, id, event);
@@ -1006,7 +1006,7 @@
private Intent createAuthFillInIntent(AssistStructure structure) {
Intent fillInIntent = new Intent();
- fillInIntent.putExtra(AutoFillManager.EXTRA_ASSIST_STRUCTURE, structure);
+ fillInIntent.putExtra(AutofillManager.EXTRA_ASSIST_STRUCTURE, structure);
return fillInIntent;
}
@@ -1025,7 +1025,7 @@
pw.print(prefix); pw.print("mCurrentViewStates: "); pw.println(mCurrentViewState);
pw.print(prefix); pw.print("mViewStates: "); pw.println(mViewStates.size());
final String prefix2 = prefix + " ";
- for (Map.Entry<AutoFillId, ViewState> entry : mViewStates.entrySet()) {
+ for (Map.Entry<AutofillId, ViewState> entry : mViewStates.entrySet()) {
pw.print(prefix); pw.print("State for id "); pw.println(entry.getKey());
entry.getValue().dump(prefix2, pw);
}
@@ -1049,9 +1049,9 @@
if (DEBUG) {
Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset);
}
- mClient.autoFill(dataset.getFieldIds(), dataset.getFieldValues());
+ mClient.autofill(dataset.getFieldIds(), dataset.getFieldValues());
} catch (RemoteException e) {
- Slog.w(TAG, "Error auto-filling activity: " + e);
+ Slog.w(TAG, "Error autofilling activity: " + e);
}
}
}
@@ -1063,12 +1063,12 @@
}
}
- private ViewNode findViewNodeByIdLocked(AutoFillId id) {
+ private ViewNode findViewNodeByIdLocked(AutofillId id) {
final int size = mStructure.getWindowNodeCount();
for (int i = 0; i < size; i++) {
final WindowNode window = mStructure.getWindowNodeAt(i);
final ViewNode root = window.getRootViewNode();
- if (id.equals(root.getAutoFillId())) {
+ if (id.equals(root.getAutofillId())) {
return root;
}
final ViewNode child = findViewNodeByIdLocked(root, id);
@@ -1079,16 +1079,16 @@
return null;
}
- private ViewNode findViewNodeByIdLocked(ViewNode parent, AutoFillId id) {
+ private ViewNode findViewNodeByIdLocked(ViewNode parent, AutofillId id) {
final int childrenSize = parent.getChildCount();
if (childrenSize > 0) {
for (int i = 0; i < childrenSize; i++) {
final ViewNode child = parent.getChildAt(i);
- if (id.equals(child.getAutoFillId())) {
+ if (id.equals(child.getAutofillId())) {
return child;
}
final ViewNode grandChild = findViewNodeByIdLocked(child, id);
- if (grandChild != null && id.equals(grandChild.getAutoFillId())) {
+ if (grandChild != null && id.equals(grandChild.getAutofillId())) {
return grandChild;
}
}
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 2f600c2..090cf91 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -19,8 +19,8 @@
import android.annotation.Nullable;
import android.os.Bundle;
import android.service.autofill.Dataset;
-import android.view.autofill.AutoFillId;
-import android.view.autofill.AutoFillValue;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
import java.util.ArrayList;
import java.util.Arrays;
@@ -61,9 +61,9 @@
* Gets the value of a {@link Dataset} field by its id, or {@code null} if not found.
*/
@Nullable
- static AutoFillValue findValue(Dataset dataset, AutoFillId id) {
+ static AutofillValue findValue(Dataset dataset, AutofillId id) {
if (dataset != null) {
- final ArrayList<AutoFillId> ids = dataset.getFieldIds();
+ final ArrayList<AutofillId> ids = dataset.getFieldIds();
final int size = ids.size();
for (int i = 0; i < size; i++) {
if (id.equals(ids.get(i))) {
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index d9f9721..76385b1 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -30,7 +30,7 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.service.autofill.AutoFillService;
+import android.service.autofill.AutofillService;
import android.service.autofill.FillResponse;
import android.service.autofill.IAutoFillService;
import android.service.autofill.IAutoFillServiceConnection;
@@ -100,8 +100,7 @@
mContext = context;
mCallbacks = callbacks;
mComponentName = componentName;
- mIntent = new Intent(AutoFillService.SERVICE_INTERFACE)
- .setComponent(mComponentName);
+ mIntent = new Intent(AutofillService.SERVICE_INTERFACE).setComponent(mComponentName);
mUserId = userId;
mHandler = new MyHandler(context);
}
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 599bbfe..3eefa7c 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -15,8 +15,8 @@
*/
package com.android.server.autofill.ui;
-import static android.view.autofill.AutoFillManager.AutofillCallback.EVENT_INPUT_HIDDEN;
-import static android.view.autofill.AutoFillManager.AutofillCallback.EVENT_INPUT_SHOWN;
+import static android.view.autofill.AutofillManager.AutofillCallback.EVENT_INPUT_HIDDEN;
+import static android.view.autofill.AutofillManager.AutofillCallback.EVENT_INPUT_SHOWN;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -31,7 +31,7 @@
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Slog;
-import android.view.autofill.AutoFillId;
+import android.view.autofill.AutofillId;
import android.widget.Toast;
import com.android.server.UiThread;
@@ -39,7 +39,7 @@
import java.io.PrintWriter;
/**
- * Handles all auto-fill related UI tasks. The UI has two components:
+ * Handles all autofill related UI tasks. The UI has two components:
* fill UI that shows a popup style window anchored at the focused
* input field for choosing a dataset to fill or trigger the response
* authentication flow; save UI that shows a toast style window for
@@ -66,7 +66,7 @@
void fill(@NonNull Dataset dataset);
void save();
void cancelSave();
- void onEvent(AutoFillId id, int event);
+ void onEvent(AutofillId id, int event);
}
public AutoFillUI(@NonNull Context context) {
@@ -102,7 +102,7 @@
/**
* Hides the fill UI.
*/
- public void hideFillUi(AutoFillId id) {
+ public void hideFillUi(AutofillId id) {
mHandler.post(() -> {
hideFillUiUiThread();
if (mCallback != null) {
@@ -153,7 +153,7 @@
* @param anchorBounds bounds of the focused view
* @param filterText text of the view to be filled
*/
- public void showFillUi(@NonNull AutoFillId focusedId, @NonNull FillResponse response,
+ public void showFillUi(@NonNull AutofillId focusedId, @NonNull FillResponse response,
@NonNull Rect anchorBounds, @Nullable String filterText) {
mHandler.post(() -> {
if (!hasCallback()) {
@@ -190,7 +190,7 @@
}
/**
- * Shows the UI asking the user to save for auto-fill.
+ * Shows the UI asking the user to save for autofill.
*/
public void showSaveUi(@NonNull CharSequence providerLabel, @NonNull SaveInfo info) {
mHandler.post(() -> {
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 0d5fbbe..4a380c5 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -32,12 +32,11 @@
import android.view.View.MeasureSpec;
import android.view.ViewGroup;
import android.view.WindowManager;
-import android.view.autofill.AutoFillId;
-import android.view.autofill.AutoFillValue;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.android.internal.R;
-import com.android.internal.R;
import libcore.util.Objects;
import java.util.ArrayList;
@@ -67,7 +66,7 @@
private boolean mDestroyed;
FillUi(@NonNull Context context, @NonNull FillResponse response,
- @NonNull AutoFillId focusedViewId, @NonNull IBinder windowToken,
+ @NonNull AutofillId focusedViewId, @NonNull IBinder windowToken,
@NonNull Rect anchorBounds, @Nullable String filterText,
@NonNull Callback callback) {
mAnchorBounds.set(anchorBounds);
@@ -101,7 +100,7 @@
final Dataset dataset = response.getDatasets().get(i);
final int index = dataset.getFieldIds().indexOf(focusedViewId);
if (index >= 0) {
- AutoFillValue value = dataset.getFieldValues().get(index);
+ final AutofillValue value = dataset.getFieldValues().get(index);
final View view;
try {
view = dataset.getPresentation().apply(context, null);
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 0d438cb..179b3d0 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -2839,7 +2839,8 @@
}
final class UidObserver extends IUidObserver.Stub {
- @Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
+ @Override public void onUidStateChanged(int uid, int procState,
+ long procStateSeq) throws RemoteException {
}
@Override public void onUidGone(int uid, boolean disabled) throws RemoteException {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0a65cab..fef7b51 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -127,10 +127,11 @@
import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
+import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_ONLY;
+import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
-import static com.android.server.am.ActivityStackSupervisor.RESTORE_FROM_RECENTS;
import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
@@ -533,8 +534,8 @@
// on getting this result before starting to launch its UI).
static final int PENDING_ASSIST_EXTRAS_LONG_TIMEOUT = 2000;
- // How long to wait in getAutoFillAssistStructure() for the activity to respond with the result.
- static final int PENDING_AUTO_FILL_ASSIST_STRUCTURE_TIMEOUT = 2000;
+ // How long to wait in getAutofillAssistStructure() for the activity to respond with the result.
+ static final int PENDING_AUTOFILL_ASSIST_STRUCTURE_TIMEOUT = 2000;
// Maximum number of persisted Uri grants a package is allowed
static final int MAX_PERSISTED_URI_GRANTS = 128;
@@ -702,6 +703,7 @@
public class PendingAssistExtras extends Binder implements Runnable {
public final ActivityRecord activity;
+ public boolean isHome;
public final Bundle extras;
public final Intent intent;
public final String hint;
@@ -723,6 +725,7 @@
receiverExtras = _receiverExtras;
userHandle = _userHandle;
}
+
@Override
public void run() {
Slog.w(TAG, "getAssistContextExtras failed: timeout retrieving from " + activity);
@@ -2625,11 +2628,11 @@
}
@VisibleForTesting
- public ActivityManagerService() {
+ public ActivityManagerService(AppOpsService appOpsService) {
GL_ES_VERSION = 0;
mActivityStarter = null;
mAppErrors = null;
- mAppOpsService = null;
+ mAppOpsService = appOpsService;
mBatteryStatsService = null;
mCompatModePackages = null;
mConstants = null;
@@ -4255,7 +4258,8 @@
mProcessObservers.finishBroadcast();
}
- private void dispatchUidsChanged() {
+ @VisibleForTesting
+ void dispatchUidsChanged() {
int N;
synchronized (this) {
N = mPendingUidChanges.size();
@@ -4278,104 +4282,105 @@
int i = mUidObservers.beginBroadcast();
while (i > 0) {
i--;
- final IUidObserver observer = mUidObservers.getBroadcastItem(i);
- final UidObserverRegistration reg = (UidObserverRegistration)
- mUidObservers.getBroadcastCookie(i);
- if (observer != null) {
- try {
- for (int j=0; j<N; j++) {
- UidRecord.ChangeItem item = mActiveUidChanges[j];
- final int change = item.change;
- UidRecord validateUid = null;
- if (VALIDATE_UID_STATES && i == 0) {
- validateUid = mValidateUids.get(item.uid);
- if (validateUid == null && change != UidRecord.CHANGE_GONE
- && change != UidRecord.CHANGE_GONE_IDLE) {
- validateUid = new UidRecord(item.uid);
- mValidateUids.put(item.uid, validateUid);
- }
- }
- if (change == UidRecord.CHANGE_IDLE
- || change == UidRecord.CHANGE_GONE_IDLE) {
- if ((reg.which & ActivityManager.UID_OBSERVER_IDLE) != 0) {
- if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
- "UID idle uid=" + item.uid);
- observer.onUidIdle(item.uid, item.ephemeral);
- }
- if (VALIDATE_UID_STATES && i == 0) {
- if (validateUid != null) {
- validateUid.idle = true;
- }
- }
- } else if (change == UidRecord.CHANGE_ACTIVE) {
- if ((reg.which & ActivityManager.UID_OBSERVER_ACTIVE) != 0) {
- if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
- "UID active uid=" + item.uid);
- observer.onUidActive(item.uid);
- }
- if (VALIDATE_UID_STATES && i == 0) {
- validateUid.idle = false;
- }
- }
- if (change == UidRecord.CHANGE_GONE
- || change == UidRecord.CHANGE_GONE_IDLE) {
- if ((reg.which & ActivityManager.UID_OBSERVER_GONE) != 0) {
- if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
- "UID gone uid=" + item.uid);
- observer.onUidGone(item.uid, item.ephemeral);
- }
- if (reg.lastProcStates != null) {
- reg.lastProcStates.delete(item.uid);
- }
- if (VALIDATE_UID_STATES && i == 0) {
- if (validateUid != null) {
- mValidateUids.remove(item.uid);
- }
- }
- } else {
- if ((reg.which & ActivityManager.UID_OBSERVER_PROCSTATE) != 0) {
- if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
- "UID CHANGED uid=" + item.uid
- + ": " + item.processState);
- boolean doReport = true;
- if (reg.cutpoint >= ActivityManager.MIN_PROCESS_STATE) {
- final int lastState = reg.lastProcStates.get(item.uid,
- ActivityManager.PROCESS_STATE_UNKNOWN);
- if (lastState != ActivityManager.PROCESS_STATE_UNKNOWN) {
- final boolean lastAboveCut = lastState <= reg.cutpoint;
- final boolean newAboveCut = item.processState <= reg.cutpoint;
- doReport = lastAboveCut != newAboveCut;
- } else {
- doReport = item.processState
- != ActivityManager.PROCESS_STATE_NONEXISTENT;
- }
- }
- if (doReport) {
- if (reg.lastProcStates != null) {
- reg.lastProcStates.put(item.uid, item.processState);
- }
- observer.onUidStateChanged(item.uid, item.processState);
- }
- }
- if (VALIDATE_UID_STATES && i == 0) {
- validateUid.curProcState = validateUid.setProcState
- = item.processState;
- }
- }
- }
- } catch (RemoteException e) {
- }
- }
+ dispatchUidsChangedForObserver(mUidObservers.getBroadcastItem(i),
+ (UidObserverRegistration) mUidObservers.getBroadcastCookie(i), N);
}
mUidObservers.finishBroadcast();
+ if (VALIDATE_UID_STATES && mUidObservers.getRegisteredCallbackCount() > 0) {
+ for (int j = 0; j < N; ++j) {
+ final UidRecord.ChangeItem item = mActiveUidChanges[j];
+ if (item.change == UidRecord.CHANGE_GONE
+ || item.change == UidRecord.CHANGE_GONE_IDLE) {
+ mValidateUids.remove(item.uid);
+ } else {
+ UidRecord validateUid = mValidateUids.get(item.uid);
+ if (validateUid == null) {
+ validateUid = new UidRecord(item.uid);
+ mValidateUids.put(item.uid, validateUid);
+ }
+ if (item.change == UidRecord.CHANGE_IDLE) {
+ validateUid.idle = true;
+ } else if (item.change == UidRecord.CHANGE_ACTIVE) {
+ validateUid.idle = false;
+ }
+ validateUid.curProcState = validateUid.setProcState = item.processState;
+ }
+ }
+ }
+
synchronized (this) {
- for (int j=0; j<N; j++) {
+ for (int j = 0; j < N; j++) {
mAvailUidChanges.add(mActiveUidChanges[j]);
}
}
}
+ private void dispatchUidsChangedForObserver(IUidObserver observer,
+ UidObserverRegistration reg, int changesSize) {
+ if (observer == null) {
+ return;
+ }
+ try {
+ for (int j = 0; j < changesSize; j++) {
+ UidRecord.ChangeItem item = mActiveUidChanges[j];
+ final int change = item.change;
+ if (change == UidRecord.CHANGE_IDLE
+ || change == UidRecord.CHANGE_GONE_IDLE) {
+ if ((reg.which & ActivityManager.UID_OBSERVER_IDLE) != 0) {
+ if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
+ "UID idle uid=" + item.uid);
+ observer.onUidIdle(item.uid, item.ephemeral);
+ }
+ } else if (change == UidRecord.CHANGE_ACTIVE) {
+ if ((reg.which & ActivityManager.UID_OBSERVER_ACTIVE) != 0) {
+ if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
+ "UID active uid=" + item.uid);
+ observer.onUidActive(item.uid);
+ }
+ }
+ if (change == UidRecord.CHANGE_GONE
+ || change == UidRecord.CHANGE_GONE_IDLE) {
+ if ((reg.which & ActivityManager.UID_OBSERVER_GONE) != 0) {
+ if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
+ "UID gone uid=" + item.uid);
+ observer.onUidGone(item.uid, item.ephemeral);
+ }
+ if (reg.lastProcStates != null) {
+ reg.lastProcStates.delete(item.uid);
+ }
+ } else {
+ if ((reg.which & ActivityManager.UID_OBSERVER_PROCSTATE) != 0) {
+ if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
+ "UID CHANGED uid=" + item.uid
+ + ": " + item.processState);
+ boolean doReport = true;
+ if (reg.cutpoint >= ActivityManager.MIN_PROCESS_STATE) {
+ final int lastState = reg.lastProcStates.get(item.uid,
+ ActivityManager.PROCESS_STATE_UNKNOWN);
+ if (lastState != ActivityManager.PROCESS_STATE_UNKNOWN) {
+ final boolean lastAboveCut = lastState <= reg.cutpoint;
+ final boolean newAboveCut = item.processState <= reg.cutpoint;
+ doReport = lastAboveCut != newAboveCut;
+ } else {
+ doReport = item.processState
+ != ActivityManager.PROCESS_STATE_NONEXISTENT;
+ }
+ }
+ if (doReport) {
+ if (reg.lastProcStates != null) {
+ reg.lastProcStates.put(item.uid, item.processState);
+ }
+ observer.onUidStateChanged(item.uid, item.processState,
+ item.procStateSeq);
+ }
+ }
+ }
+ }
+ } catch (RemoteException e) {
+ }
+ }
+
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
@@ -9650,7 +9655,7 @@
enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
"getTaskThumbnail()");
final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(
- id, !RESTORE_FROM_RECENTS, INVALID_STACK_ID);
+ id, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, INVALID_STACK_ID);
if (tr != null) {
return tr.getTaskThumbnailLocked();
}
@@ -9663,8 +9668,8 @@
synchronized (this) {
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
"getTaskDescription()");
- final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(
- id, !RESTORE_FROM_RECENTS, INVALID_STACK_ID);
+ final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(id,
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, INVALID_STACK_ID);
if (tr != null) {
return tr.lastTaskDescription;
}
@@ -9776,7 +9781,7 @@
public void setTaskResizeable(int taskId, int resizeableMode) {
synchronized (this) {
final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(
- taskId, !RESTORE_FROM_RECENTS, INVALID_STACK_ID);
+ taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, INVALID_STACK_ID);
if (task == null) {
Slog.w(TAG, "setTaskResizeable: taskId=" + taskId + " not found");
return;
@@ -9838,8 +9843,8 @@
Rect rect = new Rect();
try {
synchronized (this) {
- final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(
- taskId, !RESTORE_FROM_RECENTS, INVALID_STACK_ID);
+ final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId,
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, INVALID_STACK_ID);
if (task == null) {
Slog.w(TAG, "getTaskBounds: taskId=" + taskId + " not found");
return rect;
@@ -9870,8 +9875,8 @@
final long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
- final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(
- taskId, !RESTORE_FROM_RECENTS, INVALID_STACK_ID);
+ final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId,
+ MATCH_TASK_IN_STACKS_ONLY, INVALID_STACK_ID);
if (task == null) {
Slog.w(TAG, "cancelTaskWindowTransition: taskId=" + taskId + " not found");
return;
@@ -9889,8 +9894,8 @@
final long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
- final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(
- taskId, !RESTORE_FROM_RECENTS, INVALID_STACK_ID);
+ final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId,
+ MATCH_TASK_IN_STACKS_ONLY, INVALID_STACK_ID);
if (task == null) {
Slog.w(TAG, "cancelTaskThumbnailTransition: taskId=" + taskId + " not found");
return;
@@ -9909,8 +9914,8 @@
try {
final TaskRecord task;
synchronized (this) {
- task = mStackSupervisor.anyTaskForIdLocked(
- taskId, !RESTORE_FROM_RECENTS, INVALID_STACK_ID);
+ task = mStackSupervisor.anyTaskForIdLocked(taskId,
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, INVALID_STACK_ID);
if (task == null) {
Slog.w(TAG, "getTaskSnapshot: taskId=" + taskId + " not found");
return null;
@@ -12646,16 +12651,16 @@
}
@Override
- public boolean requestAutoFillData(IResultReceiver receiver, Bundle receiverExtras,
+ public boolean requestAutofillData(IResultReceiver receiver, Bundle receiverExtras,
IBinder activityToken) {
// NOTE: we could always use ActivityManager.ASSIST_CONTEXT_FULL and let ActivityThread
// rely on the flags to decide whether the handleRequestAssistContextExtras() is for
- // auto-fill, but it's safer to explicitly use new AutoFill types, in case the Assist
+ // autofill, but it's safer to explicitly use new AutoFill types, in case the Assist
// requests use flags in the future as well (since their flags value might collide with the
- // auto-fill flag values).
- return enqueueAssistContext(ActivityManager.ASSIST_CONTEXT_AUTO_FILL, null, null,
+ // autofill flag values).
+ return enqueueAssistContext(ActivityManager.ASSIST_CONTEXT_AUTOFILL, null, null,
receiver, receiverExtras, activityToken, true, true, UserHandle.getCallingUserId(),
- null, PENDING_AUTO_FILL_ASSIST_STRUCTURE_TIMEOUT) != null;
+ null, PENDING_AUTOFILL_ASSIST_STRUCTURE_TIMEOUT) != null;
}
private PendingAssistExtras enqueueAssistContext(int requestType, Intent intent, String hint,
@@ -12702,6 +12707,7 @@
pae = new PendingAssistExtras(activity, extras, intent, hint, receiver, receiverExtras,
userHandle);
+ pae.isHome = activity.isHomeActivity();
// Increment the sessionId if necessary
if (newSessionId) {
@@ -12748,6 +12754,8 @@
}
}
+ /** Called from an app when assist data is ready. */
+ @Override
public void reportAssistContextExtras(IBinder token, Bundle extras, AssistStructure structure,
AssistContent content, Uri referrer) {
PendingAssistExtras pae = (PendingAssistExtras)token;
@@ -12758,6 +12766,9 @@
if (referrer != null) {
pae.extras.putParcelable(Intent.EXTRA_REFERRER, referrer);
}
+ if (structure != null) {
+ structure.setHomeActivity(pae.isHome);
+ }
pae.haveResult = true;
pae.notifyAll();
if (pae.intent == null && pae.receiver == null) {
@@ -19890,14 +19901,11 @@
/** Helper method that requests bounds from WM and applies them to stack. */
private void resizeStackWithBoundsFromWindowManager(int stackId, boolean deferResume) {
final Rect newStackBounds = new Rect();
- final Rect newTempTaskBounds = new Rect();
- mStackSupervisor.getStack(stackId).getBoundsForNewConfiguration(newStackBounds,
- newTempTaskBounds);
+ mStackSupervisor.getStack(stackId).getBoundsForNewConfiguration(newStackBounds);
mStackSupervisor.resizeStackLocked(
stackId, !newStackBounds.isEmpty() ? newStackBounds : null /* bounds */,
- !newTempTaskBounds.isEmpty() ? newTempTaskBounds : null /* tempTaskBounds */,
- null /* tempTaskInsetBounds */, false /* preserveWindows */,
- false /* allowResizeInDockedMode */, deferResume);
+ null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
+ false /* preserveWindows */, false /* allowResizeInDockedMode */, deferResume);
}
/**
@@ -21477,6 +21485,7 @@
pendingChange.processState = uidRec != null
? uidRec.setProcState : ActivityManager.PROCESS_STATE_NONEXISTENT;
pendingChange.ephemeral = uidRec.ephemeral;
+ pendingChange.procStateSeq = uidRec != null ? uidRec.curProcStateSeq : 0;
// Directly update the power manager, since we sit on top of it and it is critical
// it be kept in sync (so wake locks will be held as soon as appropriate).
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 15a9efc..2d91cad 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -120,6 +120,7 @@
import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
import com.android.server.wm.StackWindowController;
import com.android.server.wm.StackWindowListener;
+import com.android.server.wm.TaskStack;
import com.android.server.wm.WindowManagerService;
import java.io.FileDescriptor;
@@ -544,10 +545,13 @@
mActivityContainer.mActivityDisplay.mDisplay.getSize(out);
}
- void getStackDockedModeBounds(Rect outBounds, Rect outTempBounds, Rect outTempInsetBounds,
- boolean ignoreVisibility) {
- mWindowContainerController.getStackDockedModeBounds(outBounds, outTempBounds,
- outTempInsetBounds, ignoreVisibility);
+ /**
+ * @see ActivityStack.getStackDockedModeBounds(Rect, Rect, Rect, boolean)
+ */
+ void getStackDockedModeBounds(Rect currentTempTaskBounds, Rect outStackBounds,
+ Rect outTempTaskBounds, boolean ignoreVisibility) {
+ mWindowContainerController.getStackDockedModeBounds(currentTempTaskBounds,
+ outStackBounds, outTempTaskBounds, ignoreVisibility);
}
void prepareFreezingTaskBounds() {
@@ -562,8 +566,8 @@
outBounds.setEmpty();
}
- void getBoundsForNewConfiguration(Rect outBounds, Rect outTempBounds) {
- mWindowContainerController.getBoundsForNewConfiguration(outBounds, outTempBounds);
+ void getBoundsForNewConfiguration(Rect outBounds) {
+ mWindowContainerController.getBoundsForNewConfiguration(outBounds);
}
void positionChildWindowContainerAtTop(TaskRecord child) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 59f58d7..2ae815e30 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -21,8 +21,6 @@
import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
-import static android.app.ActivityManager.RESIZE_MODE_FORCED;
-import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
@@ -97,6 +95,7 @@
import static java.lang.Integer.MAX_VALUE;
import android.Manifest;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.Activity;
@@ -105,7 +104,6 @@
import android.app.ActivityManager.StackId;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityOptions;
-import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.IActivityContainerCallback;
import android.app.ProfilerInfo;
@@ -179,10 +177,11 @@
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.Objects;
import java.util.Set;
public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener {
@@ -248,15 +247,31 @@
// Force the focus to change to the stack we are moving a task to..
static final boolean FORCE_FOCUS = true;
- // Restore task from the saved recents if it can't be found in any live stack.
- static final boolean RESTORE_FROM_RECENTS = true;
-
// Don't execute any calls to resume.
static final boolean DEFER_RESUME = true;
// Used to indicate that a task is removed it should also be removed from recents.
static final boolean REMOVE_FROM_RECENTS = true;
+ /**
+ * The modes which affect which tasks are returned when calling
+ * {@link ActivityStackSupervisor#anyTaskForIdLocked(int)}.
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ MATCH_TASK_IN_STACKS_ONLY,
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS,
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE
+ })
+ public @interface AnyTaskForIdMatchTaskMode {}
+ // Match only tasks in the current stacks
+ static final int MATCH_TASK_IN_STACKS_ONLY = 0;
+ // Match either tasks in the current stacks, or in the recent tasks if not found in the stacks
+ static final int MATCH_TASK_IN_STACKS_OR_RECENT_TASKS = 1;
+ // Match either tasks in the current stacks, or in the recent tasks, restoring it to the
+ // provided stack id
+ static final int MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE = 2;
+
// Activity actions an app cannot start if it uses a permission which is not granted.
private static final ArrayMap<String, String> ACTION_TO_RUNTIME_PERMISSION =
new ArrayMap<>();
@@ -713,18 +728,26 @@
}
TaskRecord anyTaskForIdLocked(int id) {
- return anyTaskForIdLocked(id, RESTORE_FROM_RECENTS, INVALID_STACK_ID);
+ return anyTaskForIdLocked(id, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE,
+ INVALID_STACK_ID);
}
/**
* Returns a {@link TaskRecord} for the input id if available. Null otherwise.
* @param id Id of the task we would like returned.
- * @param restoreFromRecents If the id was not in the active list, but was found in recents,
- * restore the task from recents to the active list.
+ * @param matchMode The mode to match the given task id in.
* @param stackId The stack to restore the task to (default launch stack will be used if
- * stackId is {@link android.app.ActivityManager.StackId#INVALID_STACK_ID}).
+ * stackId is {@link android.app.ActivityManager.StackId#INVALID_STACK_ID}). Only
+ * valid if the matchMode is
+ * {@link #MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE}.
*/
- TaskRecord anyTaskForIdLocked(int id, boolean restoreFromRecents, int stackId) {
+ TaskRecord anyTaskForIdLocked(int id, @AnyTaskForIdMatchTaskMode int matchMode, int stackId) {
+ // If there is a stack id set, ensure that we are attempting to actually restore a task
+ if (matchMode != MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE &&
+ stackId != INVALID_STACK_ID) {
+ throw new IllegalArgumentException("Should not specify stackId for non-restore lookup");
+ }
+
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
@@ -737,18 +760,23 @@
}
}
- // Don't give up! Look in recents.
- if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents");
- TaskRecord task = mRecentTasks.taskForIdLocked(id);
- if (task == null) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "\tDidn't find task id=" + id + " in recents");
+ // If we are matching stack tasks only, return now
+ if (matchMode == MATCH_TASK_IN_STACKS_ONLY) {
return null;
}
- if (!restoreFromRecents) {
+ // Otherwise, check the recent tasks and return if we find it there and we are not restoring
+ // the task from recents
+ if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents");
+ TaskRecord task = mRecentTasks.taskForIdLocked(id);
+ if (matchMode == MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) {
+ if (DEBUG_RECENTS && task == null) {
+ Slog.d(TAG_RECENTS, "\tDidn't find task id=" + id + " in recents");
+ }
return task;
}
+ // Implicitly, this case is MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE
if (!restoreRecentTaskLocked(task, stackId)) {
if (DEBUG_RECENTS) Slog.w(TAG_RECENTS,
"Couldn't restore task id=" + id + " found in recents");
@@ -844,7 +872,7 @@
// was 10, user 0 could only have taskIds 0 to 9, user 1: 10 to 19, user 2: 20 to 29, so on.
int candidateTaskId = nextTaskIdForUser(currentTaskId, userId);
while (mRecentTasks.taskIdTakenForUserLocked(candidateTaskId, userId)
- || anyTaskForIdLocked(candidateTaskId, !RESTORE_FROM_RECENTS,
+ || anyTaskForIdLocked(candidateTaskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS,
INVALID_STACK_ID) != null) {
candidateTaskId = nextTaskIdForUser(candidateTaskId, userId);
if (candidateTaskId == currentTaskId) {
@@ -2249,7 +2277,7 @@
for (int i = mResizingTasksDuringAnimation.size() - 1; i >= 0; i--) {
final int taskId = mResizingTasksDuringAnimation.valueAt(i);
final TaskRecord task =
- anyTaskForIdLocked(taskId, !RESTORE_FROM_RECENTS, INVALID_STACK_ID);
+ anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_ONLY, INVALID_STACK_ID);
if (task != null) {
task.setTaskDockedResizing(false);
}
@@ -2375,19 +2403,19 @@
// static stacks need to be adjusted so they don't overlap with the docked stack.
// We get the bounds to use from window manager which has been adjusted for any
// screen controls and is also the same for all stacks.
- final Rect tempOtherTaskRect = new Rect();
- final Rect tempOtherTaskInsetRect = new Rect();
+ final Rect otherTaskRect = new Rect();
for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
final ActivityStack current = getStack(i);
if (current != null && StackId.isResizeableByDockedStack(i)) {
- current.getStackDockedModeBounds(tempRect, tempOtherTaskRect,
- tempOtherTaskInsetRect, true /* ignoreVisibility */);
+ current.getStackDockedModeBounds(
+ tempOtherTaskBounds /* currentTempTaskBounds */,
+ tempRect /* outStackBounds */,
+ otherTaskRect /* outTempTaskBounds */, true /* ignoreVisibility */);
+
resizeStackLocked(i, tempRect,
- !tempOtherTaskRect.isEmpty() ? tempOtherTaskRect :
- tempOtherTaskBounds,
- !tempOtherTaskInsetRect.isEmpty() ? tempOtherTaskInsetRect :
- tempOtherTaskInsetBounds,
- preserveWindows, true /* allowResizeInDockedMode */, deferResume);
+ !otherTaskRect.isEmpty() ? otherTaskRect : tempOtherTaskBounds,
+ tempOtherTaskInsetBounds, preserveWindows,
+ true /* allowResizeInDockedMode */, deferResume);
}
}
}
@@ -2493,7 +2521,8 @@
* @return Returns true if the given task was found and removed.
*/
boolean removeTaskByIdLocked(int taskId, boolean killProcess, boolean removeFromRecents) {
- final TaskRecord tr = anyTaskForIdLocked(taskId, !RESTORE_FROM_RECENTS, INVALID_STACK_ID);
+ final TaskRecord tr = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS,
+ INVALID_STACK_ID);
if (tr != null) {
tr.removeTaskActivitiesLocked();
cleanUpRemovedTaskLocked(tr, killProcess, removeFromRecents);
@@ -4784,7 +4813,8 @@
mWindowManager.prepareAppTransition(TRANSIT_DOCK_TASK_FROM_RECENTS, false);
}
- task = anyTaskForIdLocked(taskId, RESTORE_FROM_RECENTS, launchStackId);
+ task = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE,
+ launchStackId);
if (task == null) {
continueUpdateBounds(HOME_STACK_ID);
mWindowManager.executeAppTransition();
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 33889ba..2bbfc21 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -1562,9 +1562,14 @@
// activity. Well that should not be too hard...
// Note: we must persist the {@link TaskRecord} first as intentActivity could be
// removed from calling performClearTaskLocked (For example, if it is being brought out
- // of history or if it is finished immediately), thus disassociating the task.
- mReuseTask = intentActivity.task;
- mReuseTask.performClearTaskLocked();
+ // of history or if it is finished immediately), thus disassociating the task. Also note
+ // that mReuseTask is reset as a result of {@link TaskRecord#performClearTaskLocked}
+ // launching another activity.
+ // TODO(b/36119896): We shouldn't trigger activity launches in this path since we are
+ // already launching one.
+ final TaskRecord task = intentActivity.task;
+ task.performClearTaskLocked();
+ mReuseTask = task;
mReuseTask.setIntent(mStartActivity);
// When we clear the task - focus will be adjusted, which will bring another task
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index 9dde39e..9deabb3 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -55,6 +55,9 @@
import java.util.List;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+
+import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
public class TaskPersister {
static final String TAG = "TaskPersister";
@@ -452,7 +455,8 @@
final int taskId = task.taskId;
if (mStackSupervisor.anyTaskForIdLocked(taskId,
- /* restoreFromRecents= */ false, HOME_STACK_ID) != null) {
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS,
+ INVALID_STACK_ID) != null) {
// Should not happen.
Slog.wtf(TAG, "Existing task with taskId " + taskId + "found");
} else if (userId != task.userId) {
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index f15543a..cf6c1e1 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -53,6 +53,7 @@
int change;
int processState;
boolean ephemeral;
+ long procStateSeq;
}
ChangeItem pendingChange;
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index c973911..b316a3b 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -518,7 +518,8 @@
}
final private IUidObserver mUidObserver = new IUidObserver.Stub() {
- @Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
+ @Override public void onUidStateChanged(int uid, int procState,
+ long procStateSeq) throws RemoteException {
updateUidState(uid, procState);
}
diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java
index 258fb6d..0a15db6 100644
--- a/services/core/java/com/android/server/location/ContextHubService.java
+++ b/services/core/java/com/android/server/location/ContextHubService.java
@@ -93,6 +93,8 @@
public int registerCallback(IContextHubCallback callback) throws RemoteException {
checkPermissions();
mCallbacksList.register(callback);
+ Log.d(TAG, "Added callback, total callbacks " +
+ mCallbacksList.getRegisteredCallbackCount());
return 0;
}
@@ -101,6 +103,7 @@
checkPermissions();
int[] returnArray = new int[mContextHubInfo.length];
+ Log.d(TAG, "System supports " + returnArray.length + " hubs");
for (int i = 0; i < returnArray.length; ++i) {
returnArray[i] = i;
Log.d(TAG, String.format("Hub %s is mapped to %d",
@@ -114,6 +117,7 @@
public ContextHubInfo getContextHubInfo(int contextHubHandle) throws RemoteException {
checkPermissions();
if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) {
+ Log.e(TAG, "Invalid context hub handle " + contextHubHandle);
return null; // null means fail
}
@@ -129,6 +133,7 @@
return -1;
}
if (app == null) {
+ Log.e(TAG, "Invalid null app");
return -1;
}
@@ -158,6 +163,7 @@
checkPermissions();
NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstanceHandle);
if (info == null) {
+ Log.e(TAG, "Cannot find app with handle " + nanoAppInstanceHandle);
return -1; //means failed
}
@@ -171,6 +177,7 @@
byte msg[] = new byte[0];
if (nativeSendMessage(msgHeader, msg) != 0) {
+ Log.e(TAG, "native send message fails");
return -1;
}
@@ -187,6 +194,7 @@
if (mNanoAppHash.containsKey(nanoAppInstanceHandle)) {
return mNanoAppHash.get(nanoAppInstanceHandle);
} else {
+ Log.e(TAG, "Could not find nanoApp with handle " + nanoAppInstanceHandle);
return null;
}
}
@@ -209,6 +217,7 @@
retArray[i] = foundInstances.get(i).intValue();
}
+ Log.w(TAG, "Found " + retArray.length + " apps on hub handle " + hubHandle);
return retArray;
}
@@ -265,22 +274,26 @@
if (header == null || data == null || header.length < MSG_HEADER_SIZE) {
return -1;
}
+
int callbacksCount = mCallbacksList.beginBroadcast();
+ int msgType = header[HEADER_FIELD_MSG_TYPE];
+ int msgVersion = header[HEADER_FIELD_MSG_VERSION];
+ int hubHandle = header[HEADER_FIELD_HUB_HANDLE];
+ int appInstance = header[HEADER_FIELD_APP_INSTANCE];
+
+ Log.d(TAG, "Sending message " + msgType + " version " + msgVersion + " from hubHandle " +
+ hubHandle + ", appInstance " + appInstance + ", callBackCount " + callbacksCount);
+
if (callbacksCount < 1) {
Log.v(TAG, "No message callbacks registered.");
return 0;
}
- ContextHubMessage msg = new ContextHubMessage(header[HEADER_FIELD_MSG_TYPE],
- header[HEADER_FIELD_MSG_VERSION],
- data);
+ ContextHubMessage msg = new ContextHubMessage(msgType, msgVersion, data);
for (int i = 0; i < callbacksCount; ++i) {
IContextHubCallback callback = mCallbacksList.getBroadcastItem(i);
try {
- callback.onMessageReceipt(
- header[HEADER_FIELD_HUB_HANDLE],
- header[HEADER_FIELD_APP_INSTANCE],
- msg);
+ callback.onMessageReceipt(hubHandle, appInstance, msg);
} catch (RemoteException e) {
Log.i(TAG, "Exception (" + e + ") calling remote callback (" + callback + ").");
continue;
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 4e9d838..9d93cc7 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -719,7 +719,8 @@
}
final private IUidObserver mUidObserver = new IUidObserver.Stub() {
- @Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
+ @Override public void onUidStateChanged(int uid, int procState,
+ long procStateSeq) throws RemoteException {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "onUidStateChanged");
try {
synchronized (mUidRulesFirstLock) {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 1aaec1a..8998212 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -476,7 +476,8 @@
final private IUidObserver mUidObserver = new IUidObserver.Stub() {
@Override
- public void onUidStateChanged(int uid, int procState) throws RemoteException {
+ public void onUidStateChanged(int uid, int procState, long procStateSeq)
+ throws RemoteException {
handleOnUidStateChanged(uid, procState);
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 4f1754a..8a59726 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -26,7 +26,7 @@
import static android.content.Context.DISPLAY_SERVICE;
import static android.content.Context.WINDOW_SERVICE;
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
-import static android.content.pm.PackageManager.FEATURE_TELEVISION;
+import static android.content.pm.PackageManager.FEATURE_LEANBACK;
import static android.content.pm.PackageManager.FEATURE_WATCH;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.res.Configuration.EMPTY;
@@ -416,6 +416,7 @@
BurnInProtectionHelper mBurnInProtectionHelper;
AppOpsManager mAppOpsManager;
private boolean mHasFeatureWatch;
+ private boolean mHasFeatureLeanback;
// Assigned on main thread, accessed on UI thread
volatile VrManagerInternal mVrManagerInternal;
@@ -767,6 +768,12 @@
private boolean mScreenshotChordPowerKeyTriggered;
private long mScreenshotChordPowerKeyTime;
+ private static final long BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS = 1000;
+
+ private boolean mBugreportTvKey1Pressed;
+ private boolean mBugreportTvKey2Pressed;
+ private boolean mBugreportTvScheduled;
+
/* The number of steps between min and max brightness */
private static final int BRIGHTNESS_STEPS = 10;
@@ -810,6 +817,7 @@
private static final int MSG_DISPOSE_INPUT_CONSUMER = 19;
private static final int MSG_BACK_DELAYED_PRESS = 20;
private static final int MSG_ACCESSIBILITY_SHORTCUT = 21;
+ private static final int MSG_BUGREPORT_TV = 22;
private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
@@ -888,6 +896,9 @@
case MSG_ACCESSIBILITY_SHORTCUT:
accessibilityShortcutActivated();
break;
+ case MSG_BUGREPORT_TV:
+ takeBugreport();
+ break;
}
}
}
@@ -1753,6 +1764,7 @@
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
mHasFeatureWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH);
+ mHasFeatureLeanback = mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK);
mAccessibilityShortcutController =
new AccessibilityShortcutController(mContext, new Handler());
// Init display burn-in protection
@@ -3482,6 +3494,8 @@
} else if (keyCode == KeyEvent.KEYCODE_TAB && event.isMetaPressed()) {
// Pass through keyboard navigation keys.
return 0;
+ } else if (mHasFeatureLeanback && interceptBugreportGestureTv(keyCode, down)) {
+ return -1;
}
// Toggle Caps Lock on META-ALT.
@@ -3674,6 +3688,45 @@
return 0;
}
+ /**
+ * TV only: recognizes a remote control gesture for capturing a bug report.
+ */
+ private boolean interceptBugreportGestureTv(int keyCode, boolean down) {
+ // The bugreport capture chord is a long press on DPAD CENTER and BACK simultaneously.
+ if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
+ mBugreportTvKey1Pressed = down;
+ } else if (keyCode == KeyEvent.KEYCODE_BACK) {
+ mBugreportTvKey2Pressed = down;
+ }
+
+ if (mBugreportTvKey1Pressed && mBugreportTvKey2Pressed) {
+ if (!mBugreportTvScheduled) {
+ mBugreportTvScheduled = true;
+ Message msg = Message.obtain(mHandler, MSG_BUGREPORT_TV);
+ msg.setAsynchronous(true);
+ mHandler.sendMessageDelayed(msg, BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS);
+ }
+ } else if (mBugreportTvScheduled) {
+ mHandler.removeMessages(MSG_BUGREPORT_TV);
+ mBugreportTvScheduled = false;
+ }
+
+ return mBugreportTvScheduled;
+ }
+
+ private void takeBugreport() {
+ if ("1".equals(SystemProperties.get("ro.debuggable"))
+ || Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) == 1) {
+ try {
+ ActivityManager.getService()
+ .requestBugReport(ActivityManager.BUGREPORT_OPTION_INTERACTIVE);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error taking bugreport", e);
+ }
+ }
+ }
+
/** {@inheritDoc} */
@Override
public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
@@ -7083,7 +7136,7 @@
@Override public void run() {
if (mBootMsgDialog == null) {
int theme;
- if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) {
+ if (mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK)) {
theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
} else {
theme = 0;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index c58b527..24f6f89 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -72,6 +72,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
+import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
import com.android.server.EventLogTags;
@@ -194,6 +195,7 @@
private final Context mContext;
private final ServiceThread mHandlerThread;
private final PowerManagerHandler mHandler;
+ private final AmbientDisplayConfiguration mAmbientDisplayConfiguration;
private final BatterySaverPolicy mBatterySaverPolicy;
private LightsManager mLightsManager;
@@ -516,6 +518,9 @@
// True if theater mode is enabled
private boolean mTheaterModeEnabled;
+ // True if always on display is enabled
+ private boolean mAlwaysOnEnabled;
+
// True if double tap to wake is enabled
private boolean mDoubleTapWakeEnabled;
@@ -608,6 +613,7 @@
mHandlerThread.start();
mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
mConstants = new Constants(mHandler);
+ mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext);
mBatterySaverPolicy = new BatterySaverPolicy(mHandler);
synchronized (mLock) {
@@ -640,6 +646,7 @@
mHandlerThread.start();
mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
mConstants = new Constants(mHandler);
+ mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext);
mDisplaySuspendBlocker = null;
mWakeLockSuspendBlocker = null;
}
@@ -766,6 +773,9 @@
Settings.Global.THEATER_MODE_ON),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Secure.getUriFor(
+ Settings.Secure.DOZE_ALWAYS_ON),
+ false, mSettingsObserver, UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.DOUBLE_TAP_TO_WAKE),
false, mSettingsObserver, UserHandle.USER_ALL);
IVrManager vrManager = (IVrManager) getBinderService(Context.VR_SERVICE);
@@ -863,6 +873,7 @@
Settings.Global.STAY_ON_WHILE_PLUGGED_IN, BatteryManager.BATTERY_PLUGGED_AC);
mTheaterModeEnabled = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.THEATER_MODE_ON, 0) == 1;
+ mAlwaysOnEnabled = mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT);
if (mSupportsDoubleTapWakeConfig) {
boolean doubleTapWakeEnabled = Settings.Secure.getIntForUser(resolver,
@@ -1702,6 +1713,11 @@
return false;
}
+ // On Always On Display, SystemUI shows the charging indicator
+ if (mAlwaysOnEnabled && mWakefulness == WAKEFULNESS_DOZING) {
+ return false;
+ }
+
// Otherwise wake up!
return true;
}
diff --git a/services/core/java/com/android/server/storage/AppCollector.java b/services/core/java/com/android/server/storage/AppCollector.java
index 25880fb..a77d33f 100644
--- a/services/core/java/com/android/server/storage/AppCollector.java
+++ b/services/core/java/com/android/server/storage/AppCollector.java
@@ -116,33 +116,33 @@
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_START_LOADING_SIZES: {
- final List<ApplicationInfo> apps = mPm.getInstalledApplications(
- PackageManager.GET_UNINSTALLED_PACKAGES
- | PackageManager.GET_DISABLED_COMPONENTS);
-
- final List<ApplicationInfo> volumeApps = new ArrayList<>();
- for (ApplicationInfo app : apps) {
- if (Objects.equals(app.volumeUuid, mVolume.getFsUuid())) {
- volumeApps.add(app);
- }
- }
-
- List<UserInfo> users = mUm.getUsers();
- final int count = users.size() * volumeApps.size();
- if (count == 0) {
- mStats.complete(new ArrayList<>());
- }
-
List<PackageStats> stats = new ArrayList<>();
- for (UserInfo user : users) {
- for (ApplicationInfo app : volumeApps) {
- PackageStats packageStats = new PackageStats(app.packageName, user.id);
- StorageStats storageStats = mStorageStatsManager.queryStatsForPackage(
- app.volumeUuid, app.packageName, user.getUserHandle());
- packageStats.cacheSize = storageStats.getCacheBytes();
- packageStats.codeSize = storageStats.getCodeBytes();
- packageStats.dataSize = storageStats.getDataBytes();
- stats.add(packageStats);
+ List<UserInfo> users = mUm.getUsers();
+ for (int userCount = 0, userSize = users.size();
+ userCount < userSize; userCount++) {
+ UserInfo user = users.get(userCount);
+ final List<ApplicationInfo> apps = mPm.getInstalledApplicationsAsUser(
+ PackageManager.MATCH_DISABLED_COMPONENTS, user.id);
+
+ for (int appCount = 0, size = apps.size(); appCount < size; appCount++) {
+ ApplicationInfo app = apps.get(appCount);
+ if (!Objects.equals(app.volumeUuid, mVolume.getFsUuid())) {
+ continue;
+ }
+
+ try {
+ StorageStats storageStats =
+ mStorageStatsManager.queryStatsForPackage(app.volumeUuid,
+ app.packageName, user.getUserHandle());
+ PackageStats packageStats = new PackageStats(app.packageName,
+ user.id);
+ packageStats.cacheSize = storageStats.getCacheBytes();
+ packageStats.codeSize = storageStats.getCodeBytes();
+ packageStats.dataSize = storageStats.getDataBytes();
+ stats.add(packageStats);
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "An exception occurred while fetching app size", e);
+ }
}
}
diff --git a/services/core/java/com/android/server/vr/CompatibilityDisplay.java b/services/core/java/com/android/server/vr/CompatibilityDisplay.java
index c54fd9a..5e17daa 100644
--- a/services/core/java/com/android/server/vr/CompatibilityDisplay.java
+++ b/services/core/java/com/android/server/vr/CompatibilityDisplay.java
@@ -156,7 +156,7 @@
mVirtualDisplay = mDisplayManager.createVirtualDisplay("VR 2D Display", WIDTH, HEIGHT,
DPI, null /* Surface */, 0 /* flags */);
- if (mSurface != null && mSurface.isValid()) {
+ if (mVirtualDisplay != null && mSurface != null && mSurface.isValid()) {
// TODO: Need to protect all setSurface calls with a lock.
mVirtualDisplay.setSurface(mSurface);
}
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
index 83e77ec..9e95eec 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
@@ -625,26 +625,52 @@
return v1 >= v2;
}
- /**
- * Returns whether this provider is valid for use as a WebView provider.
- */
- public boolean isValidProvider(WebViewProviderInfo configInfo,
- PackageInfo packageInfo) {
+ private final static int VALIDITY_OK = 0;
+ private final static int VALIDITY_INCORRECT_SDK_VERSION = 1;
+ private final static int VALIDITY_INCORRECT_VERSION_CODE = 2;
+ private final static int VALIDITY_INCORRECT_SIGNATURE = 3;
+ private final static int VALIDITY_NO_LIBRARY_FLAG = 4;
+
+ private static String getInvalidityReason(int invalidityReason) {
+ switch (invalidityReason) {
+ case VALIDITY_INCORRECT_SDK_VERSION:
+ return "SDK version too low";
+ case VALIDITY_INCORRECT_VERSION_CODE:
+ return "Version code too low";
+ case VALIDITY_INCORRECT_SIGNATURE:
+ return "Incorrect signature";
+ case VALIDITY_NO_LIBRARY_FLAG:
+ return "No WebView-library manifest flag";
+ default:
+ return "Unexcepted validity-reason";
+ }
+ }
+
+ private int validityResult(WebViewProviderInfo configInfo, PackageInfo packageInfo) {
// Ensure the provider targets this framework release (or a later one).
if (!UserPackage.hasCorrectTargetSdkVersion(packageInfo)) {
- return false;
+ return VALIDITY_INCORRECT_SDK_VERSION;
}
if (!versionCodeGE(packageInfo.versionCode, getMinimumVersionCode())
&& !mSystemInterface.systemIsDebuggable()) {
// Webview providers may be downgraded arbitrarily low, prevent that by enforcing
// minimum version code. This check is only enforced for user builds.
- return false;
+ return VALIDITY_INCORRECT_VERSION_CODE;
}
- if (providerHasValidSignature(configInfo, packageInfo, mSystemInterface) &&
- WebViewFactory.getWebViewLibrary(packageInfo.applicationInfo) != null) {
- return true;
+ if (!providerHasValidSignature(configInfo, packageInfo, mSystemInterface)) {
+ return VALIDITY_INCORRECT_SIGNATURE;
}
- return false;
+ if (WebViewFactory.getWebViewLibrary(packageInfo.applicationInfo) == null) {
+ return VALIDITY_NO_LIBRARY_FLAG;
+ }
+ return VALIDITY_OK;
+ }
+
+ /**
+ * Returns whether this provider is valid for use as a WebView provider.
+ */
+ public boolean isValidProvider(WebViewProviderInfo configInfo, PackageInfo packageInfo) {
+ return VALIDITY_OK == validityResult(configInfo, packageInfo);
}
/**
@@ -699,6 +725,53 @@
pw.println(String.format(" WebView package dirty: %b", mWebViewPackageDirty));
pw.println(String.format(" Any WebView package installed: %b",
mAnyWebViewInstalled));
+
+ try {
+ PackageInfo preferredWebViewPackage = findPreferredWebViewPackage();
+ pw.println(String.format(
+ " Preferred WebView package (name, version): (%s, %s)",
+ preferredWebViewPackage.packageName,
+ preferredWebViewPackage.versionName));
+ } catch (WebViewPackageMissingException e) {
+ pw.println(String.format(" Preferred WebView package: none"));
+ }
+
+ dumpAllPackageInformationLocked(pw);
+ }
+ }
+
+ private void dumpAllPackageInformationLocked(PrintWriter pw) {
+ WebViewProviderInfo[] allProviders = mSystemInterface.getWebViewPackages();
+ pw.println(" WebView packages:");
+ for (WebViewProviderInfo provider : allProviders) {
+ List<UserPackage> userPackages =
+ mSystemInterface.getPackageInfoForProviderAllUsers(mContext, provider);
+ PackageInfo systemUserPackageInfo =
+ userPackages.get(UserHandle.USER_SYSTEM).getPackageInfo();
+ if (systemUserPackageInfo == null) {
+ continue;
+ }
+
+ int validity = validityResult(provider, systemUserPackageInfo);
+ String packageDetails = String.format(
+ "versionName: %s, versionCode: %d, targetSdkVersion: %d",
+ systemUserPackageInfo.versionName,
+ systemUserPackageInfo.versionCode,
+ systemUserPackageInfo.applicationInfo.targetSdkVersion);
+ if (validity == VALIDITY_OK) {
+ boolean installedForAllUsers = isInstalledAndEnabledForAllUsers(
+ mSystemInterface.getPackageInfoForProviderAllUsers(mContext, provider));
+ pw.println(String.format(
+ " Valid package %s (%s) is %s installed/enabled for all users",
+ systemUserPackageInfo.packageName,
+ packageDetails,
+ installedForAllUsers ? "" : "NOT"));
+ } else {
+ pw.println(String.format(" Invalid package %s (%s), reason: %s",
+ systemUserPackageInfo.packageName,
+ packageDetails,
+ getInvalidityReason(validity)));
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/AlertWindowNotification.java b/services/core/java/com/android/server/wm/AlertWindowNotification.java
index b7b419b..efc92cf 100644
--- a/services/core/java/com/android/server/wm/AlertWindowNotification.java
+++ b/services/core/java/com/android/server/wm/AlertWindowNotification.java
@@ -19,9 +19,9 @@
import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
import static android.content.Context.NOTIFICATION_SERVICE;
-import static android.content.Intent.EXTRA_PACKAGE_NAME;
-import static android.content.Intent.EXTRA_UID;
-import static com.android.server.wm.WindowManagerService.ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION;
+import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.provider.Settings.ACTION_MANAGE_OVERLAY_PERMISSION;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -35,6 +35,7 @@
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
+import android.net.Uri;
import com.android.internal.R;
import com.android.server.policy.IconUtilities;
@@ -49,14 +50,12 @@
private String mNotificationTag;
private final NotificationManager mNotificationManager;
private final String mPackageName;
- private final int mUid;
private boolean mCancelled;
private IconUtilities mIconUtilities;
- AlertWindowNotification(WindowManagerService service, String packageName, int uid) {
+ AlertWindowNotification(WindowManagerService service, String packageName) {
mService = service;
mPackageName = packageName;
- mUid = uid;
mNotificationManager =
(NotificationManager) mService.mContext.getSystemService(NOTIFICATION_SERVICE);
mNotificationTag = CHANNEL_PREFIX + mPackageName;
@@ -96,7 +95,8 @@
createNotificationChannelIfNeeded(context, appName);
- final String message = context.getString(R.string.alert_windows_notification_message);
+ final String message = context.getString(R.string.alert_windows_notification_message,
+ appName);
final Notification.Builder builder = new Notification.Builder(context, mNotificationTag)
.setOngoing(true)
.setContentTitle(
@@ -106,7 +106,7 @@
.setColor(context.getColor(R.color.system_notification_accent_color))
.setStyle(new Notification.BigTextStyle().bigText(message))
.setLocalOnly(true)
- .addAction(getTurnOffAction(context, mPackageName, mUid));
+ .setContentIntent(getContentIntent(context, mPackageName));
if (aInfo != null) {
final Drawable drawable = pm.getApplicationIcon(aInfo);
@@ -119,17 +119,12 @@
mNotificationManager.notify(mNotificationTag, NOTIFICATION_ID, builder.build());
}
- private Notification.Action getTurnOffAction(Context context, String packageName, int uid) {
- final Intent intent = new Intent(ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION);
- intent.putExtra(EXTRA_PACKAGE_NAME, packageName);
- intent.putExtra(EXTRA_UID, uid);
+ private PendingIntent getContentIntent(Context context, String packageName) {
+ final Intent intent = new Intent(ACTION_MANAGE_OVERLAY_PERMISSION,
+ Uri.fromParts("package", packageName, null));
+ intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
// Calls into activity manager...
- final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, mRequestCode,
- intent, FLAG_CANCEL_CURRENT);
- return new Notification.Action.Builder(R.drawable.alert_window_layer,
- context.getString(R.string.alert_windows_notification_turn_off_action),
- pendingIntent).build();
-
+ return PendingIntent.getActivity(context, mRequestCode, intent, FLAG_CANCEL_CURRENT);
}
private void createNotificationChannelIfNeeded(Context context, String appName) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 647adbf..4aa013a 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -785,6 +785,16 @@
if (canFreezeBounds()) {
freezeBounds();
}
+
+ // In the process of tearing down before relaunching, the app will
+ // try and clean up it's child surfaces. We need to prevent this from
+ // happening, so we sever the children, transfering their ownership
+ // from the client it-self to the parent surface (owned by us).
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState w = mChildren.get(i);
+ w.mWinAnimator.detachChildren();
+ }
+
mPendingRelaunchCount++;
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 461c3fa..5486aa8 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1584,24 +1584,9 @@
// TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
// same display. Or even when the current IME/target are not on the same screen as the next
// IME/target. For now only look for input windows on the main screen.
+ mUpdateImeTarget = updateImeTarget;
+ WindowState target = getWindow(mComputeImeTargetPredicate);
- // The target candidate provided by the IME tells us which window token, but not which
- // window within the token (e.g. child windows...). So, we use the token to look-up the
- // best target window.
- // TODO: Have the input method service report the right window with the token vs. just the
- // base window of the token.
- final WindowState baseWin = mService.getWindow(mService.mInputMethodTargetCandidate);
- final WindowToken targetToken = baseWin != null ? baseWin.mToken : null;
- WindowState target = targetToken != null ?
- targetToken.getWindow(mComputeImeTargetPredicate) : null;
- // If there isn't a better candidate in the token (maybe because they are not visible), then
- // fall back to targeting the base window of the token, so the IME can still maintain the
- // right z-order based on the last person that set it vs. changing its z-order to the very
- // up since there if target is null.
- // TODO: Consider z-ordering IME to bottom instead of top if there is no visible target.
- // Also, consider tying the visible the visibility of the IME to the current target. I.e if
- // target isn't visible, then IME shouldn't be visible.
- target = target == null ? baseWin : target;
// Yet more tricksyness! If this window is a "starting" window, we do actually want
// to be on top of it, but it is not -really- where input will go. So look down below
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index aa8e377..fc37797 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -109,7 +109,6 @@
private final Rect mTmpRect2 = new Rect();
private final Rect mTmpRect3 = new Rect();
private final Rect mLastRect = new Rect();
- private final Rect mMiddlePositionDockedStackRect = new Rect();
private boolean mLastVisibility = false;
private final RemoteCallbackList<IDockedStackListener> mDockedStackListeners
= new RemoteCallbackList<>();
@@ -186,16 +185,6 @@
return (int) (minWidth / mDisplayContent.getDisplayMetrics().density);
}
- /**
- * The middlePositionDockedStackRect is half the screen area that sits at the top (portrait) or
- * left (landscape).
- *
- * @return fixed rect for temp stack
- */
- Rect getMiddlePositionDockedStackRect() {
- return mMinimizedDock && isHomeStackResizable() ? mMiddlePositionDockedStackRect : null;
- }
-
void getHomeStackBoundsInDockedMode(Rect outBounds) {
final DisplayInfo di = mDisplayContent.getDisplayInfo();
mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
@@ -264,29 +253,8 @@
initSnapAlgorithmForRotations();
}
- /**
- * Calculates the constant rects {@link mMiddlePositionDockedStackRect} based on orientation,
- * stable insets and display size.
- */
- private void updateConstantRects() {
- final DisplayInfo di = mDisplayContent.getDisplayInfo();
- mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
- mTmpRect);
- int dividerSize = mDividerWindowWidth - 2 * mDividerInsets;
- Configuration configuration = mDisplayContent.getConfiguration();
- boolean isHorizontal = configuration.orientation == Configuration.ORIENTATION_PORTRAIT;
- int middlePosition = DockedDividerUtils.calculateMiddlePosition(isHorizontal, mTmpRect,
- di.logicalWidth, di.logicalHeight, dividerSize);
- if (isHorizontal) {
- mMiddlePositionDockedStackRect.set(0, 0, di.logicalWidth, middlePosition);
- } else {
- mMiddlePositionDockedStackRect.set(0, 0, middlePosition, di.logicalHeight);
- }
- }
-
void onConfigurationChanged() {
loadDimens();
- updateConstantRects();
}
boolean isResizing() {
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 1d50d0d..0e6b1b6 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -108,6 +108,7 @@
private final DisplayMetrics mTmpMetrics = new DisplayMetrics();
private final Rect mTmpInsets = new Rect();
private final Rect mTmpRect = new Rect();
+ private final Rect mTmpAnimatingBoundsRect = new Rect();
private final Point mTmpDisplaySize = new Point();
/**
@@ -359,7 +360,7 @@
if (isValidPictureInPictureAspectRatio(mAspectRatio)) {
transformBoundsToAspectRatio(normalBounds, mAspectRatio);
}
- final Rect animatingBounds = mTmpRect;
+ final Rect animatingBounds = mTmpAnimatingBoundsRect;
final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID);
if (pinnedStack != null) {
pinnedStack.getAnimatingBounds(animatingBounds);
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 720a454..b7a9e66 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -601,8 +601,7 @@
if (mAlertWindowSurfaces.isEmpty()) {
cancelAlertWindowNotification();
} else if (mAlertWindowNotification == null){
- mAlertWindowNotification = new AlertWindowNotification(
- mService, mPackageName, mUid);
+ mAlertWindowNotification = new AlertWindowNotification(mService, mPackageName);
}
}
}
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index b0e115b..8186d30 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -199,17 +199,19 @@
}
}
- public void getStackDockedModeBounds(Rect outBounds, Rect outTempBounds,
- Rect outTempInsetBounds, boolean ignoreVisibility) {
+ /**
+ * @see TaskStack.getStackDockedModeBoundsLocked(Rect, Rect, Rect, boolean)
+ */
+ public void getStackDockedModeBounds(Rect currentTempTaskBounds, Rect outStackBounds,
+ Rect outTempTaskBounds, boolean ignoreVisibility) {
synchronized (mWindowMap) {
if (mContainer != null) {
- mContainer.getStackDockedModeBoundsLocked(outBounds, outTempBounds,
- outTempInsetBounds, ignoreVisibility);
+ mContainer.getStackDockedModeBoundsLocked(currentTempTaskBounds, outStackBounds,
+ outTempTaskBounds, ignoreVisibility);
return;
}
- outBounds.setEmpty();
- outTempBounds.setEmpty();
- outTempInsetBounds.setEmpty();
+ outStackBounds.setEmpty();
+ outTempTaskBounds.setEmpty();
}
}
@@ -241,9 +243,9 @@
}
}
- public void getBoundsForNewConfiguration(Rect outBounds, Rect outTempBounds) {
+ public void getBoundsForNewConfiguration(Rect outBounds) {
synchronized(mWindowMap) {
- mContainer.getBoundsForNewConfiguration(outBounds, outTempBounds);
+ mContainer.getBoundsForNewConfiguration(outBounds);
}
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 9f34bd7..76fb522 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -151,21 +151,7 @@
}
private void drawSnapshot(GraphicBuffer snapshot) {
-
- // TODO: Just wrap the buffer here without any copying.
- final Canvas c = mSurface.lockHardwareCanvas();
- final Bitmap b = Bitmap.createHardwareBitmap(snapshot);
- fillEmptyBackground(c, b);
- c.drawBitmap(b, 0, 0, null);
- mSurface.unlockCanvasAndPost(c);
- final boolean reportNextDraw;
- synchronized (mService.mWindowMap) {
- mHasDrawn = true;
- reportNextDraw = mReportNextDraw;
- }
- if (reportNextDraw) {
- reportDrawn();
- }
+ mSurface.attachAndQueueBuffer(snapshot);
mSurface.release();
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 7588b71..442cd54 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -429,18 +429,9 @@
return true;
}
- void getBoundsForNewConfiguration(Rect outBounds, Rect outTempBounds) {
+ void getBoundsForNewConfiguration(Rect outBounds) {
outBounds.set(mBoundsAfterRotation);
mBoundsAfterRotation.setEmpty();
- final DockedStackDividerController controller = getDisplayContent()
- .mDividerControllerLocked;
- if (mStackId == DOCKED_STACK_ID) {
- final Rect dockedStackRect = controller.getMiddlePositionDockedStackRect();
-
- if (dockedStackRect != null) {
- outTempBounds.set(dockedStackRect);
- }
- }
}
/**
@@ -686,21 +677,42 @@
super.onDisplayChanged(dc);
}
- void getStackDockedModeBoundsLocked(Rect outBounds, Rect outTempBounds,
- Rect outTempInsetBounds, boolean ignoreVisibility) {
+ /**
+ * Determines the stack and task bounds of the other stack when in docked mode. The current task
+ * bounds is passed in but depending on the stack, the task and stack must match. Only in
+ * minimized mode with resizable launcher, the other stack ignores calculating the stack bounds
+ * and uses the task bounds passed in as the stack and task bounds, otherwise the stack bounds
+ * is calculated and is also used for its task bounds.
+ * If any of the out bounds are empty, it represents default bounds
+ *
+ * @param currentTempTaskBounds the current task bounds of the other stack
+ * @param outStackBounds the calculated stack bounds of the other stack
+ * @param outTempTaskBounds the calculated task bounds of the other stack
+ * @param ignoreVisibility ignore visibility in getting the stack bounds
+ */
+ void getStackDockedModeBoundsLocked(Rect currentTempTaskBounds, Rect outStackBounds,
+ Rect outTempTaskBounds, boolean ignoreVisibility) {
+ outTempTaskBounds.setEmpty();
+
+ // When the home stack is resizable, should always have the same stack and task bounds
if (mStackId == HOME_STACK_ID && findHomeTask().isResizeable()) {
// Calculate the home stack bounds when in docked mode
getDisplayContent().mDividerControllerLocked
- .getHomeStackBoundsInDockedMode(outTempBounds);
- outTempInsetBounds.set(outTempBounds);
- } else {
- outTempBounds.setEmpty();
- outTempInsetBounds.setEmpty();
+ .getHomeStackBoundsInDockedMode(outStackBounds);
+ outTempTaskBounds.set(outStackBounds);
+ return;
+ }
+
+ // When minimized state, the stack bounds for all non-home and docked stack bounds should
+ // match the passed task bounds
+ if (isMinimizedDockAndHomeStackResizable() && currentTempTaskBounds != null) {
+ outStackBounds.set(currentTempTaskBounds);
+ return;
}
if ((mStackId != DOCKED_STACK_ID && !StackId.isResizeableByDockedStack(mStackId))
|| mDisplayContent == null) {
- outBounds.set(mBounds);
+ outStackBounds.set(mBounds);
return;
}
@@ -714,7 +726,7 @@
// The docked stack is being dismissed, but we caught before it finished being
// dismissed. In that case we want to treat it as if it is not occupying any space and
// let others occupy the whole display.
- mDisplayContent.getLogicalDisplayRect(outBounds);
+ mDisplayContent.getLogicalDisplayRect(outStackBounds);
return;
}
@@ -722,14 +734,14 @@
if (dockedSide == DOCKED_INVALID) {
// Not sure how you got here...Only thing we can do is return current bounds.
Slog.e(TAG_WM, "Failed to get valid docked side for docked stack=" + dockedStack);
- outBounds.set(mBounds);
+ outStackBounds.set(mBounds);
return;
}
mDisplayContent.getLogicalDisplayRect(mTmpRect);
dockedStack.getRawBounds(mTmpRect2);
final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT;
- getStackDockedModeBounds(mTmpRect, outBounds, mStackId, mTmpRect2,
+ getStackDockedModeBounds(mTmpRect, outStackBounds, mStackId, mTmpRect2,
mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
}
@@ -812,8 +824,8 @@
final Rect bounds = new Rect();
final Rect tempBounds = new Rect();
- final Rect tempInsetBounds = new Rect();
- getStackDockedModeBoundsLocked(bounds, tempBounds, tempInsetBounds, true /*ignoreVisibility*/);
+ getStackDockedModeBoundsLocked(null /* currentTempTaskBounds */, bounds, tempBounds,
+ true /*ignoreVisibility*/);
getController().requestResize(bounds);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8b859d1..c0cc923 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.MANAGE_APP_TOKENS;
import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
@@ -29,6 +30,7 @@
import static android.content.Intent.EXTRA_UID;
import static android.content.Intent.EXTRA_USER_HANDLE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.UserHandle.USER_NULL;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.DOCKED_INVALID;
@@ -67,6 +69,8 @@
import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END;
import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START;
+import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
+import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
import static com.android.server.wm.KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
@@ -108,6 +112,7 @@
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.IActivityManager;
+import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -346,9 +351,6 @@
final private KeyguardDisableHandler mKeyguardDisableHandler;
- static final String ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION =
- "com.android.server.wm.ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION";
-
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -364,16 +366,6 @@
}
}
break;
- case ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION:
- final String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME);
- final int uid = intent.getIntExtra(EXTRA_UID, -1);
- if (packageName != null && uid != -1) {
- synchronized (mWindowMap) {
- // Revoke permission.
- mAppOps.setMode(OP_SYSTEM_ALERT_WINDOW, uid, packageName, MODE_IGNORED);
- }
- }
- break;
}
}
};
@@ -623,14 +615,9 @@
WindowState mCurrentFocus = null;
WindowState mLastFocus = null;
- // TODO: All the IME window tracking should be moved to DisplayContent and tracked per display.
- // This just indicates the window the input method is on top of, not necessarily the window its
- // input is going to.
+ /** This just indicates the window the input method is on top of, not
+ * necessarily the window its input is going to. */
WindowState mInputMethodTarget = null;
- // The binder token currently using the IME as determined by the input method service.
- // Window manager uses this to determine the final input method target
- // (almost always this candidate) for z-ordering.
- IBinder mInputMethodTargetCandidate = null;
/** If true hold off on modifying the animation layer of mInputMethodTarget */
boolean mInputMethodTargetWaitingAnim;
@@ -1070,7 +1057,6 @@
filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
// Listen to user removal broadcasts so that we can remove the user-specific data.
filter.addAction(Intent.ACTION_USER_REMOVED);
- filter.addAction(ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION);
mContext.registerReceiver(mBroadcastReceiver, filter);
mSettingsObserver = new SettingsObserver();
@@ -2212,6 +2198,15 @@
if (mAccessibilityController != null && win.getDisplayId() == DEFAULT_DISPLAY) {
mAccessibilityController.onWindowTransitionLocked(win, transit);
}
+
+ // When we start the exit animation we take the Surface from the client
+ // so it will stop perturbing it. We need to likewise takeaway the SurfaceFlinger
+ // side child surfaces, so they will remain preserved in their current state
+ // (rather than be cleaned up immediately by the app code).
+ SurfaceControl.openTransaction();
+ winAnimator.detachChildren();
+ SurfaceControl.closeTransaction();
+
return focusMayChange;
}
@@ -6964,9 +6959,8 @@
pw.print(" mLastFocus="); pw.println(mLastFocus);
}
pw.print(" mFocusedApp="); pw.println(mFocusedApp);
- if (mInputMethodTarget != null || mInputMethodTargetCandidate != null) {
- pw.println(" mInputMethodTarget=" + mInputMethodTarget
- + " mInputMethodTargetCandidate=" + getWindow(mInputMethodTargetCandidate));
+ if (mInputMethodTarget != null) {
+ pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget);
}
pw.print(" mInTouchMode="); pw.print(mInTouchMode);
pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
@@ -7833,28 +7827,11 @@
@Override
public void updateInputMethodWindowStatus(@NonNull IBinder imeToken,
boolean imeWindowVisible, @Nullable IBinder targetWindowToken) {
- synchronized (mWindowMap) {
- final WindowState newTargetWin = getWindow(targetWindowToken);
- final WindowState currentTargetWin = getWindow(mInputMethodTargetCandidate);
-
- if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "updateInputMethodWindowStatus: imeToken="
- + imeToken + " imeWindowVisible=" + imeWindowVisible
- + " targetWindowToken=" + targetWindowToken
- + " newTargetWin=" + newTargetWin
- + " currentTargetWin=" + currentTargetWin);
-
- if (newTargetWin == currentTargetWin) {
- return;
- }
-
- final DisplayContent dc = newTargetWin != null
- ? newTargetWin.getDisplayContent() : currentTargetWin.getDisplayContent();
-
- // It is possible the window for the target candidate isn't added yet, so we
- // remember the token instead and use it to look-up the window each time we compute
- // the ime target.
- mInputMethodTargetCandidate = targetWindowToken;
- dc.computeImeTarget(true /* updateImeTarget */);
+ // TODO (b/34628091): Use this method to address the window animation issue.
+ if (DEBUG_INPUT_METHOD) {
+ Slog.w(TAG_WM, "updateInputMethodWindowStatus: imeToken=" + imeToken
+ + " imeWindowVisible=" + imeWindowVisible
+ + " targetWindowToken=" + targetWindowToken);
}
}
@@ -7900,10 +7877,6 @@
}
}
- WindowState getWindow(IBinder binder) {
- return binder == null ? null : mWindowMap.get(binder);
- }
-
void registerAppFreezeListener(AppFreezeListener listener) {
if (!mAppFreezeListeners.contains(listener)) {
mAppFreezeListeners.add(listener);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 6d572d7..7825903 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -74,7 +74,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
@@ -82,7 +81,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -1532,6 +1530,13 @@
return changed;
}
+ // Next up we will notify the client that it's visibility has changed.
+ // We need to prevent it from destroying child surfaces until
+ // the animation has finished.
+ if (!visible && isVisibleNow()) {
+ mWinAnimator.detachChildren();
+ }
+
if (visible != isVisibleNow()) {
if (!runningAppAnimation) {
final AccessibilityController accessibilityController =
@@ -3832,6 +3837,8 @@
windowInfo.title = mAttrs.accessibilityTitle;
windowInfo.accessibilityIdOfAnchor = mAttrs.accessibilityIdOfAnchor;
windowInfo.focused = isFocused();
+ Task task = getTask();
+ windowInfo.inPictureInPicture = (task != null) && task.inPinnedWorkspace();
if (mIsChildWindow) {
windowInfo.parentToken = getParentWindow().mClient.asBinder();
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 98598e1..4b71338 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -566,6 +566,20 @@
if (!mDestroyPreservedSurfaceUponRedraw) {
return;
}
+ if (mSurfaceController != null) {
+ if (mPendingDestroySurface != null) {
+ // If we are preserving a surface but we aren't relaunching that means
+ // we are just doing an in-place switch. In that case any SurfaceFlinger side
+ // child layers need to be reparented to the new surface to make this
+ // transparent to the app.
+ if (mWin.mAppToken == null || mWin.mAppToken.isRelaunching() == false) {
+ SurfaceControl.openTransaction();
+ mPendingDestroySurface.reparentChildrenInTransaction(mSurfaceController);
+ SurfaceControl.closeTransaction();
+ }
+ }
+ }
+
destroyDeferredSurfaceLocked();
mDestroyPreservedSurfaceUponRedraw = false;
}
@@ -1965,4 +1979,10 @@
}
return mForceScaleUntilResize;
}
+
+ void detachChildren() {
+ if (mSurfaceController != null) {
+ mSurfaceController.detachChildren();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index f8e7428..f7d3343 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -135,6 +135,20 @@
}
}
+ void reparentChildrenInTransaction(WindowSurfaceController other) {
+ if (SHOW_TRANSACTIONS) Slog.i(TAG, "REPARENT from: " + this + " to: " + other);
+ if ((mSurfaceControl != null) && (other.mSurfaceControl != null)) {
+ mSurfaceControl.reparentChildren(other.getHandle());
+ }
+ }
+
+ void detachChildren() {
+ if (SHOW_TRANSACTIONS) Slog.i(TAG, "SEVER CHILDREN");
+ if (mSurfaceControl != null) {
+ mSurfaceControl.detachChildren();
+ }
+ }
+
void hideInTransaction(String reason) {
if (SHOW_TRANSACTIONS) logSurface("HIDE ( " + reason + " )", null);
mHiddenForOtherReasons = true;
diff --git a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
index ad64e4e..e6e2cb3 100644
--- a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
+++ b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
@@ -141,7 +141,7 @@
}
private ServiceConnection getServiceConnection(
- final AssociationRequest<?> request,
+ final AssociationRequest request,
final IFindDeviceCallback findDeviceCallback,
final String callingPackage) {
return new ServiceConnection() {
diff --git a/services/tests/notification/Android.mk b/services/tests/notification/Android.mk
index bc37fef..de9553a 100644
--- a/services/tests/notification/Android.mk
+++ b/services/tests/notification/Android.mk
@@ -27,6 +27,8 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_JACK_FLAGS := --multi-dex native
+
LOCAL_PACKAGE_NAME := FrameworksNotificationTests
LOCAL_CERTIFICATE := platform
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 3f34d4f..a9b2ae5 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -594,19 +594,19 @@
@Test
public void testUidForeground() throws Exception {
// push all uids into background
- mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE);
- mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_SERVICE);
+ mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE, 0);
+ mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_SERVICE, 0);
assertFalse(mService.isUidForeground(UID_A));
assertFalse(mService.isUidForeground(UID_B));
// push one of the uids into foreground
- mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_TOP);
+ mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_TOP, 0);
assertTrue(mService.isUidForeground(UID_A));
assertFalse(mService.isUidForeground(UID_B));
// and swap another uid into foreground
- mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE);
- mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_TOP);
+ mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE, 0);
+ mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_TOP, 0);
assertFalse(mService.isUidForeground(UID_A));
assertTrue(mService.isUidForeground(UID_B));
}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index 38c6b0d..6cca771 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -314,8 +314,8 @@
final Bundle bundle = new Bundle();
bundle.putParcelable(EXTRA_RECOMMENDATION_RESULT, providerResult);
doAnswer(invocation -> {
- bundle.putInt(EXTRA_SEQUENCE, invocation.getArgumentAt(2, int.class));
- invocation.getArgumentAt(1, IRemoteCallback.class).sendResult(bundle);
+ bundle.putInt(EXTRA_SEQUENCE, invocation.getArgument(2));
+ invocation.<IRemoteCallback>getArgument(1).sendResult(bundle);
return null;
}).when(mRecommendationProvider)
.requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
@@ -379,7 +379,7 @@
injectProvider();
final Bundle bundle = new Bundle();
doAnswer(invocation -> {
- invocation.getArgumentAt(1, IRemoteCallback.class).sendResult(bundle);
+ invocation.<IRemoteCallback>getArgument(1).sendResult(bundle);
return null;
}).when(mRecommendationProvider)
.requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
@@ -956,7 +956,7 @@
IBinder mockBinder = mock(IBinder.class);
when(mockBinder.queryLocalInterface(anyString()))
.thenReturn(mRecommendationProvider);
- invocation.getArgumentAt(1, ServiceConnection.class)
+ invocation.<ServiceConnection>getArgument(1)
.onServiceConnected(NEW_SCORER.getRecommendationServiceComponent(),
mockBinder);
return true;
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
index 64f176a..e8663a2 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
@@ -50,10 +50,10 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import org.mockito.compat.ArgumentMatcher;
import java.util.ArrayList;
import java.util.List;
@@ -77,7 +77,7 @@
when(mMockContext.getPackageManager()).thenReturn(mMockPm);
when(mMockPm.queryIntentServices(Mockito.argThat(new ArgumentMatcher<Intent>() {
@Override
- public boolean matches(Object object) {
+ public boolean matchesObject(Object object) {
Intent intent = (Intent) object;
return NetworkScoreManager.ACTION_RECOMMEND_NETWORKS.equals(intent.getAction());
}
@@ -395,7 +395,7 @@
when(mMockPm.resolveService(
Mockito.argThat(new ArgumentMatcher<Intent>() {
@Override
- public boolean matches(Object object) {
+ public boolean matchesObject(Object object) {
Intent intent = (Intent) object;
return NetworkScoreManager.ACTION_RECOMMEND_NETWORKS
.equals(intent.getAction())
@@ -416,7 +416,7 @@
when(mMockPm.resolveActivity(
Mockito.argThat(new ArgumentMatcher<Intent>() {
@Override
- public boolean matches(Object object) {
+ public boolean matchesObject(Object object) {
Intent intent = (Intent) object;
return NetworkScoreManager.ACTION_CUSTOM_ENABLE.equals(intent.getAction())
&& useOpenWifiComp.getPackageName().equals(intent.getPackage());
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/ActionReplacingCallbackTest.java b/services/tests/servicestests/src/com/android/server/accessibility/ActionReplacingCallbackTest.java
new file mode 100644
index 0000000..8afe853
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/ActionReplacingCallbackTest.java
@@ -0,0 +1,279 @@
+/*
+ * 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.accessibility;
+
+import android.graphics.Region;
+import android.os.RemoteException;
+import android.view.MagnificationSpec;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+import android.view.accessibility.AccessibilityWindowInfo;
+import android.view.accessibility.IAccessibilityInteractionConnection;
+import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS;
+import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS;
+import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK;
+import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_COLLAPSE;
+import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND;
+import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_CONTEXT_CLICK;
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+/**
+ * Tests for ActionReplacingCallback
+ */
+public class ActionReplacingCallbackTest {
+ private static final int INTERACTION_ID = 0xBEEF;
+ private static final int INTERROGATING_PID = 0xFEED;
+ private static final int APP_WINDOW_ID = 0xACE;
+ private static final int NON_ROOT_NODE_ID = 0xAAAA5555;
+ private static final long INTERROGATING_TID = 0x1234FACE;
+
+ private static final AccessibilityAction[] ACTIONS_FROM_REPLACER =
+ {ACTION_CLICK, ACTION_EXPAND};
+ private static final AccessibilityAction[] A11Y_FOCUS_ACTIONS =
+ {ACTION_ACCESSIBILITY_FOCUS, ACTION_CLEAR_ACCESSIBILITY_FOCUS};
+ // We expect both the replacer actions and a11y focus actions to appear
+ private static final AccessibilityAction[] REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE =
+ {ACTION_CLICK, ACTION_EXPAND, ACTION_ACCESSIBILITY_FOCUS,
+ ACTION_CLEAR_ACCESSIBILITY_FOCUS};
+
+ @Mock IAccessibilityInteractionConnectionCallback mMockServiceCallback;
+ @Mock IAccessibilityInteractionConnection mMockReplacerConnection;
+
+ @Captor private ArgumentCaptor<Integer> mInteractionIdCaptor;
+ @Captor private ArgumentCaptor<AccessibilityNodeInfo> mInfoCaptor;
+ @Captor private ArgumentCaptor<List<AccessibilityNodeInfo>> mInfoListCaptor;
+
+ private ActionReplacingCallback mActionReplacingCallback;
+ private int mReplacerInteractionId;
+
+ @Before
+ public void setUp() throws RemoteException {
+ initMocks(this);
+ mActionReplacingCallback = new ActionReplacingCallback(
+ mMockServiceCallback, mMockReplacerConnection, INTERACTION_ID, INTERROGATING_PID,
+ INTERROGATING_TID);
+ verify(mMockReplacerConnection).findAccessibilityNodeInfoByAccessibilityId(
+ eq(AccessibilityNodeInfo.ROOT_NODE_ID), (Region) anyObject(),
+ mInteractionIdCaptor.capture(), eq(mActionReplacingCallback), eq(0),
+ eq(INTERROGATING_PID), eq(INTERROGATING_TID), (MagnificationSpec) anyObject(),
+ eq(null));
+ mReplacerInteractionId = mInteractionIdCaptor.getValue().intValue();
+ }
+
+ @Test
+ public void testConstructor_registersToGetRootNodeOfActionReplacer() throws RemoteException {
+ assertNotEquals(INTERACTION_ID, mReplacerInteractionId);
+ verifyNoMoreInteractions(mMockServiceCallback);
+ }
+
+ @Test
+ public void testCallbacks_singleRootNodeThenReplacer_returnsNodeWithReplacedActions()
+ throws RemoteException {
+ AccessibilityNodeInfo infoFromApp = AccessibilityNodeInfo.obtain();
+ infoFromApp.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID, APP_WINDOW_ID);
+ infoFromApp.addAction(ACTION_CONTEXT_CLICK);
+ mActionReplacingCallback.setFindAccessibilityNodeInfoResult(infoFromApp, INTERACTION_ID);
+ verifyNoMoreInteractions(mMockServiceCallback);
+
+ mActionReplacingCallback.setFindAccessibilityNodeInfosResult(getReplacerNodes(),
+ mReplacerInteractionId);
+
+ verify(mMockServiceCallback).setFindAccessibilityNodeInfoResult(mInfoCaptor.capture(),
+ eq(INTERACTION_ID));
+ AccessibilityNodeInfo infoSentToService = mInfoCaptor.getValue();
+ assertEquals(AccessibilityNodeInfo.ROOT_NODE_ID, infoSentToService.getSourceNodeId());
+ assertInfoHasExactlyTheseActions(infoSentToService, REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE);
+ }
+
+ public void testCallbacks_singleNonrootNodeThenReplacer_returnsNodeWithNoActions()
+ throws RemoteException {
+ AccessibilityNodeInfo infoFromApp = AccessibilityNodeInfo.obtain();
+ infoFromApp.setSourceNodeId(NON_ROOT_NODE_ID, APP_WINDOW_ID);
+ infoFromApp.addAction(ACTION_CONTEXT_CLICK);
+ mActionReplacingCallback.setFindAccessibilityNodeInfoResult(infoFromApp, INTERACTION_ID);
+ verifyNoMoreInteractions(mMockServiceCallback);
+
+ mActionReplacingCallback.setFindAccessibilityNodeInfosResult(getReplacerNodes(),
+ mReplacerInteractionId);
+
+ verify(mMockServiceCallback).setFindAccessibilityNodeInfoResult(mInfoCaptor.capture(),
+ eq(INTERACTION_ID));
+ AccessibilityNodeInfo infoSentToService = mInfoCaptor.getValue();
+ assertEquals(NON_ROOT_NODE_ID, infoSentToService.getSourceNodeId());
+ assertTrue(infoSentToService.getActionList().isEmpty());
+ }
+
+ public void testCallbacks_replacerThenSingleRootNode_returnsNodeWithReplacedActions()
+ throws RemoteException {
+ mActionReplacingCallback.setFindAccessibilityNodeInfosResult(getReplacerNodes(),
+ mReplacerInteractionId);
+ verifyNoMoreInteractions(mMockServiceCallback);
+
+ AccessibilityNodeInfo infoFromApp = AccessibilityNodeInfo.obtain();
+ infoFromApp.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID, APP_WINDOW_ID);
+ infoFromApp.addAction(ACTION_CONTEXT_CLICK);
+ mActionReplacingCallback.setFindAccessibilityNodeInfoResult(infoFromApp, INTERACTION_ID);
+
+ verify(mMockServiceCallback).setFindAccessibilityNodeInfoResult(mInfoCaptor.capture(),
+ eq(INTERACTION_ID));
+ AccessibilityNodeInfo infoSentToService = mInfoCaptor.getValue();
+ assertEquals(AccessibilityNodeInfo.ROOT_NODE_ID, infoSentToService.getSourceNodeId());
+ assertInfoHasExactlyTheseActions(infoSentToService, REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE);
+ }
+
+ public void testCallbacks_multipleNodesThenReplacer_clearsActionsAndAddsSomeToRoot()
+ throws RemoteException {
+ mActionReplacingCallback
+ .setFindAccessibilityNodeInfosResult(getAppNodeList(), INTERACTION_ID);
+ verifyNoMoreInteractions(mMockServiceCallback);
+
+ mActionReplacingCallback.setFindAccessibilityNodeInfosResult(getReplacerNodes(),
+ mReplacerInteractionId);
+
+ verify(mMockServiceCallback).setFindAccessibilityNodeInfosResult(mInfoListCaptor.capture(),
+ eq(INTERACTION_ID));
+ assertEquals(2, mInfoListCaptor.getValue().size());
+ AccessibilityNodeInfo rootInfoSentToService = getNodeWithIdFromList(
+ mInfoListCaptor.getValue(), AccessibilityNodeInfo.ROOT_NODE_ID);
+ AccessibilityNodeInfo otherInfoSentToService = getNodeWithIdFromList(
+ mInfoListCaptor.getValue(), NON_ROOT_NODE_ID);
+ assertInfoHasExactlyTheseActions(
+ rootInfoSentToService, REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE);
+ assertTrue(otherInfoSentToService.getActionList().isEmpty());
+ }
+
+ public void testCallbacks_replacerThenMultipleNodes_clearsActionsAndAddsSomeToRoot()
+ throws RemoteException {
+ mActionReplacingCallback.setFindAccessibilityNodeInfosResult(getReplacerNodes(),
+ mReplacerInteractionId);
+ verifyNoMoreInteractions(mMockServiceCallback);
+
+ mActionReplacingCallback
+ .setFindAccessibilityNodeInfosResult(getAppNodeList(), INTERACTION_ID);
+
+ verify(mMockServiceCallback).setFindAccessibilityNodeInfosResult(mInfoListCaptor.capture(),
+ eq(INTERACTION_ID));
+ assertEquals(2, mInfoListCaptor.getValue().size());
+ AccessibilityNodeInfo rootInfoSentToService = getNodeWithIdFromList(
+ mInfoListCaptor.getValue(), AccessibilityNodeInfo.ROOT_NODE_ID);
+ AccessibilityNodeInfo otherInfoSentToService = getNodeWithIdFromList(
+ mInfoListCaptor.getValue(), NON_ROOT_NODE_ID);
+ assertInfoHasExactlyTheseActions(
+ rootInfoSentToService, REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE);
+ assertTrue(otherInfoSentToService.getActionList().isEmpty());
+ }
+
+ public void testConstructor_actionReplacerThrowsException_passesDataToService()
+ throws RemoteException {
+ doThrow(RemoteException.class).when(mMockReplacerConnection)
+ .findAccessibilityNodeInfoByAccessibilityId(eq(AccessibilityNodeInfo.ROOT_NODE_ID),
+ (Region) anyObject(), mInteractionIdCaptor.capture(),
+ eq(mActionReplacingCallback), eq(0), eq(INTERROGATING_PID),
+ eq(INTERROGATING_TID), (MagnificationSpec) anyObject(), eq(null));
+ ActionReplacingCallback actionReplacingCallback = new ActionReplacingCallback(
+ mMockServiceCallback, mMockReplacerConnection, INTERACTION_ID, INTERROGATING_PID,
+ INTERROGATING_TID);
+
+ verifyNoMoreInteractions(mMockServiceCallback);
+ AccessibilityNodeInfo infoFromApp = AccessibilityNodeInfo.obtain();
+ infoFromApp.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID, APP_WINDOW_ID);
+ infoFromApp.addAction(ACTION_CONTEXT_CLICK);
+ actionReplacingCallback.setFindAccessibilityNodeInfoResult(infoFromApp, INTERACTION_ID);
+
+ verify(mMockServiceCallback).setFindAccessibilityNodeInfoResult(mInfoCaptor.capture(),
+ eq(INTERACTION_ID));
+ AccessibilityNodeInfo infoSentToService = mInfoCaptor.getValue();
+ assertEquals(AccessibilityNodeInfo.ROOT_NODE_ID, infoSentToService.getSourceNodeId());
+ assertEquals(1, infoSentToService.getActionList().size());
+ assertEquals(ACTION_CONTEXT_CLICK, infoSentToService.getActionList().get(0));
+ }
+
+ public void testSetPerformAccessibilityActionResult_actsAsPassThrough() throws RemoteException {
+ mActionReplacingCallback.setPerformAccessibilityActionResult(true, INTERACTION_ID);
+ verify(mMockServiceCallback).setPerformAccessibilityActionResult(true, INTERACTION_ID);
+ mActionReplacingCallback.setPerformAccessibilityActionResult(false, INTERACTION_ID);
+ verify(mMockServiceCallback).setPerformAccessibilityActionResult(false, INTERACTION_ID);
+ }
+
+
+ private List<AccessibilityNodeInfo> getReplacerNodes() {
+ AccessibilityNodeInfo root = AccessibilityNodeInfo.obtain();
+ root.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID,
+ AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
+ for (AccessibilityAction action : ACTIONS_FROM_REPLACER) {
+ root.addAction(action);
+ }
+
+ // Second node should have no effect
+ AccessibilityNodeInfo other = AccessibilityNodeInfo.obtain();
+ other.setSourceNodeId(NON_ROOT_NODE_ID,
+ AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
+ other.addAction(ACTION_COLLAPSE);
+
+ return Arrays.asList(root, other);
+ }
+
+ private void assertInfoHasExactlyTheseActions(
+ AccessibilityNodeInfo info, AccessibilityAction[] actions) {
+ List<AccessibilityAction> nodeActions = info.getActionList();
+ assertEquals(new HashSet<AccessibilityAction>(nodeActions),
+ new HashSet<AccessibilityAction>(Arrays.asList(actions)));
+ }
+
+ private AccessibilityNodeInfo getNodeWithIdFromList(
+ List<AccessibilityNodeInfo> infos, long id) {
+ for (AccessibilityNodeInfo info : infos) {
+ if (info.getSourceNodeId() == id) {
+ return info;
+ }
+ }
+ assertTrue("Didn't find node", false);
+ return null;
+ }
+
+ private List<AccessibilityNodeInfo> getAppNodeList() {
+ AccessibilityNodeInfo rootInfoFromApp = AccessibilityNodeInfo.obtain();
+ rootInfoFromApp.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID, APP_WINDOW_ID);
+ rootInfoFromApp.addAction(ACTION_CONTEXT_CLICK);
+ AccessibilityNodeInfo otherInfoFromApp = AccessibilityNodeInfo.obtain();
+ otherInfoFromApp.setSourceNodeId(NON_ROOT_NODE_ID, APP_WINDOW_ID);
+ otherInfoFromApp.addAction(ACTION_CLICK);
+ return Arrays.asList(rootInfoFromApp, otherInfoFromApp);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/KeyEventDispatcherTest.java b/services/tests/servicestests/src/com/android/server/accessibility/KeyEventDispatcherTest.java
index 0ab91a1..fc12edc 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/KeyEventDispatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/KeyEventDispatcherTest.java
@@ -22,13 +22,13 @@
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyObject;
-import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
+import static org.mockito.hamcrest.MockitoHamcrest.argThat;
import java.util.ArrayList;
import java.util.Arrays;
@@ -46,12 +46,13 @@
import android.view.KeyEvent;
import android.view.WindowManagerPolicy;
import com.android.server.accessibility.KeyEventDispatcher.KeyEventFilter;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
-import org.mockito.ArgumentMatcher;
/**
* Tests for KeyEventDispatcher
@@ -558,7 +559,7 @@
.matches(mInputEventsHander.timedMessages.get(1).obj));
}
- private class KeyEventMatcher extends ArgumentMatcher<KeyEvent> {
+ private class KeyEventMatcher extends TypeSafeMatcher<KeyEvent> {
private KeyEvent mEventToMatch;
KeyEventMatcher(KeyEvent eventToMatch) {
@@ -566,14 +567,15 @@
}
@Override
- public boolean matches(Object event) {
- if (!(event instanceof KeyEvent)) {
- return false;
- }
- KeyEvent keyEvent = (KeyEvent) event;
+ public boolean matchesSafely(KeyEvent keyEvent) {
return (mEventToMatch.getAction() == keyEvent.getAction())
&& (mEventToMatch.getKeyCode() == keyEvent.getKeyCode());
}
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Key event matcher");
+ }
}
private class MessageCapturingHandler extends Handler {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
index cb5e8bb..d44c1ca 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
@@ -22,7 +22,6 @@
import static org.junit.Assert.assertFalse;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyObject;
-import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
@@ -30,6 +29,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+import static org.mockito.hamcrest.MockitoHamcrest.argThat;
import android.animation.ValueAnimator;
import android.content.BroadcastReceiver;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
index 73344e0..ec99a9a 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
@@ -28,7 +28,6 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
@@ -36,6 +35,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.hamcrest.MockitoHamcrest.argThat;
import android.accessibilityservice.GestureDescription.GestureStep;
import android.accessibilityservice.GestureDescription.TouchPoint;
@@ -65,7 +65,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
-import org.mockito.ArgumentMatcher;
+import org.mockito.compat.ArgumentMatcher;
/**
* Tests for MotionEventInjector
@@ -396,7 +396,7 @@
hasEventTime(downTime + CONTINUED_LINE_INTERVAL)));
// Timing will restart when the gesture continues
long secondSequenceStart = events.get(2).getEventTime();
- assertTrue(secondSequenceStart > events.get(1).getEventTime());
+ assertTrue(secondSequenceStart >= events.get(1).getEventTime());
assertThat(events.get(2), allOf(isAtPoint(CONTINUED_LINE_MID2), IS_ACTION_MOVE));
assertThat(events.get(3), allOf(isAtPoint(CONTINUED_LINE_END), IS_ACTION_MOVE,
hasEventTime(secondSequenceStart + CONTINUED_LINE_INTERVAL)));
@@ -738,7 +738,7 @@
return next;
}
- static class MotionEventMatcher extends ArgumentMatcher<MotionEvent> {
+ static class MotionEventMatcher extends TypeSafeMatcher<MotionEvent> {
long mDownTime;
long mEventTime;
long mActionMasked;
@@ -764,8 +764,7 @@
}
@Override
- public boolean matches(Object o) {
- MotionEvent event = (MotionEvent) o;
+ public boolean matchesSafely(MotionEvent event) {
if ((event.getDownTime() == mDownTime) && (event.getEventTime() == mEventTime)
&& (event.getActionMasked() == mActionMasked) && ((int) event.getX() == mX)
&& ((int) event.getY() == mY)) {
@@ -782,6 +781,11 @@
Log.e(LOG_TAG, "event.getY() = " + event.getY() + ", expected " + mY);
return false;
}
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Motion event matcher");
+ }
}
private static class MotionEventActionMatcher extends TypeSafeMatcher<MotionEvent> {
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index cc2f7d5..556b218 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -31,15 +31,35 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
import android.app.ActivityManager;
+import android.app.AppOpsManager;
+import android.app.IUidObserver;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.RemoteException;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import com.android.server.AppOpsService;
+
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
import java.util.function.Function;
/**
@@ -62,9 +82,16 @@
public class ActivityManagerServiceTest {
private static final int TEST_UID = 111;
+ @Mock private AppOpsService mAppOpsService;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
@Test
public void testIncrementProcStateSeqIfNeeded() {
- final ActivityManagerService ams = new ActivityManagerService();
+ final ActivityManagerService ams = new ActivityManagerService(mAppOpsService);
final UidRecord uidRec = new UidRecord(TEST_UID);
assertEquals("Initially global seq counter should be 0", 0, ams.mProcStateSeqCounter);
@@ -104,7 +131,7 @@
@Test
public void testShouldIncrementProcStateSeq() {
- final ActivityManagerService ams = new ActivityManagerService();
+ final ActivityManagerService ams = new ActivityManagerService(mAppOpsService);
final UidRecord uidRec = new UidRecord(TEST_UID);
final String error1 = "Seq should be incremented: prevState: %s, curState: %s";
@@ -145,4 +172,286 @@
uidRec.curProcState = PROCESS_STATE_LAST_ACTIVITY;
assertTrue(errorMsg.apply(error1), ams.shouldIncrementProcStateSeq(uidRec));
}
+
+ /**
+ * This test verifies that process state changes are dispatched to observers based on the
+ * changes they wanted to listen (this is specified when registering the observer).
+ */
+ @Test
+ public void testDispatchUids_dispatchNeededChanges() throws RemoteException {
+ final ActivityManagerService ams = new ActivityManagerService(mAppOpsService);
+ when(mAppOpsService.checkOperation(AppOpsManager.OP_GET_USAGE_STATS, Process.myUid(), null))
+ .thenReturn(AppOpsManager.MODE_ALLOWED);
+
+ final int[] changesToObserve = {
+ ActivityManager.UID_OBSERVER_PROCSTATE,
+ ActivityManager.UID_OBSERVER_GONE,
+ ActivityManager.UID_OBSERVER_IDLE,
+ ActivityManager.UID_OBSERVER_ACTIVE,
+ ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE
+ | ActivityManager.UID_OBSERVER_ACTIVE | ActivityManager.UID_OBSERVER_IDLE
+ };
+ final IUidObserver[] observers = new IUidObserver.Stub[changesToObserve.length];
+ for (int i = 0; i < observers.length; ++i) {
+ observers[i] = Mockito.mock(IUidObserver.Stub.class);
+ when(observers[i].asBinder()).thenReturn((IBinder) observers[i]);
+ ams.registerUidObserver(observers[i], changesToObserve[i] /* which */,
+ ActivityManager.PROCESS_STATE_UNKNOWN /* cutpoint */, null /* caller */);
+
+ // When we invoke AMS.registerUidObserver, there are some interactions with observers[i]
+ // mock in RemoteCallbackList class. We don't want to test those interactions and
+ // at the same time, we don't want those to interfere with verifyNoMoreInteractions.
+ // So, resetting the mock here.
+ Mockito.reset(observers[i]);
+ }
+
+ // Add pending uid records each corresponding to a different change type UidRecord.CHANGE_*
+ final int[] changesForPendingUidRecords = {
+ UidRecord.CHANGE_PROCSTATE,
+ UidRecord.CHANGE_GONE,
+ UidRecord.CHANGE_GONE_IDLE,
+ UidRecord.CHANGE_IDLE,
+ UidRecord.CHANGE_ACTIVE
+ };
+ final int[] procStatesForPendingUidRecords = {
+ ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE,
+ ActivityManager.PROCESS_STATE_NONEXISTENT,
+ ActivityManager.PROCESS_STATE_CACHED_EMPTY,
+ ActivityManager.PROCESS_STATE_CACHED_ACTIVITY,
+ ActivityManager.PROCESS_STATE_TOP
+ };
+ final Map<Integer, UidRecord.ChangeItem> changeItems = new HashMap<>();
+ for (int i = 0; i < changesForPendingUidRecords.length; ++i) {
+ final UidRecord.ChangeItem pendingChange = new UidRecord.ChangeItem();
+ pendingChange.change = changesForPendingUidRecords[i];
+ pendingChange.uid = i;
+ pendingChange.processState = procStatesForPendingUidRecords[i];
+ pendingChange.procStateSeq = i;
+ changeItems.put(changesForPendingUidRecords[i], pendingChange);
+ ams.mPendingUidChanges.add(pendingChange);
+ }
+
+ ams.dispatchUidsChanged();
+ // Verify the required changes have been dispatched to observers.
+ for (int i = 0; i < observers.length; ++i) {
+ final int changeToObserve = changesToObserve[i];
+ final IUidObserver observerToTest = observers[i];
+ if ((changeToObserve & ActivityManager.UID_OBSERVER_IDLE) != 0) {
+ // Observer listens to uid idle changes, so change items corresponding to
+ // UidRecord.CHANGE_IDLE or UidRecord.CHANGE_IDLE_GONE needs to be
+ // delivered to this observer.
+ final int[] changesToVerify = {
+ UidRecord.CHANGE_IDLE,
+ UidRecord.CHANGE_GONE_IDLE
+ };
+ verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems,
+ (observer, changeItem) -> {
+ verify(observer).onUidIdle(changeItem.uid, changeItem.ephemeral);
+ });
+ }
+ if ((changeToObserve & ActivityManager.UID_OBSERVER_ACTIVE) != 0) {
+ // Observer listens to uid active changes, so change items corresponding to
+ // UidRecord.CHANGE_ACTIVE needs to be delivered to this observer.
+ final int[] changesToVerify = { UidRecord.CHANGE_ACTIVE };
+ verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems,
+ (observer, changeItem) -> {
+ verify(observer).onUidActive(changeItem.uid);
+ });
+ }
+ if ((changeToObserve & ActivityManager.UID_OBSERVER_GONE) != 0) {
+ // Observer listens to uid gone changes, so change items corresponding to
+ // UidRecord.CHANGE_GONE or UidRecord.CHANGE_IDLE_GONE needs to be
+ // delivered to this observer.
+ final int[] changesToVerify = {
+ UidRecord.CHANGE_GONE,
+ UidRecord.CHANGE_GONE_IDLE
+ };
+ verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems,
+ (observer, changeItem) -> {
+ verify(observer).onUidGone(changeItem.uid, changeItem.ephemeral);
+ });
+ }
+ if ((changeToObserve & ActivityManager.UID_OBSERVER_PROCSTATE) != 0) {
+ // Observer listens to uid procState changes, so change items corresponding to
+ // UidRecord.CHANGE_PROCSTATE or UidRecord.CHANGE_IDLE or UidRecord.CHANGE_ACTIVE
+ // needs to be delivered to this observer.
+ final int[] changesToVerify = {
+ UidRecord.CHANGE_PROCSTATE,
+ UidRecord.CHANGE_ACTIVE,
+ UidRecord.CHANGE_IDLE
+ };
+ verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems,
+ (observer, changeItem) -> {
+ verify(observer).onUidStateChanged(changeItem.uid,
+ changeItem.processState, changeItem.procStateSeq);
+ });
+ }
+ // Verify there are no other callbacks for this observer.
+ verifyNoMoreInteractions(observerToTest);
+ }
+ }
+
+ private interface ObserverChangesVerifier {
+ void verify(IUidObserver observer, UidRecord.ChangeItem changeItem) throws RemoteException;
+ }
+
+ private void verifyObserverReceivedChanges(IUidObserver observer, int[] changesToVerify,
+ Map<Integer, UidRecord.ChangeItem> changeItems, ObserverChangesVerifier verifier)
+ throws RemoteException {
+ for (int change : changesToVerify) {
+ final UidRecord.ChangeItem changeItem = changeItems.get(change);
+ verifier.verify(observer, changeItem);
+ }
+ }
+
+ /**
+ * This test verifies that process state changes are dispatched to observers only when they
+ * change across the cutpoint (this is specified when registering the observer).
+ */
+ @Test
+ public void testDispatchUidChanges_procStateCutpoint() throws RemoteException {
+ final ActivityManagerService ams = new ActivityManagerService(mAppOpsService);
+ final IUidObserver observer = Mockito.mock(IUidObserver.Stub.class);
+
+ when(observer.asBinder()).thenReturn((IBinder) observer);
+ ams.registerUidObserver(observer, ActivityManager.UID_OBSERVER_PROCSTATE /* which */,
+ ActivityManager.PROCESS_STATE_SERVICE /* cutpoint */, null /* callingPackage */);
+ // When we invoke AMS.registerUidObserver, there are some interactions with observer
+ // mock in RemoteCallbackList class. We don't want to test those interactions and
+ // at the same time, we don't want those to interfere with verifyNoMoreInteractions.
+ // So, resetting the mock here.
+ Mockito.reset(observer);
+
+ final UidRecord.ChangeItem changeItem = new UidRecord.ChangeItem();
+ changeItem.uid = TEST_UID;
+ changeItem.change = UidRecord.CHANGE_PROCSTATE;
+ changeItem.processState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
+ changeItem.procStateSeq = 111;
+ ams.mPendingUidChanges.add(changeItem);
+ ams.dispatchUidsChanged();
+ // First process state message is always delivered regardless of whether the process state
+ // change is above or below the cutpoint (PROCESS_STATE_SERVICE).
+ verify(observer).onUidStateChanged(TEST_UID,
+ changeItem.processState, changeItem.procStateSeq);
+ verifyNoMoreInteractions(observer);
+
+ changeItem.processState = ActivityManager.PROCESS_STATE_RECEIVER;
+ ams.mPendingUidChanges.add(changeItem);
+ ams.dispatchUidsChanged();
+ // Previous process state change is below cutpoint (PROCESS_STATE_SERVICE) and
+ // the current process state change is also below cutpoint, so no callback will be invoked.
+ verifyNoMoreInteractions(observer);
+
+ changeItem.processState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
+ ams.mPendingUidChanges.add(changeItem);
+ ams.dispatchUidsChanged();
+ // Previous process state change is below cutpoint (PROCESS_STATE_SERVICE) and
+ // the current process state change is above cutpoint, so callback will be invoked with the
+ // current process state change.
+ verify(observer).onUidStateChanged(TEST_UID,
+ changeItem.processState, changeItem.procStateSeq);
+ verifyNoMoreInteractions(observer);
+
+ changeItem.processState = ActivityManager.PROCESS_STATE_TOP;
+ ams.mPendingUidChanges.add(changeItem);
+ ams.dispatchUidsChanged();
+ // Previous process state change is above cutpoint (PROCESS_STATE_SERVICE) and
+ // the current process state change is also above cutpoint, so no callback will be invoked.
+ verifyNoMoreInteractions(observer);
+
+ changeItem.processState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
+ ams.mPendingUidChanges.add(changeItem);
+ ams.dispatchUidsChanged();
+ // Previous process state change is above cutpoint (PROCESS_STATE_SERVICE) and
+ // the current process state change is below cutpoint, so callback will be invoked with the
+ // current process state change.
+ verify(observer).onUidStateChanged(TEST_UID,
+ changeItem.processState, changeItem.procStateSeq);
+ verifyNoMoreInteractions(observer);
+ }
+
+ /**
+ * This test verifies that {@link ActivityManagerService#mValidateUids} which is a
+ * part of dumpsys is correctly updated.
+ */
+ @Test
+ public void testDispatchUidChanges_validateUidsUpdated() {
+ final ActivityManagerService ams = new ActivityManagerService(mAppOpsService);
+
+ final int[] changesForPendingItems = {
+ UidRecord.CHANGE_PROCSTATE,
+ UidRecord.CHANGE_GONE,
+ UidRecord.CHANGE_GONE_IDLE,
+ UidRecord.CHANGE_IDLE,
+ UidRecord.CHANGE_ACTIVE
+ };
+ final int[] procStatesForPendingItems = {
+ ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE,
+ ActivityManager.PROCESS_STATE_CACHED_EMPTY,
+ ActivityManager.PROCESS_STATE_CACHED_ACTIVITY,
+ ActivityManager.PROCESS_STATE_SERVICE,
+ ActivityManager.PROCESS_STATE_RECEIVER
+ };
+ final ArrayList<UidRecord.ChangeItem> pendingItemsForUids
+ = new ArrayList<>(changesForPendingItems.length);
+ for (int i = 0; i < changesForPendingItems.length; ++i) {
+ final UidRecord.ChangeItem item = new UidRecord.ChangeItem();
+ item.uid = i;
+ item.change = changesForPendingItems[i];
+ item.processState = procStatesForPendingItems[i];
+ pendingItemsForUids.add(i, item);
+ }
+
+ // Verify that when there no observers listening to uid state changes, then there will
+ // be no changes to validateUids.
+ ams.mPendingUidChanges.addAll(pendingItemsForUids);
+ ams.dispatchUidsChanged();
+ assertEquals("No observers registered, so validateUids should be empty",
+ 0, ams.mValidateUids.size());
+
+ final IUidObserver observer = Mockito.mock(IUidObserver.Stub.class);
+ when(observer.asBinder()).thenReturn((IBinder) observer);
+ ams.registerUidObserver(observer, 0, 0, null);
+ // Verify that when observers are registered, then validateUids is correctly updated.
+ ams.mPendingUidChanges.addAll(pendingItemsForUids);
+ ams.dispatchUidsChanged();
+ for (int i = 0; i < pendingItemsForUids.size(); ++i) {
+ final UidRecord.ChangeItem item = pendingItemsForUids.get(i);
+ final UidRecord validateUidRecord = ams.mValidateUids.get(item.uid);
+ if (item.change == UidRecord.CHANGE_GONE || item.change == UidRecord.CHANGE_GONE_IDLE) {
+ assertNull("validateUidRecord should be null since the change is either "
+ + "CHANGE_GONE or CHANGE_GONE_IDLE", validateUidRecord);
+ } else {
+ assertNotNull("validateUidRecord should not be null since the change is neither "
+ + "CHANGE_GONE nor CHANGE_GONE_IDLE", validateUidRecord);
+ assertEquals("processState: " + item.processState + " curProcState: "
+ + validateUidRecord.curProcState + " should have been equal",
+ item.processState, validateUidRecord.curProcState);
+ assertEquals("processState: " + item.processState + " setProcState: "
+ + validateUidRecord.curProcState + " should have been equal",
+ item.processState, validateUidRecord.setProcState);
+ if (item.change == UidRecord.CHANGE_IDLE) {
+ assertTrue("UidRecord.idle should be updated to true for CHANGE_IDLE",
+ validateUidRecord.idle);
+ } else if (item.change == UidRecord.CHANGE_ACTIVE) {
+ assertFalse("UidRecord.idle should be updated to false for CHANGE_ACTIVE",
+ validateUidRecord.idle);
+ }
+ }
+ }
+
+ // Verify that when uid state changes to CHANGE_GONE or CHANGE_GONE_IDLE, then it
+ // will be removed from validateUids.
+ assertNotEquals("validateUids should not be empty", 0, ams.mValidateUids.size());
+ for (int i = 0; i < pendingItemsForUids.size(); ++i) {
+ final UidRecord.ChangeItem item = pendingItemsForUids.get(i);
+ // Assign CHANGE_GONE_IDLE to some items and CHANGE_GONE to the others, using even/odd
+ // distribution for this assignment.
+ item.change = (i % 2) == 0 ? UidRecord.CHANGE_GONE_IDLE : UidRecord.CHANGE_GONE;
+ }
+ ams.mPendingUidChanges.addAll(pendingItemsForUids);
+ ams.dispatchUidsChanged();
+ assertEquals("validateUids should be empty, validateUids: " + ams.mValidateUids,
+ 0, ams.mValidateUids.size());
+ }
}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index f969e80..8987ac1 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -85,7 +85,6 @@
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.atLeast;
@@ -99,6 +98,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
+import static org.mockito.hamcrest.MockitoHamcrest.argThat;
/**
* Tests for DevicePolicyManager( and DevicePolicyManagerService).
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
index 3806da6..e43786c 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
@@ -29,6 +29,7 @@
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.mockito.Mockito;
+import org.mockito.hamcrest.MockitoHamcrest;
public class MockUtils {
private MockUtils() {
@@ -47,7 +48,7 @@
description.appendText("UserHandle: user-id= \"" + userId + "\"");
}
};
- return Mockito.argThat(m);
+ return MockitoHamcrest.argThat(m);
}
public static Intent checkIntentComponent(final ComponentName component) {
@@ -63,7 +64,7 @@
description.appendText("Intent: component=\"" + component + "\"");
}
};
- return Mockito.argThat(m);
+ return MockitoHamcrest.argThat(m);
}
public static Intent checkIntentAction(final String action) {
@@ -79,7 +80,7 @@
description.appendText("Intent: action=\"" + action + "\"");
}
};
- return Mockito.argThat(m);
+ return MockitoHamcrest.argThat(m);
}
public static Intent checkIntent(final Intent intent) {
@@ -94,7 +95,7 @@
description.appendText(intent.toString());
}
};
- return Mockito.argThat(m);
+ return MockitoHamcrest.argThat(m);
}
public static Bundle checkUserRestrictions(String... keys) {
@@ -111,7 +112,7 @@
description.appendText("User restrictions=" + getRestrictionsAsString(expected));
}
};
- return Mockito.argThat(m);
+ return MockitoHamcrest.argThat(m);
}
private static String getRestrictionsAsString(Bundle b) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 1b59d72..b410400 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -2119,7 +2119,7 @@
protected void makeCallerForeground() {
try {
mService.mUidObserver.onUidStateChanged(
- mInjectedCallingUid, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
+ mInjectedCallingUid, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
}
@@ -2128,7 +2128,7 @@
protected void makeCallerBackground() {
try {
mService.mUidObserver.onUidStateChanged(
- mInjectedCallingUid, ActivityManager.PROCESS_STATE_TOP_SLEEPING);
+ mInjectedCallingUid, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0);
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 900da09..7c5eb07 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -1640,7 +1640,7 @@
// State changed, but not foreground, so no resetting.
mService.mUidObserver.onUidStateChanged(
- CALLING_UID_1, ActivityManager.PROCESS_STATE_TOP_SLEEPING);
+ CALLING_UID_1, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
@@ -1664,7 +1664,7 @@
// State changed, package1 foreground, reset.
mService.mUidObserver.onUidStateChanged(
- CALLING_UID_1, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
+ CALLING_UID_1, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
@@ -1684,16 +1684,16 @@
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
mService.mUidObserver.onUidStateChanged(
- CALLING_UID_1, ActivityManager.PROCESS_STATE_TOP_SLEEPING);
+ CALLING_UID_1, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0);
mInjectedCurrentTimeMillis++;
// Different app comes to foreground briefly, and goes back to background.
// Now, make sure package 2's counter is reset, even in this case.
mService.mUidObserver.onUidStateChanged(
- CALLING_UID_2, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
+ CALLING_UID_2, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
mService.mUidObserver.onUidStateChanged(
- CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING);
+ CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
@@ -1724,9 +1724,9 @@
});
mService.mUidObserver.onUidStateChanged(
- CALLING_UID_2, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
+ CALLING_UID_2, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
mService.mUidObserver.onUidStateChanged(
- CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING);
+ CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
@@ -1753,7 +1753,7 @@
// Now, also try calling some APIs and make sure foreground apps don't get throttled.
mService.mUidObserver.onUidStateChanged(
UserHandle.getUid(USER_10, CALLING_UID_1),
- ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
+ ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
assertFalse(mManager.isRateLimitingActive());
diff --git a/services/tests/servicestests/src/com/android/server/policy/AccessibilityShortcutControllerTest.java b/services/tests/servicestests/src/com/android/server/policy/AccessibilityShortcutControllerTest.java
index 1de6348..8329d68 100644
--- a/services/tests/servicestests/src/com/android/server/policy/AccessibilityShortcutControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/policy/AccessibilityShortcutControllerTest.java
@@ -45,8 +45,8 @@
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.mockito.internal.util.reflection.Whitebox;
+import java.lang.reflect.Field;
import java.util.Collections;
import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN;
@@ -124,7 +124,15 @@
when(mToast.getWindowParams()).thenReturn(mLayoutParams);
Window window = mock(Window.class);
- Whitebox.setInternalState(window, "mWindowAttributes", new WindowManager.LayoutParams());
+ // Initialize the mWindowAttributes field which was not properly initialized during mock
+ // creation.
+ try {
+ Field field = Window.class.getDeclaredField("mWindowAttributes");
+ field.setAccessible(true);
+ field.set(window, new WindowManager.LayoutParams());
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to set mWindowAttributes", e);
+ }
when(mAlertDialog.getWindow()).thenReturn(window);
}
diff --git a/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java b/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
index e1dda51..d18457b 100644
--- a/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
@@ -66,16 +66,15 @@
import com.android.server.SystemService;
import com.android.server.retaildemo.RetailDemoModeService.Injector;
-import org.hamcrest.Description;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
-import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.compat.ArgumentMatcher;
import java.io.File;
import java.util.concurrent.CountDownLatch;
@@ -283,7 +282,7 @@
}
@Override
- public boolean matches(Object argument) {
+ public boolean matchesObject(Object argument) {
if (argument instanceof Intent) {
return ((Intent) argument).filterEquals(mIntent);
}
@@ -291,8 +290,8 @@
}
@Override
- public void describeTo(Description description) {
- description.appendText("Expected: " + mIntent);
+ public String toString() {
+ return "Expected: " + mIntent;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java b/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java
index 8cf7c8a..3cdf109 100644
--- a/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java
@@ -28,6 +28,9 @@
import android.os.UserManager;
import android.os.storage.VolumeInfo;
import android.test.AndroidTestCase;
+import android.util.ArrayMap;
+import android.util.Log;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -40,12 +43,14 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.when;
@@ -57,24 +62,29 @@
@Mock private PackageManager mPm;
@Mock private UserManager mUm;
@Mock private StorageStatsManager mSsm;
- private List<ApplicationInfo> mApps;
private List<UserInfo> mUsers;
+ private Map<Integer, List<ApplicationInfo>> mUserApps;
@Before
public void setUp() throws Exception {
super.setUp();
MockitoAnnotations.initMocks(this);
- mApps = new ArrayList<>();
when(mContext.getPackageManager()).thenReturn(mPm);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUm);
when(mContext.getSystemService(Context.STORAGE_STATS_SERVICE)).thenReturn(mSsm);
// Set up the app list.
- when(mPm.getInstalledApplications(anyInt())).thenReturn(mApps);
+ doAnswer((InvocationOnMock invocation) -> {
+ Integer userId = (Integer) invocation.getArguments()[1];
+ return mUserApps.get(userId);
+ }).when(mPm).getInstalledApplicationsAsUser(anyInt(), anyInt());
// Set up the user list with a single user (0).
mUsers = new ArrayList<>();
mUsers.add(new UserInfo(0, "", 0));
+
+ mUserApps = new ArrayMap<>();
+ mUserApps.put(0, new ArrayList<>());
when(mUm.getUsers()).thenReturn(mUsers);
}
@@ -89,7 +99,7 @@
@Test
public void testAppOnExternalVolume() throws Exception {
- addApplication("com.test.app", "differentuuid");
+ addApplication("com.test.app", "differentuuid", 0);
VolumeInfo volume = new VolumeInfo("testuuid", 0, null, null);
volume.fsUuid = "testuuid";
AppCollector collector = new AppCollector(mContext, volume);
@@ -99,7 +109,7 @@
@Test
public void testOneValidApp() throws Exception {
- addApplication("com.test.app", "testuuid");
+ addApplication("com.test.app", "testuuid", 0);
VolumeInfo volume = new VolumeInfo("testuuid", 0, null, null);
volume.fsUuid = "testuuid";
AppCollector collector = new AppCollector(mContext, volume);
@@ -112,11 +122,9 @@
@Test
public void testMultipleUsersOneApp() throws Exception {
- addApplication("com.test.app", "testuuid");
- ApplicationInfo otherUsersApp = new ApplicationInfo();
- otherUsersApp.packageName = "com.test.app";
- otherUsersApp.volumeUuid = "testuuid";
- otherUsersApp.uid = 1;
+ addApplication("com.test.app", "testuuid", 0);
+ mUserApps.put(1, new ArrayList<>());
+ addApplication("com.test.app", "testuuid", 1);
mUsers.add(new UserInfo(1, "", 0));
VolumeInfo volume = new VolumeInfo("testuuid", 0, null, null);
@@ -138,11 +146,28 @@
AppCollector collector = new AppCollector(mContext, null);
}
- private void addApplication(String packageName, String uuid) {
+ @Test
+ public void testAppNotFoundDoesntCauseCrash() throws Exception {
+ VolumeInfo volume = new VolumeInfo("testuuid", 0, null, null);
+ addApplication("com.test.app", "uuid", 0);
+ mUsers.add(new UserInfo(1, "", 0));
+ mUserApps.put(1, new ArrayList<>());
+ AppCollector collector = new AppCollector(mContext, volume);
+ when(mSsm.queryStatsForPackage(anyString(), anyString(), any(UserHandle.class))).thenThrow(
+ new IllegalStateException());
+
+ assertThat(collector.getPackageStats(TIMEOUT)).isEmpty();
+ }
+
+ private void addApplication(String packageName, String uuid, int userId) {
ApplicationInfo info = new ApplicationInfo();
info.packageName = packageName;
info.volumeUuid = uuid;
- mApps.add(info);
+ List<ApplicationInfo> userApps = mUserApps.get(userId);
+ if (userApps == null) {
+ userApps = new ArrayList<>();
+ mUserApps.put(userId, userApps);
+ }
+ userApps.add(info);
}
-
}
diff --git a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
index e4b74eb..925f414 100644
--- a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
@@ -35,14 +35,12 @@
import android.webkit.WebViewProviderInfo;
import android.webkit.WebViewProviderResponse;
-import org.hamcrest.Description;
-
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.Matchers;
-import org.mockito.ArgumentMatcher;
+import org.mockito.compat.ArgumentMatcher;
import java.util.concurrent.CountDownLatch;
@@ -149,14 +147,13 @@
}
@Override
- public boolean matches(Object p) {
+ public boolean matchesObject(Object p) {
return ((PackageInfo) p).packageName.equals(mPackageName);
}
- // Provide a more useful description in case of mismatch
@Override
- public void describeTo (Description description) {
- description.appendText(String.format("PackageInfo with name '%s'", mPackageName));
+ public String toString() {
+ return String.format("PackageInfo with name '%s'", mPackageName);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index e589bc7..3868242 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -22,7 +22,6 @@
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
@@ -147,7 +146,6 @@
final WindowState appWin = createWindow(null, TYPE_APPLICATION, sDisplayContent, "appWin");
appWin.setHasSurface(true);
assertTrue(appWin.canBeImeTarget());
- sWm.mInputMethodTargetCandidate = appWin.mClient.asBinder();
WindowState imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */);
assertEquals(appWin, imeTarget);
@@ -158,20 +156,6 @@
assertTrue(childWin.canBeImeTarget());
imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */);
assertEquals(childWin, imeTarget);
-
- final WindowState appWin2 =
- createWindow(null, TYPE_APPLICATION, sDisplayContent, "appWin2");
- appWin2.setHasSurface(true);
- assertTrue(appWin2.canBeImeTarget());
- // Verify that the IME target isn't adjusted since mInputMethodTargetCandidate didn't change
- // to the new app.
- imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */);
- assertNotEquals(appWin2, imeTarget);
-
- sWm.mInputMethodTargetCandidate = appWin2.mClient.asBinder();
- // Verify app is not IME target since its token is set as a candidate.
- imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */);
- assertEquals(appWin2, imeTarget);
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index c8b73f1..0971bb6 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -82,7 +82,7 @@
final ActivityManagerInternal am =
LocalServices.getService(ActivityManagerInternal.class);
doAnswer((InvocationOnMock invocationOnMock) -> {
- final Runnable runnable = invocationOnMock.getArgumentAt(0, Runnable.class);
+ final Runnable runnable = invocationOnMock.<Runnable>getArgument(0);
if (runnable != null) {
runnable.run();
}
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 18c48b7..911050a 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -69,6 +69,7 @@
class WindowTestsBase {
static WindowManagerService sWm = null;
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;
static int sNextStackId = FIRST_DYNAMIC_STACK_ID;
@@ -147,7 +148,6 @@
}
sWm.mInputMethodTarget = null;
- sWm.mInputMethodTargetCandidate = null;
}
private static WindowState createCommonWindow(WindowState parent, int type, String name) {
@@ -222,12 +222,11 @@
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);
attrs.setTitle(name);
- final WindowState w = new WindowState(sWm, sMockSession, new TestIWindow(), token, parent,
- OP_NONE, 0, attrs, 0, 0, ownerCanAddInternalSystemWindow);
+ final WindowState w = new WindowState(sWm, sMockSession, sIWindow, token, parent, OP_NONE,
+ 0, attrs, 0, 0, ownerCanAddInternalSystemWindow);
// TODO: Probably better to make this call in the WindowState ctor to avoid errors with
// adding it to the token...
token.addWindow(w);
- sWm.mWindowMap.put(w.mClient.asBinder(), w);
return w;
}
@@ -455,9 +454,8 @@
boolean resizeReported;
TestWindowState(WindowManager.LayoutParams attrs, WindowToken token) {
- super(sWm, sMockSession, new TestIWindow(), token, null, OP_NONE, 0, attrs, 0, 0,
+ super(sWm, sMockSession, sIWindow, token, null, OP_NONE, 0, attrs, 0, 0,
false /* ownerCanAddInternalSystemWindow */);
- sWm.mWindowMap.put(mClient.asBinder(), this);
}
@Override
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index fd335c3..f2bae4c 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -59,6 +59,7 @@
import org.json.JSONObject;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
+import org.mockito.hamcrest.MockitoHamcrest;
import java.io.BufferedReader;
import java.io.File;
@@ -672,7 +673,7 @@
d.appendText(description);
}
};
- return Mockito.argThat(m);
+ return MockitoHamcrest.argThat(m);
}
public static List<ShortcutInfo> checkShortcutIds(String... ids) {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 3c7ee43..7be2b0f 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -342,7 +342,7 @@
private final IUidObserver mUidObserver = new IUidObserver.Stub() {
@Override
- public void onUidStateChanged(int uid, int procState) {
+ public void onUidStateChanged(int uid, int procState, long procStateSeq) {
final int newCounter = (procState <= ActivityManager.PROCESS_STATE_TOP) ? 0 : 1;
synchronized (mUidToKernelCounter) {
final int oldCounter = mUidToKernelCounter.get(uid, 0);
@@ -364,7 +364,7 @@
@Override
public void onUidGone(int uid, boolean disabled) throws RemoteException {
- onUidStateChanged(uid, ActivityManager.PROCESS_STATE_NONEXISTENT);
+ onUidStateChanged(uid, ActivityManager.PROCESS_STATE_NONEXISTENT, 0);
}
@Override
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index a17676a..b142bc2 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -33,6 +33,7 @@
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbPort;
import android.hardware.usb.UsbPortStatus;
+import android.os.BatteryManager;
import android.os.FileUtils;
import android.os.Handler;
import android.os.Looper;
@@ -122,6 +123,7 @@
private static final int MSG_UPDATE_USER_RESTRICTIONS = 6;
private static final int MSG_UPDATE_HOST_STATE = 7;
private static final int MSG_ACCESSORY_MODE_ENTER_TIMEOUT = 8;
+ private static final int MSG_UPDATE_CHARGING_STATE = 9;
private static final int AUDIO_MODE_SOURCE = 1;
@@ -203,6 +205,15 @@
}
};
+ private final BroadcastReceiver mChargingReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
+ boolean usbCharging = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
+ mHandler.sendMessage(MSG_UPDATE_CHARGING_STATE, usbCharging);
+ }
+ };
+
public UsbDeviceManager(Context context, UsbAlsaManager alsaManager,
UsbSettingsManager settingsManager) {
mContext = context;
@@ -229,6 +240,8 @@
}
mContext.registerReceiver(mHostReceiver,
new IntentFilter(UsbManager.ACTION_USB_PORT_CHANGED));
+ mContext.registerReceiver(mChargingReceiver,
+ new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
}
private UsbProfileGroupSettingsManager getCurrentSettings() {
@@ -358,6 +371,7 @@
private int mUsbNotificationId;
private boolean mAdbNotificationShown;
private int mCurrentUser = UserHandle.USER_NULL;
+ private boolean mUsbCharging;
public UsbHandler(Looper looper) {
super(looper);
@@ -456,7 +470,10 @@
args.argi2 = sourcePower ? 1 :0;
args.argi3 = sinkPower ? 1 :0;
- obtainMessage(MSG_UPDATE_HOST_STATE, args).sendToTarget();
+ removeMessages(MSG_UPDATE_HOST_STATE);
+ Message msg = obtainMessage(MSG_UPDATE_HOST_STATE, args);
+ // debounce rapid transitions of connect/disconnect on type-c ports
+ sendMessageDelayed(msg, UPDATE_DELAY);
}
private boolean waitForState(String state) {
@@ -799,6 +816,10 @@
mPendingBootBroadcast = true;
}
break;
+ case MSG_UPDATE_CHARGING_STATE:
+ mUsbCharging = (msg.arg1 == 1);
+ updateUsbNotification();
+ break;
case MSG_ENABLE_ADB:
setAdbEnabled(msg.arg1 == 1);
break;
@@ -892,7 +913,7 @@
}
} else if (mSourcePower) {
id = com.android.internal.R.string.usb_supplying_notification_title;
- } else if (mHostConnected && mSinkPower) {
+ } else if (mHostConnected && mSinkPower && mUsbCharging) {
id = com.android.internal.R.string.usb_charging_notification_title;
}
if (id != mUsbNotificationId) {
@@ -998,6 +1019,7 @@
pw.println(" mHostConnected: " + mHostConnected);
pw.println(" mSourcePower: " + mSourcePower);
pw.println(" mSinkPower: " + mSinkPower);
+ pw.println(" mUsbCharging: " + mUsbCharging);
try {
pw.println(" Kernel state: "
+ FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim());
diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java
index a923fc3..86f4a01 100644
--- a/services/usb/java/com/android/server/usb/UsbPortManager.java
+++ b/services/usb/java/com/android/server/usb/UsbPortManager.java
@@ -41,6 +41,7 @@
import android.util.Log;
import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.FgThread;
@@ -78,7 +79,7 @@
private final Context mContext;
// Proxy object for the usb hal daemon.
- // @GuardedBy("mLock")
+ @GuardedBy("mLock")
private IUsb mProxy = null;
// Callback when the UsbPort status is changed by the kernel.
@@ -92,7 +93,7 @@
private static final int USB_HAL_DEATH_COOKIE = 1000;
// Usb hal service name.
- private static String sSERVICENAME = "usb_hal";
+ private static String sServiceName = "usb_hal";
// Used as the key while sending the bundle to Main thread.
private static final String PORT_INFO = "port_info";
@@ -119,13 +120,14 @@
try {
boolean ret = IServiceManager.getService()
.registerForNotifications("android.hardware.usb@1.0::IUsb",
- "", mServiceNotification);
+ "", mServiceNotification);
if (!ret) {
- logAndPrint(Log.ERROR, null, "Failed to register service start notification");
+ logAndPrint(Log.ERROR, null,
+ "Failed to register service start notification");
}
} catch (RemoteException e) {
- logAndPrint(Log.ERROR, null, "Failed to register service start notification");
- Thread.dumpStack();
+ logAndPrintException(null,
+ "Failed to register service start notification", e);
return;
}
connectToProxy(null);
@@ -136,9 +138,8 @@
try {
mProxy.queryPortStatus();
} catch (RemoteException e) {
- logAndPrint(Log.ERROR, null,
- "ServiceStart: Failed to query port status");
- Thread.dumpStack();
+ logAndPrintException(null,
+ "ServiceStart: Failed to query port status", e);
}
}
mSystemReady = true;
@@ -234,9 +235,9 @@
RawPortInfo sim = mSimulatedPorts.get(portId);
if (sim != null) {
// Change simulated state.
- sim.mCurrentMode = newMode;
- sim.mCurrentPowerRole = newPowerRole;
- sim.mCurrentDataRole = newDataRole;
+ sim.currentMode = newMode;
+ sim.currentPowerRole = newPowerRole;
+ sim.currentDataRole = newDataRole;
updatePortsLocked(pw, null);
} else if (mProxy != null) {
if (currentMode != newMode) {
@@ -248,18 +249,17 @@
// directly instead.
logAndPrint(Log.ERROR, pw, "Trying to set the USB port mode: "
- + "portId=" + portId
- + ", newMode=" + UsbPort.modeToString(newMode));
+ + "portId=" + portId
+ + ", newMode=" + UsbPort.modeToString(newMode));
PortRole newRole = new PortRole();
newRole.type = PortRoleType.MODE;
newRole.role = newMode;
try {
mProxy.switchRole(portId, newRole);
} catch (RemoteException e) {
- logAndPrint(Log.ERROR, pw, "Failed to set the USB port mode: "
+ logAndPrintException(pw, "Failed to set the USB port mode: "
+ "portId=" + portId
- + ", newMode=" + UsbPort.modeToString(newRole.role));
- Thread.dumpStack();
+ + ", newMode=" + UsbPort.modeToString(newRole.role), e);
return;
}
} else {
@@ -271,10 +271,11 @@
try {
mProxy.switchRole(portId, newRole);
} catch (RemoteException e) {
- logAndPrint(Log.ERROR, pw, "Failed to set the USB port power role: "
- + "portId=" + portId
- + ", newPowerRole=" + UsbPort.powerRoleToString(newRole.role));
- Thread.dumpStack();
+ logAndPrintException(pw, "Failed to set the USB port power role: "
+ + "portId=" + portId
+ + ", newPowerRole=" + UsbPort.powerRoleToString
+ (newRole.role),
+ e);
return;
}
}
@@ -285,10 +286,11 @@
try {
mProxy.switchRole(portId, newRole);
} catch (RemoteException e) {
- logAndPrint(Log.ERROR, pw, "Failed to set the USB port data role: "
- + "portId=" + portId
- + ", newDataRole=" + UsbPort.dataRoleToString(newRole.role));
- Thread.dumpStack();
+ logAndPrintException(pw, "Failed to set the USB port data role: "
+ + "portId=" + portId
+ + ", newDataRole=" + UsbPort.dataRoleToString(newRole
+ .role),
+ e);
return;
}
}
@@ -328,7 +330,7 @@
return;
}
- if ((portInfo.mSupportedModes & mode) == 0) {
+ if ((portInfo.supportedModes & mode) == 0) {
pw.println("Simulated port does not support mode: " + UsbPort.modeToString(mode));
return;
}
@@ -340,12 +342,12 @@
+ ", canChangePowerRole=" + canChangePowerRole
+ ", dataRole=" + UsbPort.dataRoleToString(dataRole)
+ ", canChangeDataRole=" + canChangeDataRole);
- portInfo.mCurrentMode = mode;
- portInfo.mCanChangeMode = canChangeMode;
- portInfo.mCurrentPowerRole = powerRole;
- portInfo.mCanChangePowerRole = canChangePowerRole;
- portInfo.mCurrentDataRole = dataRole;
- portInfo.mCanChangeDataRole = canChangeDataRole;
+ portInfo.currentMode = mode;
+ portInfo.canChangeMode = canChangeMode;
+ portInfo.currentPowerRole = powerRole;
+ portInfo.canChangePowerRole = canChangePowerRole;
+ portInfo.currentDataRole = dataRole;
+ portInfo.canChangeDataRole = canChangeDataRole;
updatePortsLocked(pw, null);
}
}
@@ -359,12 +361,12 @@
}
pw.println("Disconnecting simulated port: portId=" + portId);
- portInfo.mCurrentMode = 0;
- portInfo.mCanChangeMode = false;
- portInfo.mCurrentPowerRole = 0;
- portInfo.mCanChangePowerRole = false;
- portInfo.mCurrentDataRole = 0;
- portInfo.mCanChangeDataRole = false;
+ portInfo.currentMode = 0;
+ portInfo.canChangeMode = false;
+ portInfo.currentPowerRole = 0;
+ portInfo.canChangePowerRole = false;
+ portInfo.currentDataRole = 0;
+ portInfo.canChangeDataRole = false;
updatePortsLocked(pw, null);
}
}
@@ -425,7 +427,9 @@
}
public void notifyPortStatusChange(ArrayList<PortStatus> currentPortStatus, int retval) {
- if (!portManager.mSystemReady) return;
+ if (!portManager.mSystemReady) {
+ return;
+ }
if (retval != Status.SUCCESS) {
logAndPrint(Log.ERROR, pw, "port status enquiry failed");
@@ -490,21 +494,21 @@
private void connectToProxy(IndentingPrintWriter pw) {
synchronized (mLock) {
- if (mProxy != null) return;
+ if (mProxy != null) {
+ return;
+ }
try {
- mProxy = IUsb.getService(sSERVICENAME);
+ mProxy = IUsb.getService(sServiceName);
mProxy.linkToDeath(new DeathRecipient(pw), USB_HAL_DEATH_COOKIE);
mProxy.setCallback(mHALCallback);
mProxy.queryPortStatus();
} catch (NoSuchElementException e) {
- logAndPrint(Log.ERROR, pw, sSERVICENAME + " not found."
- + " Did the service fail to start?");
- Thread.dumpStack();
+ logAndPrintException(pw, sServiceName + " not found."
+ + " Did the service fail to start?", e);
} catch (RemoteException e) {
- logAndPrint(Log.ERROR, pw, sSERVICENAME
- + " connectToProxy: Service not responding");
- Thread.dumpStack();
+ logAndPrintException(pw, sServiceName
+ + " connectToProxy: Service not responding", e);
}
}
}
@@ -523,17 +527,17 @@
final int count = mSimulatedPorts.size();
for (int i = 0; i < count; i++) {
final RawPortInfo portInfo = mSimulatedPorts.valueAt(i);
- addOrUpdatePortLocked(portInfo.mPortId, portInfo.mSupportedModes,
- portInfo.mCurrentMode, portInfo.mCanChangeMode,
- portInfo.mCurrentPowerRole, portInfo.mCanChangePowerRole,
- portInfo.mCurrentDataRole, portInfo.mCanChangeDataRole, pw);
+ addOrUpdatePortLocked(portInfo.portId, portInfo.supportedModes,
+ portInfo.currentMode, portInfo.canChangeMode,
+ portInfo.currentPowerRole, portInfo.canChangePowerRole,
+ portInfo.currentDataRole, portInfo.canChangeDataRole, pw);
}
} else {
for (RawPortInfo currentPortInfo : newPortInfo) {
- addOrUpdatePortLocked(currentPortInfo.mPortId, currentPortInfo.mSupportedModes,
- currentPortInfo.mCurrentMode, currentPortInfo.mCanChangeMode,
- currentPortInfo.mCurrentPowerRole, currentPortInfo.mCanChangePowerRole,
- currentPortInfo.mCurrentDataRole, currentPortInfo.mCanChangeDataRole, pw);
+ addOrUpdatePortLocked(currentPortInfo.portId, currentPortInfo.supportedModes,
+ currentPortInfo.currentMode, currentPortInfo.canChangeMode,
+ currentPortInfo.currentPowerRole, currentPortInfo.canChangePowerRole,
+ currentPortInfo.currentDataRole, currentPortInfo.canChangeDataRole, pw);
}
}
@@ -562,18 +566,18 @@
// Must only be called by updatePortsLocked.
private void addOrUpdatePortLocked(String portId, int supportedModes,
- int currentMode, boolean canChangeMode,
- int currentPowerRole, boolean canChangePowerRole,
- int currentDataRole, boolean canChangeDataRole,
- IndentingPrintWriter pw) {
+ int currentMode, boolean canChangeMode,
+ int currentPowerRole, boolean canChangePowerRole,
+ int currentDataRole, boolean canChangeDataRole,
+ IndentingPrintWriter pw) {
// Only allow mode switch capability for dual role ports.
// Validate that the current mode matches the supported modes we expect.
if (supportedModes != UsbPort.MODE_DUAL) {
canChangeMode = false;
if (currentMode != 0 && currentMode != supportedModes) {
logAndPrint(Log.WARN, pw, "Ignoring inconsistent current mode from USB "
- + "port driver: supportedModes=" + UsbPort.modeToString(supportedModes)
- + ", currentMode=" + UsbPort.modeToString(currentMode));
+ + "port driver: supportedModes=" + UsbPort.modeToString(supportedModes)
+ + ", currentMode=" + UsbPort.modeToString(currentMode));
currentMode = 0;
}
}
@@ -588,8 +592,8 @@
// Can change both power and data role independently.
// Assume all combinations are possible.
supportedRoleCombinations |=
- COMBO_SOURCE_HOST | COMBO_SOURCE_DEVICE
- | COMBO_SINK_HOST | COMBO_SINK_DEVICE;
+ COMBO_SOURCE_HOST | COMBO_SOURCE_DEVICE
+ | COMBO_SINK_HOST | COMBO_SINK_DEVICE;
} else if (canChangePowerRole) {
// Can only change power role.
// Assume data role must remain at its current value.
@@ -617,24 +621,24 @@
if (portInfo == null) {
portInfo = new PortInfo(portId, supportedModes);
portInfo.setStatus(currentMode, canChangeMode,
- currentPowerRole, canChangePowerRole,
- currentDataRole, canChangeDataRole,
- supportedRoleCombinations);
+ currentPowerRole, canChangePowerRole,
+ currentDataRole, canChangeDataRole,
+ supportedRoleCombinations);
mPorts.put(portId, portInfo);
} else {
// Sanity check that ports aren't changing definition out from under us.
if (supportedModes != portInfo.mUsbPort.getSupportedModes()) {
logAndPrint(Log.WARN, pw, "Ignoring inconsistent list of supported modes from "
- + "USB port driver (should be immutable): "
- + "previous=" + UsbPort.modeToString(
- portInfo.mUsbPort.getSupportedModes())
- + ", current=" + UsbPort.modeToString(supportedModes));
+ + "USB port driver (should be immutable): "
+ + "previous=" + UsbPort.modeToString(
+ portInfo.mUsbPort.getSupportedModes())
+ + ", current=" + UsbPort.modeToString(supportedModes));
}
if (portInfo.setStatus(currentMode, canChangeMode,
- currentPowerRole, canChangePowerRole,
- currentDataRole, canChangeDataRole,
- supportedRoleCombinations)) {
+ currentPowerRole, canChangePowerRole,
+ currentDataRole, canChangeDataRole,
+ supportedRoleCombinations)) {
portInfo.mDisposition = PortInfo.DISPOSITION_CHANGED;
} else {
portInfo.mDisposition = PortInfo.DISPOSITION_READY;
@@ -661,7 +665,7 @@
final Intent intent = new Intent(UsbManager.ACTION_USB_PORT_CHANGED);
intent.addFlags(
Intent.FLAG_RECEIVER_FOREGROUND |
- Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+ Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
intent.putExtra(UsbManager.EXTRA_PORT, portInfo.mUsbPort);
intent.putExtra(UsbManager.EXTRA_PORT_STATUS, portInfo.mUsbPortStatus);
@@ -682,6 +686,13 @@
}
}
+ private static void logAndPrintException(IndentingPrintWriter pw, String msg, Exception e) {
+ Slog.e(TAG, msg, e);
+ if (pw != null) {
+ pw.println(msg + e);
+ }
+ }
+
private final Handler mHandler = new Handler(FgThread.get().getLooper()) {
@Override
public void handleMessage(Message msg) {
@@ -730,7 +741,7 @@
|| mUsbPortStatus.getCurrentPowerRole() != currentPowerRole
|| mUsbPortStatus.getCurrentDataRole() != currentDataRole
|| mUsbPortStatus.getSupportedRoleCombinations()
- != supportedRoleCombinations) {
+ != supportedRoleCombinations) {
mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
supportedRoleCombinations);
return true;
@@ -752,32 +763,32 @@
* Values of the member variables mocked directly incase of emulation.
*/
private static final class RawPortInfo implements Parcelable {
- public final String mPortId;
- public final int mSupportedModes;
- public int mCurrentMode;
- public boolean mCanChangeMode;
- public int mCurrentPowerRole;
- public boolean mCanChangePowerRole;
- public int mCurrentDataRole;
- public boolean mCanChangeDataRole;
+ public final String portId;
+ public final int supportedModes;
+ public int currentMode;
+ public boolean canChangeMode;
+ public int currentPowerRole;
+ public boolean canChangePowerRole;
+ public int currentDataRole;
+ public boolean canChangeDataRole;
RawPortInfo(String portId, int supportedModes) {
- mPortId = portId;
- mSupportedModes = supportedModes;
+ this.portId = portId;
+ this.supportedModes = supportedModes;
}
RawPortInfo(String portId, int supportedModes,
- int currentMode, boolean canChangeMode,
- int currentPowerRole, boolean canChangePowerRole,
- int currentDataRole, boolean canChangeDataRole) {
- mPortId = portId;
- mSupportedModes = supportedModes;
- mCurrentMode = currentMode;
- mCanChangeMode = canChangeMode;
- mCurrentPowerRole = currentPowerRole;
- mCanChangePowerRole = canChangePowerRole;
- mCurrentDataRole = currentDataRole;
- mCanChangeDataRole = canChangeDataRole;
+ int currentMode, boolean canChangeMode,
+ int currentPowerRole, boolean canChangePowerRole,
+ int currentDataRole, boolean canChangeDataRole) {
+ this.portId = portId;
+ this.supportedModes = supportedModes;
+ this.currentMode = currentMode;
+ this.canChangeMode = canChangeMode;
+ this.currentPowerRole = currentPowerRole;
+ this.canChangePowerRole = canChangePowerRole;
+ this.currentDataRole = currentDataRole;
+ this.canChangeDataRole = canChangeDataRole;
}
@Override
@@ -787,37 +798,37 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mPortId);
- dest.writeInt(mSupportedModes);
- dest.writeInt(mCurrentMode);
- dest.writeByte((byte) (mCanChangeMode ? 1 : 0));
- dest.writeInt(mCurrentPowerRole);
- dest.writeByte((byte) (mCanChangePowerRole ? 1 : 0));
- dest.writeInt(mCurrentDataRole);
- dest.writeByte((byte) (mCanChangeDataRole ? 1 : 0));
+ dest.writeString(portId);
+ dest.writeInt(supportedModes);
+ dest.writeInt(currentMode);
+ dest.writeByte((byte) (canChangeMode ? 1 : 0));
+ dest.writeInt(currentPowerRole);
+ dest.writeByte((byte) (canChangePowerRole ? 1 : 0));
+ dest.writeInt(currentDataRole);
+ dest.writeByte((byte) (canChangeDataRole ? 1 : 0));
}
public static final Parcelable.Creator<RawPortInfo> CREATOR =
new Parcelable.Creator<RawPortInfo>() {
- @Override
- public RawPortInfo createFromParcel(Parcel in) {
- String id = in.readString();
- int supportedModes = in.readInt();
- int currentMode = in.readInt();
- boolean canChangeMode = in.readByte() != 0;
- int currentPowerRole = in.readInt();
- boolean canChangePowerRole = in.readByte() != 0;
- int currentDataRole = in.readInt();
- boolean canChangeDataRole = in.readByte() != 0;
- return new RawPortInfo(id, supportedModes, currentMode, canChangeMode,
- currentPowerRole, canChangePowerRole,
- currentDataRole, canChangeDataRole);
- }
+ @Override
+ public RawPortInfo createFromParcel(Parcel in) {
+ String id = in.readString();
+ int supportedModes = in.readInt();
+ int currentMode = in.readInt();
+ boolean canChangeMode = in.readByte() != 0;
+ int currentPowerRole = in.readInt();
+ boolean canChangePowerRole = in.readByte() != 0;
+ int currentDataRole = in.readInt();
+ boolean canChangeDataRole = in.readByte() != 0;
+ return new RawPortInfo(id, supportedModes, currentMode, canChangeMode,
+ currentPowerRole, canChangePowerRole,
+ currentDataRole, canChangeDataRole);
+ }
- @Override
- public RawPortInfo[] newArray(int size) {
- return new RawPortInfo[size];
- }
- };
+ @Override
+ public RawPortInfo[] newArray(int size) {
+ return new RawPortInfo[size];
+ }
+ };
}
}
diff --git a/telecomm/java/android/telecom/Log.java b/telecomm/java/android/telecom/Log.java
index ced6627..6107895 100644
--- a/telecomm/java/android/telecom/Log.java
+++ b/telecomm/java/android/telecom/Log.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
+import android.os.Build;
import android.telecom.Logging.EventManager;
import android.telecom.Logging.Session;
import android.telecom.Logging.SessionManager;
@@ -55,6 +56,7 @@
public static boolean ERROR = isLoggable(android.util.Log.ERROR);
private static final boolean FORCE_LOGGING = false; /* STOP SHIP if true */
+ private static final boolean USER_BUILD = Build.TYPE.equals("user");
// Used to synchronize singleton logging lazy initialization
private static final Object sSingletonSync = new Object();
@@ -404,7 +406,8 @@
/**
* Redact personally identifiable information for production users.
- * If we are running in verbose mode, return the original string, otherwise
+ * If we are running in verbose mode, return the original string,
+ * and return "****" if we are running on the user build, otherwise
* return a SHA-1 hash of the input string.
*/
public static String pii(Object pii) {
@@ -415,6 +418,11 @@
}
private static String secureHash(byte[] input) {
+ // Refrain from logging user personal information in user build.
+ if (USER_BUILD) {
+ return "****";
+ }
+
if (sMessageDigest != null) {
sMessageDigest.reset();
sMessageDigest.update(input);
diff --git a/telephony/java/android/telephony/Rlog.java b/telephony/java/android/telephony/Rlog.java
index cd0a012..2a31e3a 100644
--- a/telephony/java/android/telephony/Rlog.java
+++ b/telephony/java/android/telephony/Rlog.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
@@ -32,6 +33,8 @@
*/
public final class Rlog {
+ private static final boolean USER_BUILD = Build.TYPE.equals("user");
+
private Rlog() {
}
@@ -125,10 +128,15 @@
/**
* Returns a secure hash (using the SHA1 algorithm) of the provided input.
*
- * @return the hash
+ * @return "****" if the build type is user, otherwise the hash
* @param input the bytes for which the secure hash should be computed.
*/
private static String secureHash(byte[] input) {
+ // Refrain from logging user personal information in user build.
+ if (USER_BUILD) {
+ return "****";
+ }
+
MessageDigest messageDigest;
try {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 92197d6..51b91f4 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -23,6 +23,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.WorkerThread;
import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.app.PendingIntent;
@@ -1495,7 +1496,10 @@
/**
- * Returns the network specifier of the subscription ID pinned to the TelephonyManager.
+ * Returns the network specifier of the subscription ID pinned to the TelephonyManager. The
+ * network specifier is used by {@link
+ * android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to create a {@link
+ * android.net.NetworkRequest} that connects through the subscription.
*
* @see android.net.NetworkRequest.Builder#setNetworkSpecifier(String)
* @see #createForSubscriptionId(int)
@@ -1506,7 +1510,9 @@
}
/**
- * Returns the carrier config of the subscription ID pinned to the TelephonyManager.
+ * Returns the carrier config of the subscription ID pinned to the TelephonyManager. If an
+ * invalid subscription ID is pinned to the TelephonyManager, the returned config will contain
+ * default values.
*
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
* READ_PHONE_STATE}
@@ -1515,6 +1521,7 @@
* @see #createForSubscriptionId(int)
* @see #createForPhoneAccountHandle(PhoneAccountHandle)
*/
+ @WorkerThread
public PersistableBundle getCarrierConfig() {
CarrierConfigManager carrierConfigManager = mContext
.getSystemService(CarrierConfigManager.class);
@@ -2705,19 +2712,24 @@
/**
- * Returns the package responsible of processing visual voicemail for the phone account.
+ * Returns the package responsible of processing visual voicemail for the subscription ID pinned
+ * to the TelephonyManager. Returns {@code null} when there is no package responsible for
+ * processing visual voicemail for the subscription.
*
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
* READ_PHONE_STATE}
+ *
+ * @see #createForSubscriptionId(int)
+ * @see #createForPhoneAccountHandle(PhoneAccountHandle)
+ * @see VisualVoicemailService
*/
@Nullable
- public String getVisualVoicemailPackageName(PhoneAccountHandle phoneAccountHandle) {
+ public String getVisualVoicemailPackageName() {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
return telephony
- .getVisualVoicemailPackageName(mContext.getOpPackageName(),
- phoneAccountHandle);
+ .getVisualVoicemailPackageName(mContext.getOpPackageName(), mSubId);
}
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
diff --git a/telephony/java/android/telephony/VisualVoicemailSms.java b/telephony/java/android/telephony/VisualVoicemailSms.java
index 6235c10..1e6ea4b 100644
--- a/telephony/java/android/telephony/VisualVoicemailSms.java
+++ b/telephony/java/android/telephony/VisualVoicemailSms.java
@@ -63,7 +63,8 @@
/**
* The key-value pairs sent by the SMS, or {@code null} if the framework cannot parse the SMS as
- * voicemail but the carrier pattern indicates it is.
+ * voicemail but the carrier pattern indicates it is. The interpretation of the fields is
+ * carrier dependent.
*/
public Bundle getFields() {
return mFields;
diff --git a/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java b/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java
index 9d19d08..56a8c62 100644
--- a/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java
+++ b/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java
@@ -16,7 +16,6 @@
package android.telephony;
import android.content.Context;
-import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -55,8 +54,17 @@
*/
public static final int DESTINATION_PORT_DATA_SMS = -2;
+ /**
+ * @hide
+ */
public static final String DEFAULT_CLIENT_PREFIX = "//VVM";
+ /**
+ * @hide
+ */
public static final List<String> DEFAULT_ORIGINATING_NUMBERS = Collections.emptyList();
+ /**
+ * @hide
+ */
public static final int DEFAULT_DESTINATION_PORT = DESTINATION_PORT_ANY;
/**
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index 5f3f773..c9c48dc 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -30,9 +30,9 @@
import android.provider.ContactsContract.PhoneLookup;
import android.provider.ContactsContract.RawContacts;
import android.telephony.PhoneNumberUtils;
+import android.telephony.Rlog;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
-import android.telephony.Rlog;
import android.util.Log;
import com.android.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder;
@@ -595,7 +595,8 @@
pn = util.parse(number, countryIso);
if (VDBG) Rlog.v(TAG, "- parsed number: " + pn);
} catch (NumberParseException e) {
- Rlog.w(TAG, "getGeoDescription: NumberParseException for incoming number '" + number + "'");
+ Rlog.w(TAG, "getGeoDescription: NumberParseException for incoming number '"
+ + Rlog.pii(TAG, number) + "'");
}
if (pn != null) {
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 220ea14..40d1dbb 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -504,8 +504,7 @@
boolean isVisualVoicemailEnabled(String callingPackage,
in PhoneAccountHandle accountHandle);
- String getVisualVoicemailPackageName(String callingPackage,
- in PhoneAccountHandle phoneAccountHandle);
+ String getVisualVoicemailPackageName(String callingPackage, int subId);
// Not oneway, caller needs to make sure the vaule is set before receiving a SMS
void enableVisualVoicemailSmsFilter(String callingPackage, int subId,
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 881ac87..3330b1a 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -1513,6 +1513,21 @@
err = NO_ERROR;
}
+ if (mipmaps != NULL) {
+ ResourceDirIterator it(mipmaps, String8("mipmap"));
+ while ((err=it.next()) == NO_ERROR) {
+ err = postProcessImage(bundle, assets, &table, it.getFile());
+ if (err != NO_ERROR) {
+ hasErrors = true;
+ }
+ }
+
+ if (err < NO_ERROR) {
+ hasErrors = true;
+ }
+ err = NO_ERROR;
+ }
+
if (colors != NULL) {
ResourceDirIterator it(colors, String8("color"));
while ((err=it.next()) == NO_ERROR) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java
index af47aeb..4914a48 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java
@@ -75,14 +75,14 @@
// ---- native methods ----
@LayoutlibDelegate
- /*package*/ static long nativeCreate(Bitmap androidBitmap, int shaderTileModeX,
- int shaderTileModeY) {
+ /*package*/ static long nativeCreate(long nativeMatrix, Bitmap androidBitmap,
+ int shaderTileModeX, int shaderTileModeY) {
Bitmap_Delegate bitmap = Bitmap_Delegate.getDelegate(androidBitmap);
if (bitmap == null) {
return 0;
}
- BitmapShader_Delegate newDelegate = new BitmapShader_Delegate(
+ BitmapShader_Delegate newDelegate = new BitmapShader_Delegate(nativeMatrix,
bitmap.getImage(),
Shader_Delegate.getTileMode(shaderTileModeX),
Shader_Delegate.getTileMode(shaderTileModeY));
@@ -91,8 +91,9 @@
// ---- Private delegate/helper methods ----
- private BitmapShader_Delegate(BufferedImage image,
+ private BitmapShader_Delegate(long matrix, BufferedImage image,
TileMode tileModeX, TileMode tileModeY) {
+ super(matrix);
mJavaPaint = new BitmapShaderPaint(image, tileModeX, tileModeY);
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java
index a459734..ab37968 100644
--- a/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java
@@ -63,14 +63,17 @@
// ---- native methods ----
@LayoutlibDelegate
- /*package*/ static long nativeCreate(long native_shaderA, long native_shaderB,
- int native_mode) {
+ /*package*/ static long nativeCreate(long nativeMatrix, long native_shaderA,
+ long native_shaderB, int native_mode) {
// FIXME not supported yet.
- ComposeShader_Delegate newDelegate = new ComposeShader_Delegate();
+ ComposeShader_Delegate newDelegate = new ComposeShader_Delegate(nativeMatrix);
return sManager.addNewDelegate(newDelegate);
}
// ---- Private delegate/helper methods ----
+ private ComposeShader_Delegate(long nativeMatrix) {
+ super(nativeMatrix);
+ }
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java
index 7475c22..6a89d8f 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java
@@ -41,12 +41,14 @@
/**
* Creates the base shader and do some basic test on the parameters.
*
+ * @param nativeMatrix reference to the shader's native transformation matrix
* @param colors The colors to be distributed along the gradient line
* @param positions May be null. The relative positions [0..1] of each
* corresponding color in the colors array. If this is null, the
* the colors are distributed evenly along the gradient line.
*/
- protected Gradient_Delegate(int colors[], float positions[]) {
+ protected Gradient_Delegate(long nativeMatrix, int colors[], float positions[]) {
+ super(nativeMatrix);
if (colors.length < 2) {
throw new IllegalArgumentException("needs >= 2 number of colors");
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
index cbc30c3..cd4393a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
@@ -56,21 +56,20 @@
// ---- native methods ----
@LayoutlibDelegate
- /*package*/ static long nativeCreate1(LinearGradient thisGradient,
+ /*package*/ static long nativeCreate1(LinearGradient thisGradient, long matrix,
float x0, float y0, float x1, float y1,
int colors[], float positions[], int tileMode) {
- LinearGradient_Delegate newDelegate = new LinearGradient_Delegate(x0, y0, x1, y1,
- colors, positions, Shader_Delegate.getTileMode(tileMode));
+ LinearGradient_Delegate newDelegate = new LinearGradient_Delegate(matrix, x0, y0,
+ x1, y1, colors, positions, Shader_Delegate.getTileMode(tileMode));
return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
- /*package*/ static long nativeCreate2(LinearGradient thisGradient,
+ /*package*/ static long nativeCreate2(LinearGradient thisGradient, long matrix,
float x0, float y0, float x1, float y1,
int color0, int color1, int tileMode) {
- return nativeCreate1(thisGradient,
- x0, y0, x1, y1, new int[] { color0, color1}, null /*positions*/,
- tileMode);
+ return nativeCreate1(thisGradient, matrix, x0, y0, x1, y1, new int[] { color0, color1},
+ null /*positions*/, tileMode);
}
// ---- Private delegate/helper methods ----
@@ -78,6 +77,7 @@
/**
* Create a shader that draws a linear gradient along a line.
*
+ * @param nativeMatrix reference to the shader's native transformation matrix
* @param x0 The x-coordinate for the start of the gradient line
* @param y0 The y-coordinate for the start of the gradient line
* @param x1 The x-coordinate for the end of the gradient line
@@ -88,9 +88,9 @@
* the colors are distributed evenly along the gradient line.
* @param tile The Shader tiling mode
*/
- private LinearGradient_Delegate(float x0, float y0, float x1, float y1,
- int colors[], float positions[], TileMode tile) {
- super(colors, positions);
+ private LinearGradient_Delegate(long nativeMatrix, float x0, float y0, float x1,
+ float y1, int colors[], float positions[], TileMode tile) {
+ super(nativeMatrix, colors, positions);
mJavaPaint = new LinearGradientPaint(x0, y0, x1, y1, mColors, mPositions, tile);
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
index 9881a38..b5ba468 100644
--- a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
@@ -56,18 +56,18 @@
// ---- native methods ----
@LayoutlibDelegate
- /*package*/ static long nativeCreate1(float x, float y, float radius,
+ /*package*/ static long nativeCreate1(long matrix, float x, float y, float radius,
int colors[], float positions[], int tileMode) {
- RadialGradient_Delegate newDelegate = new RadialGradient_Delegate(x, y, radius,
+ RadialGradient_Delegate newDelegate = new RadialGradient_Delegate(matrix, x, y, radius,
colors, positions, Shader_Delegate.getTileMode(tileMode));
return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
- /*package*/ static long nativeCreate2(float x, float y, float radius,
+ /*package*/ static long nativeCreate2(long matrix, float x, float y, float radius,
int color0, int color1, int tileMode) {
- return nativeCreate1(x, y, radius, new int[] { color0, color1 }, null /*positions*/,
- tileMode);
+ return nativeCreate1(matrix, x, y, radius, new int[] { color0, color1 },
+ null /*positions*/, tileMode);
}
// ---- Private delegate/helper methods ----
@@ -75,6 +75,7 @@
/**
* Create a shader that draws a radial gradient given the center and radius.
*
+ * @param nativeMatrix reference to the shader's native transformation matrix
* @param x The x-coordinate of the center of the radius
* @param y The y-coordinate of the center of the radius
* @param radius Must be positive. The radius of the circle for this
@@ -86,9 +87,9 @@
* distributed evenly between the center and edge of the circle.
* @param tile The Shader tiling mode
*/
- private RadialGradient_Delegate(float x, float y, float radius, int colors[], float positions[],
- TileMode tile) {
- super(colors, positions);
+ private RadialGradient_Delegate(long nativeMatrix, float x, float y, float radius,
+ int colors[], float positions[], TileMode tile) {
+ super(nativeMatrix, colors, positions);
mJavaPaint = new RadialGradientPaint(x, y, radius, mColors, mPositions, tile);
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
index 0d491a0..5b75089 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
@@ -76,24 +76,16 @@
// ---- native methods ----
@LayoutlibDelegate
- /*package*/ static void nativeDestructor(long native_shader) {
- sManager.removeJavaReferenceFor(native_shader);
- }
-
- @LayoutlibDelegate
- /*package*/ static long nativeSetLocalMatrix(long native_shader, long matrix_instance) {
- // get the delegate from the native int.
- Shader_Delegate shaderDelegate = sManager.getDelegate(native_shader);
- if (shaderDelegate == null) {
- return native_shader;
- }
-
- shaderDelegate.mLocalMatrix = Matrix_Delegate.getDelegate(matrix_instance);
- return native_shader;
+ /*package*/ static void nativeSafeUnref(long nativeInstance) {
+ sManager.removeJavaReferenceFor(nativeInstance);
}
// ---- Private delegate/helper methods ----
+ protected Shader_Delegate(long nativeMatrix) {
+ mLocalMatrix = Matrix_Delegate.getDelegate(nativeMatrix);
+ }
+
protected java.awt.geom.AffineTransform getLocalMatrix() {
if (mLocalMatrix != null) {
return mLocalMatrix.getAffineTransform();
diff --git a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
index 544ba98..30152bc 100644
--- a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
@@ -52,14 +52,17 @@
// ---- native methods ----
@LayoutlibDelegate
- /*package*/ static long nativeCreate1(float x, float y, int colors[], float positions[]) {
- SweepGradient_Delegate newDelegate = new SweepGradient_Delegate(x, y, colors, positions);
+ /*package*/ static long nativeCreate1(long matrix, float x, float y, int colors[], float
+ positions[]) {
+ SweepGradient_Delegate newDelegate = new SweepGradient_Delegate(matrix, x, y, colors,
+ positions);
return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
- /*package*/ static long nativeCreate2(float x, float y, int color0, int color1) {
- return nativeCreate1(x, y, new int[] { color0, color1 }, null /*positions*/);
+ /*package*/ static long nativeCreate2(long matrix, float x, float y, int color0, int color1) {
+ return nativeCreate1(matrix, x, y, new int[] { color0, color1 },
+ null /*positions*/);
}
// ---- Private delegate/helper methods ----
@@ -67,6 +70,7 @@
/**
* A subclass of Shader that draws a sweep gradient around a center point.
*
+ * @param nativeMatrix reference to the shader's native transformation matrix
* @param cx The x-coordinate of the center
* @param cy The y-coordinate of the center
* @param colors The colors to be distributed between around the center.
@@ -78,9 +82,9 @@
* If positions is NULL, then the colors are automatically
* spaced evenly.
*/
- private SweepGradient_Delegate(float cx, float cy,
- int colors[], float positions[]) {
- super(colors, positions);
+ private SweepGradient_Delegate(long nativeMatrix, float cx, float cy,
+ int colors[], float positions[]) {
+ super(nativeMatrix, colors, positions);
mJavaPaint = new SweepGradientPaint(cx, cy, mColors, mPositions);
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 04fdae9..3276628 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -640,7 +640,7 @@
return AccessibilityManager.getInstance(this);
}
- if (AUTO_FILL_MANAGER_SERVICE.equals(service)) {
+ if (AUTOFILL_MANAGER_SERVICE.equals(service)) {
return null;
}
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java
index 156c3fd..82b3792 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.net.wifi.RttManager;
import android.util.Log;
@@ -33,7 +34,8 @@
* <ul>
* <li>Sending messages: {@link #sendMessage(PeerHandle, int, byte[])} method.
* <li>Creating a network-specifier when requesting a Aware connection:
- * {@link #createNetworkSpecifier(PeerHandle, byte[])}.
+ * {@link #createNetworkSpecifierOpen(PeerHandle)} or
+ * {@link #createNetworkSpecifierPassphrase(PeerHandle, String)}.
* </ul>
* The {@link #destroy()} method must be called to destroy discovery sessions once they are
* no longer needed.
@@ -255,7 +257,7 @@
* <p>
* This method should be used when setting up a connection with a peer discovered through Aware
* discovery or communication (in such scenarios the MAC address of the peer is shielded by
- * an opaque peer ID handle). If a Aware connection is needed to a peer discovered using other
+ * an opaque peer ID handle). If an Aware connection is needed to a peer discovered using other
* OOB (out-of-band) mechanism then use the alternative
* {@link WifiAwareSession#createNetworkSpecifierOpen(int, byte[])} method - which uses the
* peer's MAC address.
@@ -263,24 +265,22 @@
* Note: per the Wi-Fi Aware specification the roles are fixed - a Subscriber is an INITIATOR
* and a Publisher is a RESPONDER.
* <p>
- * To set up an encrypted link use the {@link #createNetworkSpecifierPmk(PeerHandle, byte[])}
- * or {@link #createNetworkSpecifierPassphrase(PeerHandle, String)} APIs.
+ * To set up an encrypted link use the
+ * {@link #createNetworkSpecifierPassphrase(PeerHandle, String)} API.
*
* @param peerHandle The peer's handle obtained through
* {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], java.util.List)}
* or
* {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, byte[])}.
* On a RESPONDER this value is used to gate the acceptance of a connection
- * request from only that peer. A RESPONDER may specify a null - indicating
- * that it will accept connection requests from any device.
+ * request from only that peer. A RESPONDER may specify a {@code null} -
+ * indicating that it will accept connection requests from any device.
*
* @return A string to be used to construct
* {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
* {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
- *
- * @hide
*/
public String createNetworkSpecifierOpen(@Nullable PeerHandle peerHandle) {
if (mTerminated) {
@@ -309,7 +309,7 @@
* <p>
* This method should be used when setting up a connection with a peer discovered through Aware
* discovery or communication (in such scenarios the MAC address of the peer is shielded by
- * an opaque peer ID handle). If a Aware connection is needed to a peer discovered using other
+ * an opaque peer ID handle). If an Aware connection is needed to a peer discovered using other
* OOB (out-of-band) mechanism then use the alternative
* {@link WifiAwareSession#createNetworkSpecifierPassphrase(int, byte[], String)} method -
* which uses the peer's MAC address.
@@ -322,12 +322,11 @@
* byte[], java.util.List)} or
* {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
* byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request
- * from only that peer. A RESPONDER may specify a null - indicating that
- * it will accept connection requests from any device.
+ * from only that peer. A RESPONDER may specify a {@code null} - indicating
+ * that it will accept connection requests from any device.
* @param passphrase The passphrase to be used to encrypt the link. The PMK is generated from
* the passphrase. Use the
- * {@link #createNetworkSpecifierPmk(PeerHandle, byte[])} to specify the
- * PMK directly or {@link #createNetworkSpecifierOpen(PeerHandle)} to
+ * {@link #createNetworkSpecifierOpen(PeerHandle)} API to
* specify an open (unencrypted) link.
*
* @return A string to be used to construct
@@ -335,8 +334,6 @@
* {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
- *
- * * @hide
*/
public String createNetworkSpecifierPassphrase(@Nullable PeerHandle peerHandle,
@NonNull String passphrase) {
@@ -371,7 +368,7 @@
* <p>
* This method should be used when setting up a connection with a peer discovered through Aware
* discovery or communication (in such scenarios the MAC address of the peer is shielded by
- * an opaque peer ID handle). If a Aware connection is needed to a peer discovered using other
+ * an opaque peer ID handle). If an Aware connection is needed to a peer discovered using other
* OOB (out-of-band) mechanism then use the alternative
* {@link WifiAwareSession#createNetworkSpecifierPmk(int, byte[], byte[])} method - which uses
* the peer's MAC address.
@@ -400,6 +397,7 @@
*
* @hide
*/
+ @SystemApi
public String createNetworkSpecifierPmk(@Nullable PeerHandle peerHandle,
@NonNull byte[] pmk) {
if (pmk == null || pmk.length == 0) {
@@ -423,27 +421,4 @@
return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerHandle, pmk, null);
}
-
- /**
- * Place-holder for {@code createNetworkSpecifierOpen(PeerHandle)}. Present to enable
- * development of replacements CL without causing an API change. Will be removed when new
- * APIs are exposed.
- *
- * @param peerHandle The peer's handle obtained through
- * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
- * byte[], java.util.List)} or
- * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
- * byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request
- * from only that peer. A RESPONDER may specify a null - indicating that
- * it will accept connection requests from any device.
- * @param token Deprecated and ignored.
- * @return A string to be used to construct
- * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
- * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
- * android.net.ConnectivityManager.NetworkCallback)}
- * [or other varieties of that API].
- */
- public String createNetworkSpecifier(@Nullable PeerHandle peerHandle, @Nullable byte[] token) {
- return createNetworkSpecifierOpen(peerHandle);
- }
}
diff --git a/wifi/java/android/net/wifi/aware/IdentityChangedListener.java b/wifi/java/android/net/wifi/aware/IdentityChangedListener.java
index cae8706..81a06e8 100644
--- a/wifi/java/android/net/wifi/aware/IdentityChangedListener.java
+++ b/wifi/java/android/net/wifi/aware/IdentityChangedListener.java
@@ -24,7 +24,8 @@
* your identity - e.g. by starting a discovery session. This actual MAC address of the
* interface may also be useful if the application uses alternative (non-Aware) discovery but needs
* to set up a Aware connection. The provided Aware discovery interface MAC address can then be used
- * in {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])}.
+ * in {@link WifiAwareSession#createNetworkSpecifierOpen(int, byte[])} or
+ * {@link WifiAwareSession#createNetworkSpecifierPassphrase(int, byte[], String)}.
*/
public class IdentityChangedListener {
/**
diff --git a/wifi/java/android/net/wifi/aware/PeerHandle.java b/wifi/java/android/net/wifi/aware/PeerHandle.java
index bbe9f54..cd45c52 100644
--- a/wifi/java/android/net/wifi/aware/PeerHandle.java
+++ b/wifi/java/android/net/wifi/aware/PeerHandle.java
@@ -19,9 +19,10 @@
/**
* Opaque object used to represent a Wi-Fi Aware peer. Obtained from discovery sessions in
* {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], java.util.List)}, used
- * when sending messages e,g, {@link PublishDiscoverySession#sendMessage(PeerHandle, int, byte[])},
+ * when sending messages e,g, {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])},
* or when configuring a network link to a peer, e.g.
- * {@link PublishDiscoverySession#createNetworkSpecifier(PeerHandle, byte[])}.
+ * {@link DiscoverySession#createNetworkSpecifierOpen(PeerHandle)} or
+ * {@link DiscoverySession#createNetworkSpecifierPassphrase(PeerHandle, String)}.
*/
public class PeerHandle {
/** @hide */
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 7b6805c..4d3957a 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -65,8 +65,10 @@
* <li>Create a Aware network specifier to be used with
* {@link ConnectivityManager#requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback)}
* to set-up a Aware connection with a peer. Refer to
- * {@link DiscoverySession#createNetworkSpecifier(PeerHandle, byte[])} and
- * {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])}.
+ * {@link DiscoverySession#createNetworkSpecifierOpen(PeerHandle)},
+ * {@link DiscoverySession#createNetworkSpecifierPassphrase(PeerHandle, String)},
+ * {@link WifiAwareSession#createNetworkSpecifierOpen(int, byte[])}, and
+ * {@link WifiAwareSession#createNetworkSpecifierPassphrase(int, byte[], String)}.
* </ul>
* <p>
* Aware may not be usable when Wi-Fi is disabled (and other conditions). To validate that
@@ -115,8 +117,10 @@
* <li>{@link NetworkRequest.Builder#addTransportType(int)} of
* {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
* <li>{@link NetworkRequest.Builder#setNetworkSpecifier(String)} using
- * {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])} or
- * {@link DiscoverySession#createNetworkSpecifier(PeerHandle, byte[])}.
+ * {@link WifiAwareSession#createNetworkSpecifierOpen(int, byte[])},
+ * {@link WifiAwareSession#createNetworkSpecifierPassphrase(int, byte[], String)},
+ * {@link DiscoverySession#createNetworkSpecifierOpen(PeerHandle)}, or
+ * {@link DiscoverySession#createNetworkSpecifierPassphrase(PeerHandle, String)}.
* </ul>
*/
public class WifiAwareManager {
@@ -206,8 +210,10 @@
* Connection creation role is that of INITIATOR. Used to create a network specifier string
* when requesting a Aware network.
*
- * @see DiscoverySession#createNetworkSpecifier(PeerHandle, byte[])
- * @see WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])
+ * @see DiscoverySession#createNetworkSpecifierOpen(PeerHandle)
+ * @see DiscoverySession#createNetworkSpecifierPassphrase(PeerHandle, String)
+ * @see WifiAwareSession#createNetworkSpecifierOpen(int, byte[])
+ * @see WifiAwareSession#createNetworkSpecifierPassphrase(int, byte[], String)
*/
public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0;
@@ -215,8 +221,10 @@
* Connection creation role is that of RESPONDER. Used to create a network specifier string
* when requesting a Aware network.
*
- * @see DiscoverySession#createNetworkSpecifier(PeerHandle, byte[])
- * @see WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])
+ * @see DiscoverySession#createNetworkSpecifierOpen(PeerHandle)
+ * @see DiscoverySession#createNetworkSpecifierPassphrase(PeerHandle, String)
+ * @see WifiAwareSession#createNetworkSpecifierOpen(int, byte[])
+ * @see WifiAwareSession#createNetworkSpecifierPassphrase(int, byte[], String)
*/
public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1;
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
index f48f641..895defb 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
@@ -193,15 +194,15 @@
* when using Aware discovery use the alternative network specifier method -
* {@link DiscoverySession#createNetworkSpecifierOpen(PeerHandle)}.
* <p>
- * To set up an encrypted link use the {@link #createNetworkSpecifierPmk(int, byte[], byte[])}
- * or {@link #createNetworkSpecifierPassphrase(int, byte[], String)} APIs.
+ * To set up an encrypted link use the
+ * {@link #createNetworkSpecifierPassphrase(int, byte[], String)} API.
*
* @param role The role of this device:
* {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or
* {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER}
* @param peer The MAC address of the peer's Aware discovery interface. On a RESPONDER this
* value is used to gate the acceptance of a connection request from only that
- * peer. A RESPONDER may specify a null - indicating that it will accept
+ * peer. A RESPONDER may specify a {@code null} - indicating that it will accept
* connection requests from any device.
*
* @return A string to be used to construct
@@ -209,8 +210,6 @@
* {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
- *
- * @hide
*/
public String createNetworkSpecifierOpen(@WifiAwareManager.DataPathRole int role,
@Nullable byte[] peer) {
@@ -242,12 +241,10 @@
* {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER}
* @param peer The MAC address of the peer's Aware discovery interface. On a RESPONDER this
* value is used to gate the acceptance of a connection request from only that
- * peer. A RESPONDER may specify a null - indicating that it will accept
+ * peer. A RESPONDER may specify a {@code null} - indicating that it will accept
* connection requests from any device.
* @param passphrase The passphrase to be used to encrypt the link. The PMK is generated from
- * the passphrase. Use the
- * {@link #createNetworkSpecifierPmk(int, byte[], byte[])} to specify the
- * PMK directly or {@link #createNetworkSpecifierOpen(int, byte[])} to
+ * the passphrase. Use {@link #createNetworkSpecifierOpen(int, byte[])} to
* specify an open (unencrypted) link.
*
* @return A string to be used to construct
@@ -255,8 +252,6 @@
* {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
- *
- * @hide
*/
public String createNetworkSpecifierPassphrase(@WifiAwareManager.DataPathRole int role,
@Nullable byte[] peer, @NonNull String passphrase) {
@@ -307,6 +302,7 @@
*
* @hide
*/
+ @SystemApi
public String createNetworkSpecifierPmk(@WifiAwareManager.DataPathRole int role,
@Nullable byte[] peer, @NonNull byte[] pmk) {
WifiAwareManager mgr = mMgr.get();
@@ -323,28 +319,4 @@
}
return mgr.createNetworkSpecifier(mClientId, role, peer, pmk, null);
}
-
- /**
- * Place-holder for {@code #createNetworkSpecifierOpen(int, byte[])}. Present to enable
- * development of replacements CL without causing an API change. Will be removed when new
- * APIs are exposed.
- *
- * @param role The role of this device:
- * {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or
- * {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER}
- * @param peer The MAC address of the peer's Aware discovery interface. On a RESPONDER this
- * value is used to gate the acceptance of a connection request from only that
- * peer. A RESPONDER may specify a null - indicating that it will accept
- * connection requests from any device.
- * @param token Deprecated and ignored.
- * @return A string to be used to construct
- * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
- * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
- * android.net.ConnectivityManager.NetworkCallback)}
- * [or other varieties of that API].
- */
- public String createNetworkSpecifier(@WifiAwareManager.DataPathRole int role,
- @Nullable byte[] peer, @Nullable byte[] token) {
- return createNetworkSpecifierOpen(role, peer);
- }
}