diff options
208 files changed, 4536 insertions, 2097 deletions
diff --git a/api/current.txt b/api/current.txt index 820b48f59cec..221f18814502 100644 --- a/api/current.txt +++ b/api/current.txt @@ -15,7 +15,6 @@ package android { field public static final java.lang.String ACCESS_WIFI_STATE = "android.permission.ACCESS_WIFI_STATE"; field public static final java.lang.String ACCOUNT_MANAGER = "android.permission.ACCOUNT_MANAGER"; field public static final java.lang.String ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL"; - field public static final java.lang.String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE"; field public static final java.lang.String ANSWER_PHONE_CALLS = "android.permission.ANSWER_PHONE_CALLS"; 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"; @@ -1297,7 +1296,7 @@ package android { field public static final int targetId = 16843740; // 0x10103dc field public static final int targetName = 16843853; // 0x101044d field public static final int targetPackage = 16842785; // 0x1010021 - field public static final int targetProcess = 16844097; // 0x1010541 + field public static final int targetProcesses = 16844097; // 0x1010541 field public static final int targetSandboxVersion = 16844110; // 0x101054e field public static final int targetSdkVersion = 16843376; // 0x1010270 field public static final int taskAffinity = 16842770; // 0x1010012 @@ -2877,7 +2876,8 @@ package android.accessibilityservice { public static abstract class FingerprintGestureController.FingerprintGestureCallback { ctor public FingerprintGestureController.FingerprintGestureCallback(); - method public void onGesture(int); + method public deprecated void onGesture(int); + method public void onGestureDetected(int); method public void onGestureDetectionAvailabilityChanged(boolean); } @@ -3035,8 +3035,8 @@ package android.accounts { field public static final java.lang.String KEY_PASSWORD = "password"; field public static final java.lang.String KEY_USERDATA = "userdata"; field public static final deprecated java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED"; - field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE = "android.accounts.key_legacy_not_visible"; - field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_VISIBLE = "android.accounts.key_legacy_visible"; + field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE = "android:accounts:key_legacy_not_visible"; + field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_VISIBLE = "android:accounts:key_legacy_visible"; field public static final int VISIBILITY_NOT_VISIBLE = 3; // 0x3 field public static final int VISIBILITY_UNDEFINED = 0; // 0x0 field public static final int VISIBILITY_USER_MANAGED_NOT_VISIBLE = 4; // 0x4 @@ -3943,7 +3943,7 @@ package android.app { field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d field public static final int IMPORTANCE_GONE = 1000; // 0x3e8 field public static final int IMPORTANCE_PERCEPTIBLE = 230; // 0xe6 - field public static final deprecated int IMPORTANCE_PERCEPTIBLE_DEPRECATED = 130; // 0x82 + field public static final int IMPORTANCE_PERCEPTIBLE_PRE_26 = 130; // 0x82 field public static final int IMPORTANCE_SERVICE = 300; // 0x12c field public static final int IMPORTANCE_TOP_SLEEPING = 150; // 0x96 field public static final int IMPORTANCE_VISIBLE = 200; // 0xc8 @@ -4030,6 +4030,7 @@ package android.app { method public static android.app.ActivityOptions makeTaskLaunchBehind(); method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int); method public void requestUsageTimeReport(android.app.PendingIntent); + method public android.app.ActivityOptions setAppVerificationBundle(android.os.Bundle); method public android.app.ActivityOptions setLaunchBounds(android.graphics.Rect); method public android.app.ActivityOptions setLaunchDisplayId(int); method public android.os.Bundle toBundle(); @@ -4817,6 +4818,7 @@ package android.app { method public void onFragmentDetached(android.app.FragmentManager, android.app.Fragment); method public void onFragmentPaused(android.app.FragmentManager, android.app.Fragment); method public void onFragmentPreAttached(android.app.FragmentManager, android.app.Fragment, android.content.Context); + method public void onFragmentPreCreated(android.app.FragmentManager, android.app.Fragment, android.os.Bundle); method public void onFragmentResumed(android.app.FragmentManager, android.app.Fragment); method public void onFragmentSaveInstanceState(android.app.FragmentManager, android.app.Fragment, android.os.Bundle); method public void onFragmentStarted(android.app.FragmentManager, android.app.Fragment); @@ -4849,10 +4851,10 @@ package android.app { method public abstract android.app.FragmentTransaction hide(android.app.Fragment); method public abstract boolean isAddToBackStackAllowed(); method public abstract boolean isEmpty(); - method public abstract android.app.FragmentTransaction postOnCommit(java.lang.Runnable); method public abstract android.app.FragmentTransaction remove(android.app.Fragment); method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment); method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment, java.lang.String); + method public abstract android.app.FragmentTransaction runOnCommit(java.lang.Runnable); method public abstract android.app.FragmentTransaction setBreadCrumbShortTitle(int); method public abstract android.app.FragmentTransaction setBreadCrumbShortTitle(java.lang.CharSequence); method public abstract android.app.FragmentTransaction setBreadCrumbTitle(int); @@ -4954,7 +4956,7 @@ package android.app { method public final android.app.Activity getLastActivity(); method public final android.app.Instrumentation.ActivityResult getResult(); method public final boolean isBlocking(); - method public android.app.Instrumentation.ActivityResult onMatchIntent(android.content.Intent); + method public android.app.Instrumentation.ActivityResult onStartActivity(android.content.Intent); method public final android.app.Activity waitForActivity(); method public final android.app.Activity waitForActivityWithTimeout(long); } @@ -4974,7 +4976,7 @@ package android.app { public class KeyguardManager { method public android.content.Intent createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence); - method public void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler); + method public deprecated void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler); method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult); method public boolean inKeyguardRestrictedInputMode(); method public boolean isDeviceLocked(); @@ -4982,6 +4984,7 @@ package android.app { method public boolean isKeyguardLocked(); method public boolean isKeyguardSecure(); method public deprecated android.app.KeyguardManager.KeyguardLock newKeyguardLock(java.lang.String); + method public void requestDismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback); } public static abstract class KeyguardManager.KeyguardDismissCallback { @@ -6112,17 +6115,6 @@ package android.app { method public void onDetached(); } - public final class WallpaperColors implements android.os.Parcelable { - ctor public WallpaperColors(android.os.Parcel); - ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>); - ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>, boolean); - method public int describeContents(); - method public java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>> getColors(); - method public boolean supportsDarkText(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR; - } - public final class WallpaperInfo implements android.os.Parcelable { ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public int describeContents(); @@ -6145,8 +6137,6 @@ package android.app { } public class WallpaperManager { - method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener); - method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler); method public void clear() throws java.io.IOException; method public void clear(int) throws java.io.IOException; method public void clearWallpaperOffsets(android.os.IBinder); @@ -6161,7 +6151,6 @@ package android.app { method public android.graphics.drawable.Drawable getDrawable(); method public android.graphics.drawable.Drawable getFastDrawable(); method public static android.app.WallpaperManager getInstance(android.content.Context); - method public android.app.WallpaperColors getWallpaperColors(int); method public android.os.ParcelFileDescriptor getWallpaperFile(int); method public int getWallpaperId(int); method public android.app.WallpaperInfo getWallpaperInfo(); @@ -6170,7 +6159,6 @@ package android.app { method public boolean isWallpaperSupported(); method public android.graphics.drawable.Drawable peekDrawable(); method public android.graphics.drawable.Drawable peekFastDrawable(); - method public void removeOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener); method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle); method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException; method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException; @@ -6195,16 +6183,12 @@ package android.app { field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview"; } - public static abstract interface WallpaperManager.OnColorsChangedListener { - method public abstract void onColorsChanged(android.app.WallpaperColors, int); - } - } package android.app.admin { public final class ConnectEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable { - method public java.lang.String getIpAddress(); + method public java.net.InetAddress getInetAddress(); method public int getPort(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.admin.ConnectEvent> CREATOR; @@ -6509,7 +6493,7 @@ package android.app.admin { field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_PORT = "android.app.extra.PROVISIONING_WIFI_PROXY_PORT"; field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE = "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE"; field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SSID = "android.app.extra.PROVISIONING_WIFI_SSID"; - field public static final int FLAG_EVICT_CE_KEY = 1; // 0x1 + field public static final int FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY = 1; // 0x1 field public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 2; // 0x2 field public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 1; // 0x1 field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff @@ -6547,8 +6531,8 @@ package android.app.admin { public final class DnsEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable { method public java.lang.String getHostname(); - method public java.lang.String[] getIpAddresses(); - method public int getIpAddressesCount(); + method public java.util.List<java.net.InetAddress> getInetAddresses(); + method public int getTotalResolvedAddressCount(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.admin.DnsEvent> CREATOR; } @@ -7008,8 +6992,8 @@ package android.app.usage { public final class StorageStats implements android.os.Parcelable { method public int describeContents(); + method public long getAppBytes(); method public long getCacheBytes(); - method public long getCodeBytes(); method public long getDataBytes(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.usage.StorageStats> CREATOR; @@ -8217,8 +8201,10 @@ package android.bluetooth.le { field public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanResult> CREATOR; field public static final int DATA_COMPLETE = 0; // 0x0 field public static final int DATA_TRUNCATED = 2; // 0x2 + field public static final int PERIODIC_INTERVAL_NOT_PRESENT = 0; // 0x0 field public static final int PHY_UNUSED = 0; // 0x0 field public static final int SID_NOT_PRESENT = 255; // 0xff + field public static final int TX_POWER_NOT_PRESENT = 127; // 0x7f } public final class ScanSettings implements android.os.Parcelable { @@ -8289,21 +8275,21 @@ package android.companion { method public android.companion.BluetoothDeviceFilter.Builder setNamePattern(java.util.regex.Pattern); } - public final class BluetoothLEDeviceFilter implements android.companion.DeviceFilter { + 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; + field public static final android.os.Parcelable.Creator<android.companion.BluetoothLeDeviceFilter> CREATOR; } - public static final class BluetoothLEDeviceFilter.Builder { - 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 setRenameFromBytes(java.lang.String, java.lang.String, int, int, boolean); - method public android.companion.BluetoothLEDeviceFilter.Builder setRenameFromName(java.lang.String, java.lang.String, int, int); - method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter); + public static final class BluetoothLeDeviceFilter.Builder { + 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 setRenameFromBytes(java.lang.String, java.lang.String, int, int, boolean); + method public android.companion.BluetoothLeDeviceFilter.Builder setRenameFromName(java.lang.String, java.lang.String, int, int); + method public android.companion.BluetoothLeDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter); } public final class CompanionDeviceManager { @@ -8439,7 +8425,7 @@ package android.content { ctor public ClipData(android.content.ClipDescription, android.content.ClipData.Item); ctor public ClipData(android.content.ClipData); method public void addItem(android.content.ClipData.Item); - method public void addItem(android.content.ClipData.Item, android.content.ContentResolver); + method public void addItem(android.content.ContentResolver, android.content.ClipData.Item); method public int describeContents(); method public android.content.ClipDescription getDescription(); method public android.content.ClipData.Item getItemAt(int); @@ -9511,6 +9497,7 @@ package android.content { field public static final java.lang.String EXTRA_CHOOSER_TARGETS = "android.intent.extra.CHOOSER_TARGETS"; field public static final java.lang.String EXTRA_CHOSEN_COMPONENT = "android.intent.extra.CHOSEN_COMPONENT"; field public static final java.lang.String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER = "android.intent.extra.CHOSEN_COMPONENT_INTENT_SENDER"; + field public static final java.lang.String EXTRA_COMPONENT_NAME = "android.intent.extra.COMPONENT_NAME"; field public static final java.lang.String EXTRA_CONTENT_ANNOTATIONS = "android.intent.extra.CONTENT_ANNOTATIONS"; field public static final java.lang.String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED"; field public static final java.lang.String EXTRA_DOCK_STATE = "android.intent.extra.DOCK_STATE"; @@ -10334,7 +10321,7 @@ package android.content.pm { field public java.lang.String[] splitPublicSourceDirs; field public java.lang.String[] splitSourceDirs; field public java.lang.String targetPackage; - field public java.lang.String targetProcess; + field public java.lang.String targetProcesses; } public class LabeledIntent extends android.content.Intent { @@ -13776,6 +13763,7 @@ package android.graphics { method public void detachFromGLContext(); method public long getTimestamp(); method public void getTransformMatrix(float[]); + method public boolean isReleased(); method public void release(); method public void releaseTexImage(); method public void setDefaultBufferSize(int, int); @@ -14508,7 +14496,7 @@ package android.hardware { method public final void takePicture(android.hardware.Camera.ShutterCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback); method public final void unlock(); field public static final java.lang.String ACTION_NEW_PICTURE = "android.hardware.action.NEW_PICTURE"; - field public static final deprecated java.lang.String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO"; + field public static final java.lang.String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO"; field public static final int CAMERA_ERROR_EVICTED = 2; // 0x2 field public static final int CAMERA_ERROR_SERVER_DIED = 100; // 0x64 field public static final int CAMERA_ERROR_UNKNOWN = 1; // 0x1 @@ -14769,18 +14757,16 @@ package android.hardware { field public static final int RGBX_8888 = 2; // 0x2 field public static final int RGB_565 = 4; // 0x4 field public static final int RGB_888 = 3; // 0x3 - field public static final long USAGE0_CPU_READ = 2L; // 0x2L - field public static final long USAGE0_CPU_READ_OFTEN = 6L; // 0x6L - field public static final long USAGE0_CPU_WRITE = 32L; // 0x20L - field public static final long USAGE0_CPU_WRITE_OFTEN = 96L; // 0x60L - field public static final long USAGE0_GPU_COLOR_OUTPUT = 2048L; // 0x800L - field public static final long USAGE0_GPU_CUBEMAP = 8192L; // 0x2000L - field public static final long USAGE0_GPU_DATA_BUFFER = 16384L; // 0x4000L - field public static final long USAGE0_GPU_SAMPLED_IMAGE = 1024L; // 0x400L - field public static final long USAGE0_GPU_STORAGE_IMAGE = 3072L; // 0xc00L - field public static final long USAGE0_PROTECTED_CONTENT = 262144L; // 0x40000L - field public static final long USAGE0_SENSOR_DIRECT_DATA = 536870912L; // 0x20000000L - field public static final long USAGE0_VIDEO_ENCODE = 2097152L; // 0x200000L + field public static final long USAGE_CPU_READ_OFTEN = 3L; // 0x3L + field public static final long USAGE_CPU_READ_RARELY = 2L; // 0x2L + field public static final long USAGE_CPU_WRITE_OFTEN = 48L; // 0x30L + field public static final long USAGE_CPU_WRITE_RARELY = 32L; // 0x20L + field public static final long USAGE_GPU_COLOR_OUTPUT = 512L; // 0x200L + field public static final long USAGE_GPU_DATA_BUFFER = 16777216L; // 0x1000000L + field public static final long USAGE_GPU_SAMPLED_IMAGE = 256L; // 0x100L + field public static final long USAGE_PROTECTED_CONTENT = 16384L; // 0x4000L + field public static final long USAGE_SENSOR_DIRECT_DATA = 8388608L; // 0x800000L + field public static final long USAGE_VIDEO_ENCODE = 65536L; // 0x10000L } public final class Sensor { @@ -25412,8 +25398,8 @@ package android.net { method public boolean requestBandwidthUpdate(android.net.Network); method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback); method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler); - method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback); - method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback, android.os.Handler); + method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, int); + method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler, int); method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent); method public deprecated void setNetworkPreference(int); method public static deprecated boolean setProcessDefaultNetwork(android.net.Network); @@ -30692,7 +30678,6 @@ package android.os { method public android.util.SizeF getSizeF(java.lang.String); method public <T extends android.os.Parcelable> android.util.SparseArray<T> getSparseParcelableArray(java.lang.String); method public java.util.ArrayList<java.lang.String> getStringArrayList(java.lang.String); - method public java.util.UUID getUuid(java.lang.String); method public boolean hasFileDescriptors(); method public void putAll(android.os.Bundle); method public void putBinder(java.lang.String, android.os.IBinder); @@ -30717,7 +30702,6 @@ package android.os { method public void putSizeF(java.lang.String, android.util.SizeF); method public void putSparseParcelableArray(java.lang.String, android.util.SparseArray<? extends android.os.Parcelable>); method public void putStringArrayList(java.lang.String, java.util.ArrayList<java.lang.String>); - method public void putUuid(java.lang.String, java.util.UUID); method public void readFromParcel(android.os.Parcel); method public void setClassLoader(java.lang.ClassLoader); method public void writeToParcel(android.os.Parcel, int); @@ -31247,7 +31231,6 @@ package android.os { method public final <T> void readTypedArray(T[], android.os.Parcelable.Creator<T>); method public final <T> void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>); method public final <T> T readTypedObject(android.os.Parcelable.Creator<T>); - method public final java.util.UUID readUuid(); method public final java.lang.Object readValue(java.lang.ClassLoader); method public final void recycle(); method public final void setDataCapacity(int); @@ -31293,7 +31276,6 @@ package android.os { method public final <T extends android.os.Parcelable> void writeTypedArray(T[], int); method public final <T extends android.os.Parcelable> void writeTypedList(java.util.List<T>); method public final <T extends android.os.Parcelable> void writeTypedObject(T, int); - method public final void writeUuid(java.util.UUID); method public final void writeValue(java.lang.Object); field public static final android.os.Parcelable.Creator<java.lang.String> STRING_CREATOR; } @@ -31696,6 +31678,7 @@ package android.os { field public static final java.lang.String DISALLOW_APPS_CONTROL = "no_control_apps"; field public static final java.lang.String DISALLOW_AUTOFILL = "no_autofill"; field public static final java.lang.String DISALLOW_BLUETOOTH = "no_bluetooth"; + field public static final java.lang.String DISALLOW_BLUETOOTH_SHARING = "no_bluetooth_sharing"; field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth"; field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts"; field public static final java.lang.String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials"; @@ -31924,9 +31907,9 @@ package android.os.storage { } public class StorageManager { - method public void allocateBytes(java.util.UUID, long, int) throws java.io.IOException; - method public void allocateBytes(java.io.FileDescriptor, long, int) throws java.io.IOException; - method public long getAllocatableBytes(java.util.UUID, int) throws java.io.IOException; + method public void allocateBytes(java.util.UUID, long) throws java.io.IOException; + method public void allocateBytes(java.io.FileDescriptor, long) throws java.io.IOException; + method public long getAllocatableBytes(java.util.UUID) throws java.io.IOException; method public long getCacheQuotaBytes(java.util.UUID) throws java.io.IOException; method public long getCacheSizeBytes(java.util.UUID) throws java.io.IOException; method public java.lang.String getMountedObbPath(java.lang.String); @@ -31939,7 +31922,6 @@ package android.os.storage { method public boolean isEncrypted(java.io.File); method public boolean isObbMounted(java.lang.String); method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener); - method public android.os.ParcelFileDescriptor openProxyFileDescriptor(int, android.os.ProxyFileDescriptorCallback) throws java.io.IOException; method public android.os.ParcelFileDescriptor openProxyFileDescriptor(int, android.os.ProxyFileDescriptorCallback, android.os.Handler) throws java.io.IOException; method public void setCacheBehaviorGroup(java.io.File, boolean) throws java.io.IOException; method public void setCacheBehaviorTombstone(java.io.File, boolean) throws java.io.IOException; @@ -31947,7 +31929,6 @@ package android.os.storage { field public static final java.lang.String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE"; field public static final java.lang.String EXTRA_REQUESTED_BYTES = "android.os.storage.extra.REQUESTED_BYTES"; field public static final java.lang.String EXTRA_UUID = "android.os.storage.extra.UUID"; - field public static final int FLAG_ALLOCATE_AGGRESSIVE = 1; // 0x1 field public static final java.util.UUID UUID_DEFAULT; } @@ -34438,7 +34419,6 @@ package android.provider { } public class FontsContract { - method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[], int, boolean, java.lang.String); method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[]); method public static android.provider.FontsContract.FontFamilyResult fetchFonts(android.content.Context, android.os.CancellationSignal, android.provider.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException; method public static void requestFonts(android.content.Context, android.provider.FontRequest, android.os.Handler, android.os.CancellationSignal, android.provider.FontsContract.FontRequestCallback); @@ -37500,7 +37480,6 @@ package android.service.quicksettings { method public final void unlockAndRun(java.lang.Runnable); field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE"; field public static final java.lang.String ACTION_QS_TILE_PREFERENCES = "android.service.quicksettings.action.QS_TILE_PREFERENCES"; - field public static final java.lang.String EXTRA_COMPONENT = "android.service.quicksettings.extra.COMPONENT"; field public static final java.lang.String META_DATA_ACTIVE_TILE = "android.service.quicksettings.ACTIVE_TILE"; } @@ -37730,12 +37709,10 @@ package android.service.wallpaper { method public int getDesiredMinimumHeight(); method public int getDesiredMinimumWidth(); method public android.view.SurfaceHolder getSurfaceHolder(); - method public void invalidateColors(); method public boolean isPreview(); method public boolean isVisible(); method public void onApplyWindowInsets(android.view.WindowInsets); method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean); - method public android.app.WallpaperColors onComputeWallpaperColors(); method public void onCreate(android.view.SurfaceHolder); method public void onDesiredSizeChanged(int, int); method public void onDestroy(); @@ -45828,6 +45805,7 @@ package android.view { 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_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 1; // 0x1 field public static final java.lang.String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE = "creditCardExpirationDate"; field public static final java.lang.String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay"; field public static final java.lang.String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = "creditCardExpirationMonth"; @@ -46539,7 +46517,7 @@ package android.view { public static abstract class ViewStructure.HtmlInfo { ctor public ViewStructure.HtmlInfo(); - method public abstract java.util.ArrayList<android.util.Pair<java.lang.String, java.lang.String>> getAttributes(); + method public abstract java.util.List<android.util.Pair<java.lang.String, java.lang.String>> getAttributes(); method public abstract java.lang.String getTag(); } @@ -47795,7 +47773,7 @@ package android.view.autofill { method public void unregisterCallback(android.view.autofill.AutofillManager.AutofillCallback); 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"; - field public static final java.lang.String EXTRA_DATA_EXTRAS = "android.view.autofill.extra.DATA_EXTRAS"; + field public static final java.lang.String EXTRA_CLIENT_STATE = "android.view.autofill.extra.EXTRA_CLIENT_STATE"; } public static abstract class AutofillManager.AutofillCallback { @@ -48936,7 +48914,6 @@ package android.webkit { method public int getRendererRequestedPriority(); method public deprecated float getScale(); method public android.webkit.WebSettings getSettings(); - method public android.view.textclassifier.TextClassifier getTextClassifier(); method public java.lang.String getTitle(); method public java.lang.String getUrl(); method public android.webkit.WebChromeClient getWebChromeClient(); @@ -48953,7 +48930,6 @@ package android.webkit { method public deprecated void onChildViewAdded(android.view.View, android.view.View); method public deprecated void onChildViewRemoved(android.view.View, android.view.View); method public deprecated void onGlobalFocusChanged(android.view.View, android.view.View); - method public void onMovedToDisplay(int, android.content.res.Configuration); method public void onPause(); method public void onResume(); method public deprecated boolean overlayHorizontalScrollbar(); @@ -48984,7 +48960,6 @@ package android.webkit { method public void setNetworkAvailable(boolean); method public deprecated void setPictureListener(android.webkit.WebView.PictureListener); method public void setRendererPriorityPolicy(int, boolean); - method public void setTextClassifier(android.view.textclassifier.TextClassifier); method public deprecated void setVerticalScrollbarOverlay(boolean); method public void setWebChromeClient(android.webkit.WebChromeClient); method public static void setWebContentsDebuggingEnabled(boolean); diff --git a/api/removed.txt b/api/removed.txt index 13bccd6b42ed..8c81ef42371e 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -18,12 +18,17 @@ package android.app.admin { method public deprecated java.lang.String getDeviceInitializerApp(); method public deprecated android.content.ComponentName getDeviceInitializerComponent(); method public void setAffiliationIds(android.content.ComponentName, java.util.List<java.lang.String>); + field public static final deprecated int FLAG_EVICT_CE_KEY = 1; // 0x1 } } package android.app.usage { + public final class StorageStats implements android.os.Parcelable { + method public deprecated long getCodeBytes(); + } + public class StorageStatsManager { method public deprecated long getFreeBytes(java.lang.String) throws java.io.IOException; method public deprecated long getTotalBytes(java.lang.String) throws java.io.IOException; @@ -38,6 +43,10 @@ package android.app.usage { package android.content { + public class ClipData implements android.os.Parcelable { + method public deprecated void addItem(android.content.ClipData.Item, android.content.ContentResolver); + } + public abstract class Context { method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int); method public abstract java.io.File getSharedPreferencesPath(java.lang.String); diff --git a/api/system-current.txt b/api/system-current.txt index 3418eb6dead2..84f8b55b8730 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1422,7 +1422,7 @@ package android { field public static final int targetId = 16843740; // 0x10103dc field public static final int targetName = 16843853; // 0x101044d field public static final int targetPackage = 16842785; // 0x1010021 - field public static final int targetProcess = 16844097; // 0x1010541 + field public static final int targetProcesses = 16844097; // 0x1010541 field public static final int targetSandboxVersion = 16844110; // 0x101054e field public static final int targetSdkVersion = 16843376; // 0x1010270 field public static final int taskAffinity = 16842770; // 0x1010012 @@ -3005,7 +3005,8 @@ package android.accessibilityservice { public static abstract class FingerprintGestureController.FingerprintGestureCallback { ctor public FingerprintGestureController.FingerprintGestureCallback(); - method public void onGesture(int); + method public deprecated void onGesture(int); + method public void onGestureDetected(int); method public void onGestureDetectionAvailabilityChanged(boolean); } @@ -3164,8 +3165,8 @@ package android.accounts { field public static final java.lang.String KEY_PASSWORD = "password"; field public static final java.lang.String KEY_USERDATA = "userdata"; field public static final deprecated java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED"; - field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE = "android.accounts.key_legacy_not_visible"; - field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_VISIBLE = "android.accounts.key_legacy_visible"; + field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE = "android:accounts:key_legacy_not_visible"; + field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_VISIBLE = "android:accounts:key_legacy_visible"; field public static final int VISIBILITY_NOT_VISIBLE = 3; // 0x3 field public static final int VISIBILITY_UNDEFINED = 0; // 0x0 field public static final int VISIBILITY_USER_MANAGED_NOT_VISIBLE = 4; // 0x4 @@ -4092,7 +4093,7 @@ package android.app { field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d field public static final int IMPORTANCE_GONE = 1000; // 0x3e8 field public static final int IMPORTANCE_PERCEPTIBLE = 230; // 0xe6 - field public static final deprecated int IMPORTANCE_PERCEPTIBLE_DEPRECATED = 130; // 0x82 + field public static final int IMPORTANCE_PERCEPTIBLE_PRE_26 = 130; // 0x82 field public static final int IMPORTANCE_SERVICE = 300; // 0x12c field public static final int IMPORTANCE_TOP_SLEEPING = 150; // 0x96 field public static final int IMPORTANCE_VISIBLE = 200; // 0xc8 @@ -4179,6 +4180,7 @@ package android.app { method public static android.app.ActivityOptions makeTaskLaunchBehind(); method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int); method public void requestUsageTimeReport(android.app.PendingIntent); + method public android.app.ActivityOptions setAppVerificationBundle(android.os.Bundle); method public android.app.ActivityOptions setLaunchBounds(android.graphics.Rect); method public android.app.ActivityOptions setLaunchDisplayId(int); method public android.os.Bundle toBundle(); @@ -4985,6 +4987,7 @@ package android.app { method public void onFragmentDetached(android.app.FragmentManager, android.app.Fragment); method public void onFragmentPaused(android.app.FragmentManager, android.app.Fragment); method public void onFragmentPreAttached(android.app.FragmentManager, android.app.Fragment, android.content.Context); + method public void onFragmentPreCreated(android.app.FragmentManager, android.app.Fragment, android.os.Bundle); method public void onFragmentResumed(android.app.FragmentManager, android.app.Fragment); method public void onFragmentSaveInstanceState(android.app.FragmentManager, android.app.Fragment, android.os.Bundle); method public void onFragmentStarted(android.app.FragmentManager, android.app.Fragment); @@ -5017,10 +5020,10 @@ package android.app { method public abstract android.app.FragmentTransaction hide(android.app.Fragment); method public abstract boolean isAddToBackStackAllowed(); method public abstract boolean isEmpty(); - method public abstract android.app.FragmentTransaction postOnCommit(java.lang.Runnable); method public abstract android.app.FragmentTransaction remove(android.app.Fragment); method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment); method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment, java.lang.String); + method public abstract android.app.FragmentTransaction runOnCommit(java.lang.Runnable); method public abstract android.app.FragmentTransaction setBreadCrumbShortTitle(int); method public abstract android.app.FragmentTransaction setBreadCrumbShortTitle(java.lang.CharSequence); method public abstract android.app.FragmentTransaction setBreadCrumbTitle(int); @@ -5134,7 +5137,7 @@ package android.app { method public final android.app.Activity getLastActivity(); method public final android.app.Instrumentation.ActivityResult getResult(); method public final boolean isBlocking(); - method public android.app.Instrumentation.ActivityResult onMatchIntent(android.content.Intent); + method public android.app.Instrumentation.ActivityResult onStartActivity(android.content.Intent); method public final android.app.Activity waitForActivity(); method public final android.app.Activity waitForActivityWithTimeout(long); } @@ -5154,7 +5157,7 @@ package android.app { public class KeyguardManager { method public android.content.Intent createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence); - method public void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler); + method public deprecated void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler); method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult); method public boolean inKeyguardRestrictedInputMode(); method public boolean isDeviceLocked(); @@ -5162,6 +5165,7 @@ package android.app { method public boolean isKeyguardLocked(); method public boolean isKeyguardSecure(); method public deprecated android.app.KeyguardManager.KeyguardLock newKeyguardLock(java.lang.String); + method public void requestDismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback); } public static abstract class KeyguardManager.KeyguardDismissCallback { @@ -6321,17 +6325,6 @@ package android.app { method public void setPersistentVrModeEnabled(boolean); } - public final class WallpaperColors implements android.os.Parcelable { - ctor public WallpaperColors(android.os.Parcel); - ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>); - ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>, boolean); - method public int describeContents(); - method public java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>> getColors(); - method public boolean supportsDarkText(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR; - } - public final class WallpaperInfo implements android.os.Parcelable { ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public int describeContents(); @@ -6354,8 +6347,6 @@ package android.app { } public class WallpaperManager { - method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener); - method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler); method public void clear() throws java.io.IOException; method public void clear(int) throws java.io.IOException; method public void clearWallpaper(); @@ -6372,7 +6363,6 @@ package android.app { method public android.graphics.drawable.Drawable getDrawable(); method public android.graphics.drawable.Drawable getFastDrawable(); method public static android.app.WallpaperManager getInstance(android.content.Context); - method public android.app.WallpaperColors getWallpaperColors(int); method public android.os.ParcelFileDescriptor getWallpaperFile(int); method public int getWallpaperId(int); method public android.app.WallpaperInfo getWallpaperInfo(); @@ -6381,7 +6371,6 @@ package android.app { method public boolean isWallpaperSupported(); method public android.graphics.drawable.Drawable peekDrawable(); method public android.graphics.drawable.Drawable peekFastDrawable(); - method public void removeOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener); method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle); method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException; method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException; @@ -6409,16 +6398,12 @@ package android.app { field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview"; } - public static abstract interface WallpaperManager.OnColorsChangedListener { - method public abstract void onColorsChanged(android.app.WallpaperColors, int); - } - } package android.app.admin { public final class ConnectEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable { - method public java.lang.String getIpAddress(); + method public java.net.InetAddress getInetAddress(); method public int getPort(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.admin.ConnectEvent> CREATOR; @@ -6752,7 +6737,7 @@ package android.app.admin { field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_PORT = "android.app.extra.PROVISIONING_WIFI_PROXY_PORT"; field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE = "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE"; field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SSID = "android.app.extra.PROVISIONING_WIFI_SSID"; - field public static final int FLAG_EVICT_CE_KEY = 1; // 0x1 + field public static final int FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY = 1; // 0x1 field public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 2; // 0x2 field public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 1; // 0x1 field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff @@ -6795,8 +6780,8 @@ package android.app.admin { public final class DnsEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable { method public java.lang.String getHostname(); - method public java.lang.String[] getIpAddresses(); - method public int getIpAddressesCount(); + method public java.util.List<java.net.InetAddress> getInetAddresses(); + method public int getTotalResolvedAddressCount(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.admin.DnsEvent> CREATOR; } @@ -7477,8 +7462,8 @@ package android.app.usage { public final class StorageStats implements android.os.Parcelable { method public int describeContents(); + method public long getAppBytes(); method public long getCacheBytes(); - method public long getCodeBytes(); method public long getDataBytes(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.usage.StorageStats> CREATOR; @@ -8708,8 +8693,10 @@ package android.bluetooth.le { field public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanResult> CREATOR; field public static final int DATA_COMPLETE = 0; // 0x0 field public static final int DATA_TRUNCATED = 2; // 0x2 + field public static final int PERIODIC_INTERVAL_NOT_PRESENT = 0; // 0x0 field public static final int PHY_UNUSED = 0; // 0x0 field public static final int SID_NOT_PRESENT = 255; // 0xff + field public static final int TX_POWER_NOT_PRESENT = 127; // 0x7f } public final class ScanSettings implements android.os.Parcelable { @@ -8789,21 +8776,21 @@ package android.companion { method public android.companion.BluetoothDeviceFilter.Builder setNamePattern(java.util.regex.Pattern); } - public final class BluetoothLEDeviceFilter implements android.companion.DeviceFilter { + 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; + field public static final android.os.Parcelable.Creator<android.companion.BluetoothLeDeviceFilter> CREATOR; } - public static final class BluetoothLEDeviceFilter.Builder { - 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 setRenameFromBytes(java.lang.String, java.lang.String, int, int, boolean); - method public android.companion.BluetoothLEDeviceFilter.Builder setRenameFromName(java.lang.String, java.lang.String, int, int); - method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter); + public static final class BluetoothLeDeviceFilter.Builder { + 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 setRenameFromBytes(java.lang.String, java.lang.String, int, int, boolean); + method public android.companion.BluetoothLeDeviceFilter.Builder setRenameFromName(java.lang.String, java.lang.String, int, int); + method public android.companion.BluetoothLeDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter); } public final class CompanionDeviceManager { @@ -8939,7 +8926,7 @@ package android.content { ctor public ClipData(android.content.ClipDescription, android.content.ClipData.Item); ctor public ClipData(android.content.ClipData); method public void addItem(android.content.ClipData.Item); - method public void addItem(android.content.ClipData.Item, android.content.ContentResolver); + method public void addItem(android.content.ContentResolver, android.content.ClipData.Item); method public int describeContents(); method public android.content.ClipDescription getDescription(); method public android.content.ClipData.Item getItemAt(int); @@ -9894,6 +9881,7 @@ package android.content { field public static final java.lang.String ACTION_FACTORY_TEST = "android.intent.action.FACTORY_TEST"; field public static final java.lang.String ACTION_GET_CONTENT = "android.intent.action.GET_CONTENT"; field public static final java.lang.String ACTION_GET_RESTRICTION_ENTRIES = "android.intent.action.GET_RESTRICTION_ENTRIES"; + field public static final java.lang.String ACTION_GLOBAL_BUTTON = "android.intent.action.GLOBAL_BUTTON"; field public static final java.lang.String ACTION_GTALK_SERVICE_CONNECTED = "android.intent.action.GTALK_CONNECTED"; field public static final java.lang.String ACTION_GTALK_SERVICE_DISCONNECTED = "android.intent.action.GTALK_DISCONNECTED"; field public static final java.lang.String ACTION_HEADSET_PLUG = "android.intent.action.HEADSET_PLUG"; @@ -10060,6 +10048,7 @@ package android.content { field public static final java.lang.String EXTRA_CHOOSER_TARGETS = "android.intent.extra.CHOOSER_TARGETS"; field public static final java.lang.String EXTRA_CHOSEN_COMPONENT = "android.intent.extra.CHOSEN_COMPONENT"; field public static final java.lang.String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER = "android.intent.extra.CHOSEN_COMPONENT_INTENT_SENDER"; + field public static final java.lang.String EXTRA_COMPONENT_NAME = "android.intent.extra.COMPONENT_NAME"; field public static final java.lang.String EXTRA_CONTENT_ANNOTATIONS = "android.intent.extra.CONTENT_ANNOTATIONS"; field public static final deprecated java.lang.String EXTRA_CSS_INDICATOR = "cssIndicator"; field public static final deprecated java.lang.String EXTRA_DATA_OPERATOR_ALPHA_LONG = "data-operator-alpha-long"; @@ -10994,7 +10983,7 @@ package android.content.pm { field public java.lang.String[] splitPublicSourceDirs; field public java.lang.String[] splitSourceDirs; field public java.lang.String targetPackage; - field public java.lang.String targetProcess; + field public java.lang.String targetProcesses; } public final class IntentFilterVerificationInfo implements android.os.Parcelable { @@ -14554,6 +14543,7 @@ package android.graphics { method public void detachFromGLContext(); method public long getTimestamp(); method public void getTransformMatrix(float[]); + method public boolean isReleased(); method public void release(); method public void releaseTexImage(); method public void setDefaultBufferSize(int, int); @@ -15286,7 +15276,7 @@ package android.hardware { method public final void takePicture(android.hardware.Camera.ShutterCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback); method public final void unlock(); field public static final java.lang.String ACTION_NEW_PICTURE = "android.hardware.action.NEW_PICTURE"; - field public static final deprecated java.lang.String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO"; + field public static final java.lang.String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO"; field public static final int CAMERA_ERROR_EVICTED = 2; // 0x2 field public static final int CAMERA_ERROR_SERVER_DIED = 100; // 0x64 field public static final int CAMERA_ERROR_UNKNOWN = 1; // 0x1 @@ -15547,18 +15537,16 @@ package android.hardware { field public static final int RGBX_8888 = 2; // 0x2 field public static final int RGB_565 = 4; // 0x4 field public static final int RGB_888 = 3; // 0x3 - field public static final long USAGE0_CPU_READ = 2L; // 0x2L - field public static final long USAGE0_CPU_READ_OFTEN = 6L; // 0x6L - field public static final long USAGE0_CPU_WRITE = 32L; // 0x20L - field public static final long USAGE0_CPU_WRITE_OFTEN = 96L; // 0x60L - field public static final long USAGE0_GPU_COLOR_OUTPUT = 2048L; // 0x800L - field public static final long USAGE0_GPU_CUBEMAP = 8192L; // 0x2000L - field public static final long USAGE0_GPU_DATA_BUFFER = 16384L; // 0x4000L - field public static final long USAGE0_GPU_SAMPLED_IMAGE = 1024L; // 0x400L - field public static final long USAGE0_GPU_STORAGE_IMAGE = 3072L; // 0xc00L - field public static final long USAGE0_PROTECTED_CONTENT = 262144L; // 0x40000L - field public static final long USAGE0_SENSOR_DIRECT_DATA = 536870912L; // 0x20000000L - field public static final long USAGE0_VIDEO_ENCODE = 2097152L; // 0x200000L + field public static final long USAGE_CPU_READ_OFTEN = 3L; // 0x3L + field public static final long USAGE_CPU_READ_RARELY = 2L; // 0x2L + field public static final long USAGE_CPU_WRITE_OFTEN = 48L; // 0x30L + field public static final long USAGE_CPU_WRITE_RARELY = 32L; // 0x20L + field public static final long USAGE_GPU_COLOR_OUTPUT = 512L; // 0x200L + field public static final long USAGE_GPU_DATA_BUFFER = 16777216L; // 0x1000000L + field public static final long USAGE_GPU_SAMPLED_IMAGE = 256L; // 0x100L + field public static final long USAGE_PROTECTED_CONTENT = 16384L; // 0x4000L + field public static final long USAGE_SENSOR_DIRECT_DATA = 8388608L; // 0x800000L + field public static final long USAGE_VIDEO_ENCODE = 65536L; // 0x10000L } public final class Sensor { @@ -27287,6 +27275,7 @@ package android.metrics { method public java.lang.Object getTaggedData(int); method public long getTimestamp(); method public int getType(); + method public int getUid(); method public boolean isLongCounterBucket(); method public boolean isSubsetOf(android.metrics.LogMaker); method public boolean isValidValue(java.lang.Object); @@ -27593,8 +27582,8 @@ package android.net { method public boolean requestBandwidthUpdate(android.net.Network); method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback); method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler); - method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback); - method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback, android.os.Handler); + method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, int); + method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler, int); method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent); method public deprecated void setNetworkPreference(int); method public static deprecated boolean setProcessDefaultNetwork(android.net.Network); @@ -33453,7 +33442,6 @@ package android.os { method public android.util.SizeF getSizeF(java.lang.String); method public <T extends android.os.Parcelable> android.util.SparseArray<T> getSparseParcelableArray(java.lang.String); method public java.util.ArrayList<java.lang.String> getStringArrayList(java.lang.String); - method public java.util.UUID getUuid(java.lang.String); method public boolean hasFileDescriptors(); method public void putAll(android.os.Bundle); method public void putBinder(java.lang.String, android.os.IBinder); @@ -33478,7 +33466,6 @@ package android.os { method public void putSizeF(java.lang.String, android.util.SizeF); method public void putSparseParcelableArray(java.lang.String, android.util.SparseArray<? extends android.os.Parcelable>); method public void putStringArrayList(java.lang.String, java.util.ArrayList<java.lang.String>); - method public void putUuid(java.lang.String, java.util.UUID); method public void readFromParcel(android.os.Parcel); method public void setClassLoader(java.lang.ClassLoader); method public void writeToParcel(android.os.Parcel, int); @@ -34040,7 +34027,6 @@ package android.os { method public final <T> void readTypedArray(T[], android.os.Parcelable.Creator<T>); method public final <T> void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>); method public final <T> T readTypedObject(android.os.Parcelable.Creator<T>); - method public final java.util.UUID readUuid(); method public final java.lang.Object readValue(java.lang.ClassLoader); method public final void recycle(); method public final void setDataCapacity(int); @@ -34086,7 +34072,6 @@ package android.os { method public final <T extends android.os.Parcelable> void writeTypedArray(T[], int); method public final <T extends android.os.Parcelable> void writeTypedList(java.util.List<T>); method public final <T extends android.os.Parcelable> void writeTypedObject(T, int); - method public final void writeUuid(java.util.UUID); method public final void writeValue(java.lang.Object); field public static final android.os.Parcelable.Creator<java.lang.String> STRING_CREATOR; } @@ -34579,6 +34564,7 @@ package android.os { field public static final java.lang.String DISALLOW_APPS_CONTROL = "no_control_apps"; field public static final java.lang.String DISALLOW_AUTOFILL = "no_autofill"; field public static final java.lang.String DISALLOW_BLUETOOTH = "no_bluetooth"; + field public static final java.lang.String DISALLOW_BLUETOOTH_SHARING = "no_bluetooth_sharing"; field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth"; field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts"; field public static final java.lang.String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials"; @@ -34823,8 +34809,11 @@ package android.os.storage { } public class StorageManager { + method public void allocateBytes(java.util.UUID, long) throws java.io.IOException; method public void allocateBytes(java.util.UUID, long, int) throws java.io.IOException; + method public void allocateBytes(java.io.FileDescriptor, long) throws java.io.IOException; method public void allocateBytes(java.io.FileDescriptor, long, int) throws java.io.IOException; + method public long getAllocatableBytes(java.util.UUID) throws java.io.IOException; method public long getAllocatableBytes(java.util.UUID, int) throws java.io.IOException; method public long getCacheQuotaBytes(java.util.UUID) throws java.io.IOException; method public long getCacheSizeBytes(java.util.UUID) throws java.io.IOException; @@ -34838,7 +34827,6 @@ package android.os.storage { method public boolean isEncrypted(java.io.File); method public boolean isObbMounted(java.lang.String); method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener); - method public android.os.ParcelFileDescriptor openProxyFileDescriptor(int, android.os.ProxyFileDescriptorCallback) throws java.io.IOException; method public android.os.ParcelFileDescriptor openProxyFileDescriptor(int, android.os.ProxyFileDescriptorCallback, android.os.Handler) throws java.io.IOException; method public void setCacheBehaviorGroup(java.io.File, boolean) throws java.io.IOException; method public void setCacheBehaviorTombstone(java.io.File, boolean) throws java.io.IOException; @@ -37429,7 +37417,6 @@ package android.provider { } public class FontsContract { - method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[], int, boolean, java.lang.String); method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[]); method public static android.provider.FontsContract.FontFamilyResult fetchFonts(android.content.Context, android.os.CancellationSignal, android.provider.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException; method public static void requestFonts(android.content.Context, android.provider.FontRequest, android.os.Handler, android.os.CancellationSignal, android.provider.FontsContract.FontRequestCallback); @@ -40696,7 +40683,6 @@ package android.service.quicksettings { method public final void unlockAndRun(java.lang.Runnable); field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE"; field public static final java.lang.String ACTION_QS_TILE_PREFERENCES = "android.service.quicksettings.action.QS_TILE_PREFERENCES"; - field public static final java.lang.String EXTRA_COMPONENT = "android.service.quicksettings.extra.COMPONENT"; field public static final java.lang.String META_DATA_ACTIVE_TILE = "android.service.quicksettings.ACTIVE_TILE"; } @@ -40989,12 +40975,10 @@ package android.service.wallpaper { method public int getDesiredMinimumHeight(); method public int getDesiredMinimumWidth(); method public android.view.SurfaceHolder getSurfaceHolder(); - method public void invalidateColors(); method public boolean isPreview(); method public boolean isVisible(); method public void onApplyWindowInsets(android.view.WindowInsets); method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean); - method public android.app.WallpaperColors onComputeWallpaperColors(); method public void onCreate(android.view.SurfaceHolder); method public void onDesiredSizeChanged(int, int); method public void onDestroy(); @@ -46761,6 +46745,7 @@ package android.util { method public int getTag(); method public int getThreadId(); method public long getTimeNanos(); + method public int getUid(); } public deprecated class EventLogTags { @@ -49413,6 +49398,7 @@ package android.view { 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_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 1; // 0x1 field public static final java.lang.String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE = "creditCardExpirationDate"; field public static final java.lang.String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay"; field public static final java.lang.String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = "creditCardExpirationMonth"; @@ -50124,7 +50110,7 @@ package android.view { public static abstract class ViewStructure.HtmlInfo { ctor public ViewStructure.HtmlInfo(); - method public abstract java.util.ArrayList<android.util.Pair<java.lang.String, java.lang.String>> getAttributes(); + method public abstract java.util.List<android.util.Pair<java.lang.String, java.lang.String>> getAttributes(); method public abstract java.lang.String getTag(); } @@ -51383,7 +51369,7 @@ package android.view.autofill { method public void unregisterCallback(android.view.autofill.AutofillManager.AutofillCallback); 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"; - field public static final java.lang.String EXTRA_DATA_EXTRAS = "android.view.autofill.extra.DATA_EXTRAS"; + field public static final java.lang.String EXTRA_CLIENT_STATE = "android.view.autofill.extra.EXTRA_CLIENT_STATE"; } public static abstract class AutofillManager.AutofillCallback { @@ -52617,7 +52603,6 @@ package android.webkit { method public int getRendererRequestedPriority(); method public deprecated float getScale(); method public android.webkit.WebSettings getSettings(); - method public android.view.textclassifier.TextClassifier getTextClassifier(); method public java.lang.String getTitle(); method public java.lang.String getUrl(); method public android.webkit.WebChromeClient getWebChromeClient(); @@ -52635,7 +52620,6 @@ package android.webkit { method public deprecated void onChildViewAdded(android.view.View, android.view.View); method public deprecated void onChildViewRemoved(android.view.View, android.view.View); method public deprecated void onGlobalFocusChanged(android.view.View, android.view.View); - method public void onMovedToDisplay(int, android.content.res.Configuration); method public void onPause(); method public void onResume(); method public deprecated boolean overlayHorizontalScrollbar(); @@ -52666,7 +52650,6 @@ package android.webkit { method public void setNetworkAvailable(boolean); method public deprecated void setPictureListener(android.webkit.WebView.PictureListener); method public void setRendererPriorityPolicy(int, boolean); - method public void setTextClassifier(android.view.textclassifier.TextClassifier); method public deprecated void setVerticalScrollbarOverlay(boolean); method public void setWebChromeClient(android.webkit.WebChromeClient); method public static void setWebContentsDebuggingEnabled(boolean); diff --git a/api/system-removed.txt b/api/system-removed.txt index 2ef8690e4362..659236df31c6 100644 --- a/api/system-removed.txt +++ b/api/system-removed.txt @@ -16,12 +16,17 @@ package android.app.admin { method public deprecated android.os.UserHandle createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle); method public deprecated android.os.UserHandle createUser(android.content.ComponentName, java.lang.String); method public void setAffiliationIds(android.content.ComponentName, java.util.List<java.lang.String>); + field public static final deprecated int FLAG_EVICT_CE_KEY = 1; // 0x1 } } package android.app.usage { + public final class StorageStats implements android.os.Parcelable { + method public deprecated long getCodeBytes(); + } + public class StorageStatsManager { method public deprecated long getFreeBytes(java.lang.String) throws java.io.IOException; method public deprecated long getTotalBytes(java.lang.String) throws java.io.IOException; @@ -36,6 +41,10 @@ package android.app.usage { package android.content { + public class ClipData implements android.os.Parcelable { + method public deprecated void addItem(android.content.ClipData.Item, android.content.ContentResolver); + } + public abstract class Context { method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int); method public abstract java.io.File getSharedPreferencesPath(java.lang.String); diff --git a/api/test-current.txt b/api/test-current.txt index 15f91ba72715..6d6abeccd362 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -15,7 +15,6 @@ package android { field public static final java.lang.String ACCESS_WIFI_STATE = "android.permission.ACCESS_WIFI_STATE"; field public static final java.lang.String ACCOUNT_MANAGER = "android.permission.ACCOUNT_MANAGER"; field public static final java.lang.String ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL"; - field public static final java.lang.String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE"; field public static final java.lang.String ANSWER_PHONE_CALLS = "android.permission.ANSWER_PHONE_CALLS"; 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"; @@ -1297,7 +1296,7 @@ package android { field public static final int targetId = 16843740; // 0x10103dc field public static final int targetName = 16843853; // 0x101044d field public static final int targetPackage = 16842785; // 0x1010021 - field public static final int targetProcess = 16844097; // 0x1010541 + field public static final int targetProcesses = 16844097; // 0x1010541 field public static final int targetSandboxVersion = 16844110; // 0x101054e field public static final int targetSdkVersion = 16843376; // 0x1010270 field public static final int taskAffinity = 16842770; // 0x1010012 @@ -2877,7 +2876,8 @@ package android.accessibilityservice { public static abstract class FingerprintGestureController.FingerprintGestureCallback { ctor public FingerprintGestureController.FingerprintGestureCallback(); - method public void onGesture(int); + method public deprecated void onGesture(int); + method public void onGestureDetected(int); method public void onGestureDetectionAvailabilityChanged(boolean); } @@ -3035,8 +3035,8 @@ package android.accounts { field public static final java.lang.String KEY_PASSWORD = "password"; field public static final java.lang.String KEY_USERDATA = "userdata"; field public static final deprecated java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED"; - field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE = "android.accounts.key_legacy_not_visible"; - field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_VISIBLE = "android.accounts.key_legacy_visible"; + field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE = "android:accounts:key_legacy_not_visible"; + field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_VISIBLE = "android:accounts:key_legacy_visible"; field public static final int VISIBILITY_NOT_VISIBLE = 3; // 0x3 field public static final int VISIBILITY_UNDEFINED = 0; // 0x0 field public static final int VISIBILITY_USER_MANAGED_NOT_VISIBLE = 4; // 0x4 @@ -3953,7 +3953,7 @@ package android.app { field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d field public static final int IMPORTANCE_GONE = 1000; // 0x3e8 field public static final int IMPORTANCE_PERCEPTIBLE = 230; // 0xe6 - field public static final deprecated int IMPORTANCE_PERCEPTIBLE_DEPRECATED = 130; // 0x82 + field public static final int IMPORTANCE_PERCEPTIBLE_PRE_26 = 130; // 0x82 field public static final int IMPORTANCE_SERVICE = 300; // 0x12c field public static final int IMPORTANCE_TOP_SLEEPING = 150; // 0x96 field public static final int IMPORTANCE_VISIBLE = 200; // 0xc8 @@ -4040,6 +4040,7 @@ package android.app { method public static android.app.ActivityOptions makeTaskLaunchBehind(); method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int); method public void requestUsageTimeReport(android.app.PendingIntent); + method public android.app.ActivityOptions setAppVerificationBundle(android.os.Bundle); method public android.app.ActivityOptions setLaunchBounds(android.graphics.Rect); method public android.app.ActivityOptions setLaunchDisplayId(int); method public void setLaunchStackId(int); @@ -4830,6 +4831,7 @@ package android.app { method public void onFragmentDetached(android.app.FragmentManager, android.app.Fragment); method public void onFragmentPaused(android.app.FragmentManager, android.app.Fragment); method public void onFragmentPreAttached(android.app.FragmentManager, android.app.Fragment, android.content.Context); + method public void onFragmentPreCreated(android.app.FragmentManager, android.app.Fragment, android.os.Bundle); method public void onFragmentResumed(android.app.FragmentManager, android.app.Fragment); method public void onFragmentSaveInstanceState(android.app.FragmentManager, android.app.Fragment, android.os.Bundle); method public void onFragmentStarted(android.app.FragmentManager, android.app.Fragment); @@ -4862,10 +4864,10 @@ package android.app { method public abstract android.app.FragmentTransaction hide(android.app.Fragment); method public abstract boolean isAddToBackStackAllowed(); method public abstract boolean isEmpty(); - method public abstract android.app.FragmentTransaction postOnCommit(java.lang.Runnable); method public abstract android.app.FragmentTransaction remove(android.app.Fragment); method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment); method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment, java.lang.String); + method public abstract android.app.FragmentTransaction runOnCommit(java.lang.Runnable); method public abstract android.app.FragmentTransaction setBreadCrumbShortTitle(int); method public abstract android.app.FragmentTransaction setBreadCrumbShortTitle(java.lang.CharSequence); method public abstract android.app.FragmentTransaction setBreadCrumbTitle(int); @@ -4967,7 +4969,7 @@ package android.app { method public final android.app.Activity getLastActivity(); method public final android.app.Instrumentation.ActivityResult getResult(); method public final boolean isBlocking(); - method public android.app.Instrumentation.ActivityResult onMatchIntent(android.content.Intent); + method public android.app.Instrumentation.ActivityResult onStartActivity(android.content.Intent); method public final android.app.Activity waitForActivity(); method public final android.app.Activity waitForActivityWithTimeout(long); } @@ -4987,7 +4989,7 @@ package android.app { public class KeyguardManager { method public android.content.Intent createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence); - method public void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler); + method public deprecated void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler); method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult); method public boolean inKeyguardRestrictedInputMode(); method public boolean isDeviceLocked(); @@ -4995,6 +4997,7 @@ package android.app { method public boolean isKeyguardLocked(); method public boolean isKeyguardSecure(); method public deprecated android.app.KeyguardManager.KeyguardLock newKeyguardLock(java.lang.String); + method public void requestDismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback); } public static abstract class KeyguardManager.KeyguardDismissCallback { @@ -6132,17 +6135,6 @@ package android.app { method public void onDetached(); } - public final class WallpaperColors implements android.os.Parcelable { - ctor public WallpaperColors(android.os.Parcel); - ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>); - ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>, boolean); - method public int describeContents(); - method public java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>> getColors(); - method public boolean supportsDarkText(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR; - } - public final class WallpaperInfo implements android.os.Parcelable { ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public int describeContents(); @@ -6165,8 +6157,6 @@ package android.app { } public class WallpaperManager { - method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener); - method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler); method public void clear() throws java.io.IOException; method public void clear(int) throws java.io.IOException; method public void clearWallpaperOffsets(android.os.IBinder); @@ -6181,7 +6171,6 @@ package android.app { method public android.graphics.drawable.Drawable getDrawable(); method public android.graphics.drawable.Drawable getFastDrawable(); method public static android.app.WallpaperManager getInstance(android.content.Context); - method public android.app.WallpaperColors getWallpaperColors(int); method public android.os.ParcelFileDescriptor getWallpaperFile(int); method public int getWallpaperId(int); method public android.app.WallpaperInfo getWallpaperInfo(); @@ -6190,7 +6179,6 @@ package android.app { method public boolean isWallpaperSupported(); method public android.graphics.drawable.Drawable peekDrawable(); method public android.graphics.drawable.Drawable peekFastDrawable(); - method public void removeOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener); method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle); method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException; method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException; @@ -6215,16 +6203,12 @@ package android.app { field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview"; } - public static abstract interface WallpaperManager.OnColorsChangedListener { - method public abstract void onColorsChanged(android.app.WallpaperColors, int); - } - } package android.app.admin { public final class ConnectEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable { - method public java.lang.String getIpAddress(); + method public java.net.InetAddress getInetAddress(); method public int getPort(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.admin.ConnectEvent> CREATOR; @@ -6539,7 +6523,7 @@ package android.app.admin { field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE = "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE"; field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SSID = "android.app.extra.PROVISIONING_WIFI_SSID"; field public static final java.lang.String EXTRA_RESTRICTION = "android.app.extra.RESTRICTION"; - field public static final int FLAG_EVICT_CE_KEY = 1; // 0x1 + field public static final int FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY = 1; // 0x1 field public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 2; // 0x2 field public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 1; // 0x1 field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff @@ -6577,8 +6561,8 @@ package android.app.admin { public final class DnsEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable { method public java.lang.String getHostname(); - method public java.lang.String[] getIpAddresses(); - method public int getIpAddressesCount(); + method public java.util.List<java.net.InetAddress> getInetAddresses(); + method public int getTotalResolvedAddressCount(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.admin.DnsEvent> CREATOR; } @@ -7038,8 +7022,8 @@ package android.app.usage { public final class StorageStats implements android.os.Parcelable { method public int describeContents(); + method public long getAppBytes(); method public long getCacheBytes(); - method public long getCodeBytes(); method public long getDataBytes(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.usage.StorageStats> CREATOR; @@ -8248,8 +8232,10 @@ package android.bluetooth.le { field public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanResult> CREATOR; field public static final int DATA_COMPLETE = 0; // 0x0 field public static final int DATA_TRUNCATED = 2; // 0x2 + field public static final int PERIODIC_INTERVAL_NOT_PRESENT = 0; // 0x0 field public static final int PHY_UNUSED = 0; // 0x0 field public static final int SID_NOT_PRESENT = 255; // 0xff + field public static final int TX_POWER_NOT_PRESENT = 127; // 0x7f } public final class ScanSettings implements android.os.Parcelable { @@ -8320,21 +8306,21 @@ package android.companion { method public android.companion.BluetoothDeviceFilter.Builder setNamePattern(java.util.regex.Pattern); } - public final class BluetoothLEDeviceFilter implements android.companion.DeviceFilter { + 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; + field public static final android.os.Parcelable.Creator<android.companion.BluetoothLeDeviceFilter> CREATOR; } - public static final class BluetoothLEDeviceFilter.Builder { - 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 setRenameFromBytes(java.lang.String, java.lang.String, int, int, boolean); - method public android.companion.BluetoothLEDeviceFilter.Builder setRenameFromName(java.lang.String, java.lang.String, int, int); - method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter); + public static final class BluetoothLeDeviceFilter.Builder { + 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 setRenameFromBytes(java.lang.String, java.lang.String, int, int, boolean); + method public android.companion.BluetoothLeDeviceFilter.Builder setRenameFromName(java.lang.String, java.lang.String, int, int); + method public android.companion.BluetoothLeDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter); } public final class CompanionDeviceManager { @@ -8470,7 +8456,7 @@ package android.content { ctor public ClipData(android.content.ClipDescription, android.content.ClipData.Item); ctor public ClipData(android.content.ClipData); method public void addItem(android.content.ClipData.Item); - method public void addItem(android.content.ClipData.Item, android.content.ContentResolver); + method public void addItem(android.content.ContentResolver, android.content.ClipData.Item); method public int describeContents(); method public android.content.ClipDescription getDescription(); method public android.content.ClipData.Item getItemAt(int); @@ -9545,6 +9531,7 @@ package android.content { field public static final java.lang.String EXTRA_CHOOSER_TARGETS = "android.intent.extra.CHOOSER_TARGETS"; field public static final java.lang.String EXTRA_CHOSEN_COMPONENT = "android.intent.extra.CHOSEN_COMPONENT"; field public static final java.lang.String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER = "android.intent.extra.CHOSEN_COMPONENT_INTENT_SENDER"; + field public static final java.lang.String EXTRA_COMPONENT_NAME = "android.intent.extra.COMPONENT_NAME"; field public static final java.lang.String EXTRA_CONTENT_ANNOTATIONS = "android.intent.extra.CONTENT_ANNOTATIONS"; field public static final java.lang.String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED"; field public static final java.lang.String EXTRA_DOCK_STATE = "android.intent.extra.DOCK_STATE"; @@ -10370,7 +10357,7 @@ package android.content.pm { field public java.lang.String[] splitPublicSourceDirs; field public java.lang.String[] splitSourceDirs; field public java.lang.String targetPackage; - field public java.lang.String targetProcess; + field public java.lang.String targetProcesses; } public class LabeledIntent extends android.content.Intent { @@ -13818,6 +13805,7 @@ package android.graphics { method public void detachFromGLContext(); method public long getTimestamp(); method public void getTransformMatrix(float[]); + method public boolean isReleased(); method public void release(); method public void releaseTexImage(); method public void setDefaultBufferSize(int, int); @@ -14554,7 +14542,7 @@ package android.hardware { method public final void takePicture(android.hardware.Camera.ShutterCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback); method public final void unlock(); field public static final java.lang.String ACTION_NEW_PICTURE = "android.hardware.action.NEW_PICTURE"; - field public static final deprecated java.lang.String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO"; + field public static final java.lang.String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO"; field public static final int CAMERA_ERROR_EVICTED = 2; // 0x2 field public static final int CAMERA_ERROR_SERVER_DIED = 100; // 0x64 field public static final int CAMERA_ERROR_UNKNOWN = 1; // 0x1 @@ -14815,18 +14803,16 @@ package android.hardware { field public static final int RGBX_8888 = 2; // 0x2 field public static final int RGB_565 = 4; // 0x4 field public static final int RGB_888 = 3; // 0x3 - field public static final long USAGE0_CPU_READ = 2L; // 0x2L - field public static final long USAGE0_CPU_READ_OFTEN = 6L; // 0x6L - field public static final long USAGE0_CPU_WRITE = 32L; // 0x20L - field public static final long USAGE0_CPU_WRITE_OFTEN = 96L; // 0x60L - field public static final long USAGE0_GPU_COLOR_OUTPUT = 2048L; // 0x800L - field public static final long USAGE0_GPU_CUBEMAP = 8192L; // 0x2000L - field public static final long USAGE0_GPU_DATA_BUFFER = 16384L; // 0x4000L - field public static final long USAGE0_GPU_SAMPLED_IMAGE = 1024L; // 0x400L - field public static final long USAGE0_GPU_STORAGE_IMAGE = 3072L; // 0xc00L - field public static final long USAGE0_PROTECTED_CONTENT = 262144L; // 0x40000L - field public static final long USAGE0_SENSOR_DIRECT_DATA = 536870912L; // 0x20000000L - field public static final long USAGE0_VIDEO_ENCODE = 2097152L; // 0x200000L + field public static final long USAGE_CPU_READ_OFTEN = 3L; // 0x3L + field public static final long USAGE_CPU_READ_RARELY = 2L; // 0x2L + field public static final long USAGE_CPU_WRITE_OFTEN = 48L; // 0x30L + field public static final long USAGE_CPU_WRITE_RARELY = 32L; // 0x20L + field public static final long USAGE_GPU_COLOR_OUTPUT = 512L; // 0x200L + field public static final long USAGE_GPU_DATA_BUFFER = 16777216L; // 0x1000000L + field public static final long USAGE_GPU_SAMPLED_IMAGE = 256L; // 0x100L + field public static final long USAGE_PROTECTED_CONTENT = 16384L; // 0x4000L + field public static final long USAGE_SENSOR_DIRECT_DATA = 8388608L; // 0x800000L + field public static final long USAGE_VIDEO_ENCODE = 65536L; // 0x10000L } public final class Sensor { @@ -25520,8 +25506,8 @@ package android.net { method public boolean requestBandwidthUpdate(android.net.Network); method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback); method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler); - method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback); - method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback, android.os.Handler); + method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, int); + method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler, int); method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent); method public deprecated void setNetworkPreference(int); method public static deprecated boolean setProcessDefaultNetwork(android.net.Network); @@ -30800,7 +30786,6 @@ package android.os { method public android.util.SizeF getSizeF(java.lang.String); method public <T extends android.os.Parcelable> android.util.SparseArray<T> getSparseParcelableArray(java.lang.String); method public java.util.ArrayList<java.lang.String> getStringArrayList(java.lang.String); - method public java.util.UUID getUuid(java.lang.String); method public boolean hasFileDescriptors(); method public void putAll(android.os.Bundle); method public void putBinder(java.lang.String, android.os.IBinder); @@ -30825,7 +30810,6 @@ package android.os { method public void putSizeF(java.lang.String, android.util.SizeF); method public void putSparseParcelableArray(java.lang.String, android.util.SparseArray<? extends android.os.Parcelable>); method public void putStringArrayList(java.lang.String, java.util.ArrayList<java.lang.String>); - method public void putUuid(java.lang.String, java.util.UUID); method public void readFromParcel(android.os.Parcel); method public void setClassLoader(java.lang.ClassLoader); method public void writeToParcel(android.os.Parcel, int); @@ -31376,7 +31360,6 @@ package android.os { method public final <T> void readTypedArray(T[], android.os.Parcelable.Creator<T>); method public final <T> void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>); method public final <T> T readTypedObject(android.os.Parcelable.Creator<T>); - method public final java.util.UUID readUuid(); method public final java.lang.Object readValue(java.lang.ClassLoader); method public final void recycle(); method public final void setDataCapacity(int); @@ -31422,7 +31405,6 @@ package android.os { method public final <T extends android.os.Parcelable> void writeTypedArray(T[], int); method public final <T extends android.os.Parcelable> void writeTypedList(java.util.List<T>); method public final <T extends android.os.Parcelable> void writeTypedObject(T, int); - method public final void writeUuid(java.util.UUID); method public final void writeValue(java.lang.Object); field public static final android.os.Parcelable.Creator<java.lang.String> STRING_CREATOR; } @@ -31829,6 +31811,7 @@ package android.os { field public static final java.lang.String DISALLOW_APPS_CONTROL = "no_control_apps"; field public static final java.lang.String DISALLOW_AUTOFILL = "no_autofill"; field public static final java.lang.String DISALLOW_BLUETOOTH = "no_bluetooth"; + field public static final java.lang.String DISALLOW_BLUETOOTH_SHARING = "no_bluetooth_sharing"; field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth"; field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts"; field public static final java.lang.String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials"; @@ -32057,9 +32040,9 @@ package android.os.storage { } public class StorageManager { - method public void allocateBytes(java.util.UUID, long, int) throws java.io.IOException; - method public void allocateBytes(java.io.FileDescriptor, long, int) throws java.io.IOException; - method public long getAllocatableBytes(java.util.UUID, int) throws java.io.IOException; + method public void allocateBytes(java.util.UUID, long) throws java.io.IOException; + method public void allocateBytes(java.io.FileDescriptor, long) throws java.io.IOException; + method public long getAllocatableBytes(java.util.UUID) throws java.io.IOException; method public long getCacheQuotaBytes(java.util.UUID) throws java.io.IOException; method public long getCacheSizeBytes(java.util.UUID) throws java.io.IOException; method public java.lang.String getMountedObbPath(java.lang.String); @@ -32072,7 +32055,6 @@ package android.os.storage { method public boolean isEncrypted(java.io.File); method public boolean isObbMounted(java.lang.String); method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener); - method public android.os.ParcelFileDescriptor openProxyFileDescriptor(int, android.os.ProxyFileDescriptorCallback) throws java.io.IOException; method public android.os.ParcelFileDescriptor openProxyFileDescriptor(int, android.os.ProxyFileDescriptorCallback, android.os.Handler) throws java.io.IOException; method public void setCacheBehaviorGroup(java.io.File, boolean) throws java.io.IOException; method public void setCacheBehaviorTombstone(java.io.File, boolean) throws java.io.IOException; @@ -32080,7 +32062,6 @@ package android.os.storage { field public static final java.lang.String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE"; field public static final java.lang.String EXTRA_REQUESTED_BYTES = "android.os.storage.extra.REQUESTED_BYTES"; field public static final java.lang.String EXTRA_UUID = "android.os.storage.extra.UUID"; - field public static final int FLAG_ALLOCATE_AGGRESSIVE = 1; // 0x1 field public static final java.util.UUID UUID_DEFAULT; } @@ -34574,7 +34555,6 @@ package android.provider { } public class FontsContract { - method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[], int, boolean, java.lang.String); method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[]); method public static android.provider.FontsContract.FontFamilyResult fetchFonts(android.content.Context, android.os.CancellationSignal, android.provider.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException; method public static void requestFonts(android.content.Context, android.provider.FontRequest, android.os.Handler, android.os.CancellationSignal, android.provider.FontsContract.FontRequestCallback); @@ -37695,7 +37675,6 @@ package android.service.quicksettings { method public final void unlockAndRun(java.lang.Runnable); field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE"; field public static final java.lang.String ACTION_QS_TILE_PREFERENCES = "android.service.quicksettings.action.QS_TILE_PREFERENCES"; - field public static final java.lang.String EXTRA_COMPONENT = "android.service.quicksettings.extra.COMPONENT"; field public static final java.lang.String META_DATA_ACTIVE_TILE = "android.service.quicksettings.ACTIVE_TILE"; } @@ -37925,12 +37904,10 @@ package android.service.wallpaper { method public int getDesiredMinimumHeight(); method public int getDesiredMinimumWidth(); method public android.view.SurfaceHolder getSurfaceHolder(); - method public void invalidateColors(); method public boolean isPreview(); method public boolean isVisible(); method public void onApplyWindowInsets(android.view.WindowInsets); method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean); - method public android.app.WallpaperColors onComputeWallpaperColors(); method public void onCreate(android.view.SurfaceHolder); method public void onDesiredSizeChanged(int, int); method public void onDestroy(); @@ -46199,6 +46176,7 @@ package android.view { 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_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 1; // 0x1 field public static final java.lang.String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE = "creditCardExpirationDate"; field public static final java.lang.String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay"; field public static final java.lang.String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = "creditCardExpirationMonth"; @@ -46914,7 +46892,7 @@ package android.view { public static abstract class ViewStructure.HtmlInfo { ctor public ViewStructure.HtmlInfo(); - method public abstract java.util.ArrayList<android.util.Pair<java.lang.String, java.lang.String>> getAttributes(); + method public abstract java.util.List<android.util.Pair<java.lang.String, java.lang.String>> getAttributes(); method public abstract java.lang.String getTag(); } @@ -48174,7 +48152,7 @@ package android.view.autofill { method public void unregisterCallback(android.view.autofill.AutofillManager.AutofillCallback); 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"; - field public static final java.lang.String EXTRA_DATA_EXTRAS = "android.view.autofill.extra.DATA_EXTRAS"; + field public static final java.lang.String EXTRA_CLIENT_STATE = "android.view.autofill.extra.EXTRA_CLIENT_STATE"; } public static abstract class AutofillManager.AutofillCallback { @@ -49315,7 +49293,6 @@ package android.webkit { method public int getRendererRequestedPriority(); method public deprecated float getScale(); method public android.webkit.WebSettings getSettings(); - method public android.view.textclassifier.TextClassifier getTextClassifier(); method public java.lang.String getTitle(); method public java.lang.String getUrl(); method public android.webkit.WebChromeClient getWebChromeClient(); @@ -49332,7 +49309,6 @@ package android.webkit { method public deprecated void onChildViewAdded(android.view.View, android.view.View); method public deprecated void onChildViewRemoved(android.view.View, android.view.View); method public deprecated void onGlobalFocusChanged(android.view.View, android.view.View); - method public void onMovedToDisplay(int, android.content.res.Configuration); method public void onPause(); method public void onResume(); method public deprecated boolean overlayHorizontalScrollbar(); @@ -49363,7 +49339,6 @@ package android.webkit { method public void setNetworkAvailable(boolean); method public deprecated void setPictureListener(android.webkit.WebView.PictureListener); method public void setRendererPriorityPolicy(int, boolean); - method public void setTextClassifier(android.view.textclassifier.TextClassifier); method public deprecated void setVerticalScrollbarOverlay(boolean); method public void setWebChromeClient(android.webkit.WebChromeClient); method public static void setWebContentsDebuggingEnabled(boolean); diff --git a/api/test-removed.txt b/api/test-removed.txt index 13bccd6b42ed..8c81ef42371e 100644 --- a/api/test-removed.txt +++ b/api/test-removed.txt @@ -18,12 +18,17 @@ package android.app.admin { method public deprecated java.lang.String getDeviceInitializerApp(); method public deprecated android.content.ComponentName getDeviceInitializerComponent(); method public void setAffiliationIds(android.content.ComponentName, java.util.List<java.lang.String>); + field public static final deprecated int FLAG_EVICT_CE_KEY = 1; // 0x1 } } package android.app.usage { + public final class StorageStats implements android.os.Parcelable { + method public deprecated long getCodeBytes(); + } + public class StorageStatsManager { method public deprecated long getFreeBytes(java.lang.String) throws java.io.IOException; method public deprecated long getTotalBytes(java.lang.String) throws java.io.IOException; @@ -38,6 +43,10 @@ package android.app.usage { package android.content { + public class ClipData implements android.os.Parcelable { + method public deprecated void addItem(android.content.ClipData.Item, android.content.ContentResolver); + } + public abstract class Context { method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int); method public abstract java.io.File getSharedPreferencesPath(java.lang.String); diff --git a/core/java/android/accessibilityservice/AccessibilityButtonController.java b/core/java/android/accessibilityservice/AccessibilityButtonController.java index c3a5daba4cfc..ee1976889299 100644 --- a/core/java/android/accessibilityservice/AccessibilityButtonController.java +++ b/core/java/android/accessibilityservice/AccessibilityButtonController.java @@ -23,6 +23,8 @@ import android.os.RemoteException; import android.util.ArrayMap; import android.util.Slog; +import com.android.internal.util.Preconditions; + /** * Controller for the accessibility button within the system's navigation area * <p> @@ -89,7 +91,7 @@ public final class AccessibilityButtonController { * @param callback the callback to add, must be non-null */ public void registerAccessibilityButtonCallback(@NonNull AccessibilityButtonCallback callback) { - registerAccessibilityButtonCallback(callback, null); + registerAccessibilityButtonCallback(callback, new Handler()); } /** @@ -99,11 +101,12 @@ public final class AccessibilityButtonController { * {@code null}. * * @param callback the callback to add, must be non-null - * @param handler the handler on which to callback should execute, or {@code null} to - * execute on the service's main thread + * @param handler the handler on which the callback should execute, must be non-null */ public void registerAccessibilityButtonCallback(@NonNull AccessibilityButtonCallback callback, - @Nullable Handler handler) { + @NonNull Handler handler) { + Preconditions.checkNotNull(callback); + Preconditions.checkNotNull(handler); synchronized (mLock) { if (mCallbacks == null) { mCallbacks = new ArrayMap<>(); @@ -121,6 +124,7 @@ public final class AccessibilityButtonController { */ public void unregisterAccessibilityButtonCallback( @NonNull AccessibilityButtonCallback callback) { + Preconditions.checkNotNull(callback); synchronized (mLock) { if (mCallbacks == null) { return; @@ -154,12 +158,7 @@ public final class AccessibilityButtonController { for (int i = 0, count = entries.size(); i < count; i++) { final AccessibilityButtonCallback callback = entries.keyAt(i); final Handler handler = entries.valueAt(i); - if (handler != null) { - handler.post(() -> callback.onClicked(this)); - } else { - // We're already on the main thread, just run the callback. - callback.onClicked(this); - } + handler.post(() -> callback.onClicked(this)); } } @@ -184,12 +183,7 @@ public final class AccessibilityButtonController { for (int i = 0, count = entries.size(); i < count; i++) { final AccessibilityButtonCallback callback = entries.keyAt(i); final Handler handler = entries.valueAt(i); - if (handler != null) { - handler.post(() -> callback.onAvailabilityChanged(this, available)); - } else { - // We're already on the main thread, just run the callback. - callback.onAvailabilityChanged(this, available); - } + handler.post(() -> callback.onAvailabilityChanged(this, available)); } } diff --git a/core/java/android/accessibilityservice/FingerprintGestureController.java b/core/java/android/accessibilityservice/FingerprintGestureController.java index e203c6de8fb5..db00fffc3a28 100644 --- a/core/java/android/accessibilityservice/FingerprintGestureController.java +++ b/core/java/android/accessibilityservice/FingerprintGestureController.java @@ -156,9 +156,9 @@ public final class FingerprintGestureController { FingerprintGestureCallback callback = handlerMap.keyAt(i); Handler handler = handlerMap.valueAt(i); if (handler != null) { - handler.post(() -> callback.onGesture(gesture)); + handler.post(() -> callback.onGestureDetected(gesture)); } else { - callback.onGesture(gesture); + callback.onGestureDetected(gesture); } } } @@ -180,6 +180,12 @@ public final class FingerprintGestureController { * @param gesture The id of the gesture that was detected. For example, * {@link #FINGERPRINT_GESTURE_SWIPE_RIGHT}. */ + public void onGestureDetected(int gesture) {} + + /** + * @deprecated Never called. Use onGestureDetected. + */ + @Deprecated public void onGesture(int gesture) {} } } diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 06b09c041f1f..a5b37f391c16 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -376,7 +376,7 @@ public class AccountManager { * {@link #VISIBILITY_USER_MANAGED_NOT_VISIBLE} is used. */ public static final String PACKAGE_NAME_KEY_LEGACY_VISIBLE = - "android.accounts.key_legacy_visible"; + "android:accounts:key_legacy_visible"; /** * Key to set visibility for applications which satisfy one of the following conditions: @@ -395,7 +395,7 @@ public class AccountManager { * {@link #VISIBILITY_USER_MANAGED_VISIBLE} is used. */ public static final String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE = - "android.accounts.key_legacy_not_visible"; + "android:accounts:key_legacy_not_visible"; /** * @hide diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 6e7b7504d4f3..223047241480 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -3143,10 +3143,15 @@ public class ActivityManager { * before {@link Build.VERSION_CODES#O}. Since the {@link Build.VERSION_CODES#O} SDK, * the value of {@link #IMPORTANCE_PERCEPTIBLE} has been fixed. * - * @deprecated Use {@link #IMPORTANCE_PERCEPTIBLE} instead. + * <p>The system will return this value instead of {@link #IMPORTANCE_PERCEPTIBLE} + * on Android versions below {@link Build.VERSION_CODES#O}. + * + * <p>On Android version {@link Build.VERSION_CODES#O} and later, this value will still be + * returned for apps with the target API level below {@link Build.VERSION_CODES#O}. + * For apps targeting version {@link Build.VERSION_CODES#O} and later, + * the correct value {@link #IMPORTANCE_PERCEPTIBLE} will be returned. */ - @Deprecated - public static final int IMPORTANCE_PERCEPTIBLE_DEPRECATED = 130; + public static final int IMPORTANCE_PERCEPTIBLE_PRE_26 = 130; /** * Constant for {@link #importance}: This process is not something the user @@ -3160,11 +3165,17 @@ public class ActivityManager { * before {@link Build.VERSION_CODES#O}. Since the {@link Build.VERSION_CODES#O} SDK, * the value of {@link #IMPORTANCE_CANT_SAVE_STATE} has been fixed. * - * @deprecated Use {@link #IMPORTANCE_CANT_SAVE_STATE} instead. + * <p>The system will return this value instead of {@link #IMPORTANCE_CANT_SAVE_STATE} + * on Android versions below {@link Build.VERSION_CODES#O}. + * + * <p>On Android version {@link Build.VERSION_CODES#O} after, this value will still be + * returned for apps with the target API level below {@link Build.VERSION_CODES#O}. + * For apps targeting version {@link Build.VERSION_CODES#O} and later, + * the correct value {@link #IMPORTANCE_CANT_SAVE_STATE} will be returned. + * * @hide */ - @Deprecated - public static final int IMPORTANCE_CANT_SAVE_STATE_DEPRECATED = 170; + public static final int IMPORTANCE_CANT_SAVE_STATE_PRE_26 = 170; /** * Constant for {@link #importance}: This process is running an @@ -3244,15 +3255,25 @@ public class ActivityManager { */ public static @Importance int procStateToImportanceForClient(int procState, Context clientContext) { + return procStateToImportanceForTargetSdk(procState, + clientContext.getApplicationInfo().targetSdkVersion); + } + + /** + * See {@link #procStateToImportanceForClient}. + * @hide + */ + public static @Importance int procStateToImportanceForTargetSdk(int procState, + int targetSdkVersion) { final int importance = procStateToImportance(procState); // For pre O apps, convert to the old, wrong values. - if (clientContext.getApplicationInfo().targetSdkVersion < VERSION_CODES.O) { + if (targetSdkVersion < VERSION_CODES.O) { switch (importance) { case IMPORTANCE_PERCEPTIBLE: - return IMPORTANCE_PERCEPTIBLE_DEPRECATED; + return IMPORTANCE_PERCEPTIBLE_PRE_26; case IMPORTANCE_CANT_SAVE_STATE: - return IMPORTANCE_CANT_SAVE_STATE_DEPRECATED; + return IMPORTANCE_CANT_SAVE_STATE_PRE_26; } } return importance; diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 63e8cc641ce9..3eec596fcb17 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -211,6 +211,9 @@ public class ActivityOptions { private static final String KEY_USAGE_TIME_REPORT = "android:activity.usageTimeReport"; private static final String KEY_ROTATION_ANIMATION_HINT = "android:activity.rotationAnimationHint"; + private static final String KEY_INSTANT_APP_VERIFICATION_BUNDLE + = "android:instantapps.installerbundle"; + /** @hide */ public static final int ANIM_NONE = 0; /** @hide */ @@ -264,6 +267,7 @@ public class ActivityOptions { private boolean mTaskOverlayCanResume; private AppTransitionAnimationSpec mAnimSpecs[]; private int mRotationAnimationHint = -1; + private Bundle mAppVerificationBundle; /** * Create an ActivityOptions specifying a custom animation to run when @@ -886,6 +890,7 @@ public class ActivityOptions { opts.getBinder(KEY_ANIMATION_FINISHED_LISTENER)); } mRotationAnimationHint = opts.getInt(KEY_ROTATION_ANIMATION_HINT); + mAppVerificationBundle = opts.getBundle(KEY_INSTANT_APP_VERIFICATION_BUNDLE); } /** @@ -1275,6 +1280,9 @@ public class ActivityOptions { b.putBinder(KEY_ANIMATION_FINISHED_LISTENER, mAnimationFinishedListener.asBinder()); } b.putInt(KEY_ROTATION_ANIMATION_HINT, mRotationAnimationHint); + if (mAppVerificationBundle != null) { + b.putBundle(KEY_INSTANT_APP_VERIFICATION_BUNDLE, mAppVerificationBundle); + } return b; } @@ -1342,6 +1350,30 @@ public class ActivityOptions { mRotationAnimationHint = hint; } + /** + * Pop the extra verification bundle for the installer. + * This removes the bundle from the ActivityOptions to make sure the installer bundle + * is only available once. + * @hide + */ + public Bundle popAppVerificationBundle() { + Bundle out = mAppVerificationBundle; + mAppVerificationBundle = null; + return out; + } + + /** + * Set the {@link Bundle} that is provided to the app installer for additional verification + * if the call to {@link Context#startActivity} results in an app being installed. + * + * This Bundle is not provided to any other app besides the installer. + */ + public ActivityOptions setAppVerificationBundle(Bundle bundle) { + mAppVerificationBundle = bundle; + return this; + + } + /** @hide */ @Override public String toString() { diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 195ba247896e..dd9db8a98202 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -670,6 +670,7 @@ public final class ActivityThread { IBinder requestToken; int requestType; int sessionId; + int flags; } static final class ActivityConfigChangeData { @@ -1288,12 +1289,13 @@ public final class ActivityThread { @Override public void requestAssistContextExtras(IBinder activityToken, IBinder requestToken, - int requestType, int sessionId) { + int requestType, int sessionId, int flags) { RequestAssistContextExtras cmd = new RequestAssistContextExtras(); cmd.activityToken = activityToken; cmd.requestToken = requestToken; cmd.requestType = requestType; cmd.sessionId = sessionId; + cmd.flags = flags; sendMessage(H.REQUEST_ASSIST_CONTEXT_EXTRAS, cmd); } @@ -3030,7 +3032,7 @@ public final class ActivityThread { referrer = r.activity.onProvideReferrer(); } if (cmd.requestType == ActivityManager.ASSIST_CONTEXT_FULL || forAutofill) { - structure = new AssistStructure(r.activity, forAutofill); + structure = new AssistStructure(r.activity, forAutofill, cmd.flags); Intent activityIntent = r.activity.getIntent(); boolean notSecure = r.window == null || (r.window.getAttributes().flags diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java index 65c5b4f702b2..46e6defbb41a 100644 --- a/core/java/android/app/BackStackRecord.java +++ b/core/java/android/app/BackStackRecord.java @@ -621,7 +621,7 @@ final class BackStackRecord extends FragmentTransaction implements } @Override - public FragmentTransaction postOnCommit(Runnable runnable) { + public FragmentTransaction runOnCommit(Runnable runnable) { if (runnable == null) { throw new IllegalArgumentException("runnable cannot be null"); } diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index fdd1b7e72352..63c0ef33ff36 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -452,6 +452,18 @@ public abstract class FragmentManager { public void onFragmentAttached(FragmentManager fm, Fragment f, Context context) {} /** + * Called right before the fragment's {@link Fragment#onCreate(Bundle)} method is called. + * This is a good time to inject any required dependencies or perform other configuration + * for the fragment. + * + * @param fm Host FragmentManager + * @param f Fragment changing state + * @param savedInstanceState Saved instance bundle from a previous instance + */ + public void onFragmentPreCreated(FragmentManager fm, Fragment f, + Bundle savedInstanceState) {} + + /** * Called after the fragment has returned from the FragmentManager's call to * {@link Fragment#onCreate(Bundle)}. This will only happen once for any given * fragment instance, though the fragment may be attached and detached multiple times. @@ -1218,6 +1230,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate dispatchOnFragmentAttached(f, mHost.getContext(), false); if (!f.mRetaining) { + dispatchOnFragmentPreCreated(f, f.mSavedFragmentState, false); f.performCreate(f.mSavedFragmentState); dispatchOnFragmentCreated(f, f.mSavedFragmentState, false); } else { @@ -3274,6 +3287,25 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate } } + void dispatchOnFragmentPreCreated(Fragment f, Bundle savedInstanceState, + boolean onlyRecursive) { + if (mParent != null) { + FragmentManager parentManager = mParent.getFragmentManager(); + if (parentManager instanceof FragmentManagerImpl) { + ((FragmentManagerImpl) parentManager) + .dispatchOnFragmentPreCreated(f, savedInstanceState, true); + } + } + if (mLifecycleCallbacks == null) { + return; + } + for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) { + if (!onlyRecursive || p.second) { + p.first.onFragmentPreCreated(this, f, savedInstanceState); + } + } + } + void dispatchOnFragmentCreated(Fragment f, Bundle savedInstanceState, boolean onlyRecursive) { if (mParent != null) { FragmentManager parentManager = mParent.getFragmentManager(); diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java index a0e5a4ec6f1f..c910e9035a3f 100644 --- a/core/java/android/app/FragmentTransaction.java +++ b/core/java/android/app/FragmentTransaction.java @@ -315,14 +315,22 @@ public abstract class FragmentTransaction { * in this transaction may have been optimized out due to the presence of a subsequent * fragment transaction in the batch. * - * <p><code>postOnCommit</code> may not be used with transactions + * + * <p>If a transaction is committed using {@link #commitAllowingStateLoss()} this runnable + * may be executed when the FragmentManager is in a state where new transactions may not + * be committed without allowing state loss.</p> + * + * <p><code>runOnCommit</code> may not be used with transactions * {@link #addToBackStack(String) added to the back stack} as Runnables cannot be persisted - * with back stack state.</p> + * with back stack state. {@link IllegalStateException} will be thrown if + * {@link #addToBackStack(String)} has been previously called for this transaction + * or if it is called after a call to <code>runOnCommit</code>.</p> * * @param runnable Runnable to add * @return this FragmentTransaction + * @throws IllegalStateException if {@link #addToBackStack(String)} has been called */ - public abstract FragmentTransaction postOnCommit(Runnable runnable); + public abstract FragmentTransaction runOnCommit(Runnable runnable); /** * Schedules a commit of this transaction. The commit does diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 5ee8e0c258f7..aeccf5629234 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -594,7 +594,7 @@ interface IActivityManager { void unregisterTaskStackListener(ITaskStackListener listener); void moveStackToDisplay(int stackId, int displayId); boolean requestAutofillData(in IResultReceiver receiver, in Bundle receiverExtras, - in IBinder activityToken); + in IBinder activityToken, int flags); void dismissKeyguard(in IBinder token, in IKeyguardDismissCallback callback); int restartUserInBackground(int userId); @@ -605,7 +605,7 @@ interface IActivityManager { void cancelTaskThumbnailTransition(int taskId); /** - * @param taskId the id of the task to retrieve the snapshots for + * @param taskId the id of the task to retrieve the sAutoapshots for * @param reducedResolution if set, if the snapshot needs to be loaded from disk, this will load * a reduced resolution of it, which is much faster * @return a graphic buffer representing a screenshot of a task diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl index 1b3c00b61539..b3521c06ae96 100644 --- a/core/java/android/app/IApplicationThread.aidl +++ b/core/java/android/app/IApplicationThread.aidl @@ -135,7 +135,7 @@ oneway interface IApplicationThread { void dumpDbInfo(in ParcelFileDescriptor fd, in String[] args); void unstableProviderDied(IBinder provider); void requestAssistContextExtras(IBinder activityToken, IBinder requestToken, - int requestType, int sessionId); + int requestType, int sessionId, int flags); void scheduleTranslucentConversionComplete(IBinder token, boolean timeout); void setProcessState(int state); void scheduleInstallProvider(in ProviderInfo provider); diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index 9377d35ecabd..69ed439799f7 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -543,10 +543,10 @@ public class Instrumentation { * Create a new ActivityMonitor that can be used for intercepting any activity to be * started. * - * <p> When an activity is started, {@link #onMatchIntent(Intent)} will be called on + * <p> When an activity is started, {@link #onStartActivity(Intent)} will be called on * instances created using this constructor to see if it is a hit. * - * @see #onMatchIntent(Intent) + * @see #onStartActivity(Intent) */ public ActivityMonitor() { mWhich = null; @@ -558,7 +558,7 @@ public class Instrumentation { /** * @return true if this monitor is used for intercepting any started activity by calling - * into {@link #onMatchIntent(Intent)}, false if this monitor is only used + * into {@link #onStartActivity(Intent)}, false if this monitor is only used * for specific intents corresponding to the intent filter or activity class * passed in the constructor. */ @@ -665,7 +665,7 @@ public class Instrumentation { * @param intent The intent used for starting the activity. * @return The {@link ActivityResult} that needs to be used in case of a match. */ - public ActivityResult onMatchIntent(Intent intent) { + public ActivityResult onStartActivity(Intent intent) { return null; } @@ -1589,7 +1589,7 @@ public class Instrumentation { final ActivityMonitor am = mActivityMonitors.get(i); ActivityResult result = null; if (am.ignoreMatchingSpecificIntents()) { - result = am.onMatchIntent(intent); + result = am.onStartActivity(intent); } if (result != null) { am.mHits++; @@ -1652,7 +1652,7 @@ public class Instrumentation { final ActivityMonitor am = mActivityMonitors.get(i); ActivityResult result = null; if (am.ignoreMatchingSpecificIntents()) { - result = am.onMatchIntent(intents[0]); + result = am.onStartActivity(intents[0]); } if (result != null) { am.mHits++; @@ -1722,7 +1722,7 @@ public class Instrumentation { final ActivityMonitor am = mActivityMonitors.get(i); ActivityResult result = null; if (am.ignoreMatchingSpecificIntents()) { - result = am.onMatchIntent(intent); + result = am.onStartActivity(intent); } if (result != null) { am.mHits++; @@ -1789,7 +1789,7 @@ public class Instrumentation { final ActivityMonitor am = mActivityMonitors.get(i); ActivityResult result = null; if (am.ignoreMatchingSpecificIntents()) { - result = am.onMatchIntent(intent); + result = am.onStartActivity(intent); } if (result != null) { am.mHits++; @@ -1835,7 +1835,7 @@ public class Instrumentation { final ActivityMonitor am = mActivityMonitors.get(i); ActivityResult result = null; if (am.ignoreMatchingSpecificIntents()) { - result = am.onMatchIntent(intent); + result = am.onStartActivity(intent); } if (result != null) { am.mHits++; @@ -1880,7 +1880,7 @@ public class Instrumentation { final ActivityMonitor am = mActivityMonitors.get(i); ActivityResult result = null; if (am.ignoreMatchingSpecificIntents()) { - result = am.onMatchIntent(intent); + result = am.onStartActivity(intent); } if (result != null) { am.mHits++; diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java index b8a5f572ccfc..4de6e44b0400 100644 --- a/core/java/android/app/KeyguardManager.java +++ b/core/java/android/app/KeyguardManager.java @@ -381,27 +381,58 @@ public class KeyguardManager { * or {@code null} if the caller isn't interested in knowing the result. * @param handler The handler to invoke the callback on, or {@code null} to use the main * handler. + * + * TO BE REMOVED */ + @Deprecated public void dismissKeyguard(@NonNull Activity activity, @Nullable KeyguardDismissCallback callback, @Nullable Handler handler) { + requestDismissKeyguard(activity, callback); + } + + /** + * If the device is currently locked (see {@link #isKeyguardLocked()}, requests the Keyguard to + * be dismissed. + * <p> + * If the Keyguard is not secure or the device is currently in a trusted state, calling this + * method will immediately dismiss the Keyguard without any user interaction. + * <p> + * If the Keyguard is secure and the device is not in a trusted state, this will bring up the + * UI so the user can enter their credentials. + * + * @param activity The activity requesting the dismissal. The activity must be either visible + * by using {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} or must be in a state in + * which it would be visible if Keyguard would not be hiding it. If that's not + * the case, the request will fail immediately and + * {@link KeyguardDismissCallback#onDismissError} will be invoked. + * @param callback The callback to be called if the request to dismiss Keyguard was successful + * or {@code null} if the caller isn't interested in knowing the result. The + * callback will not be invoked if the activity was destroyed before the + * callback was received. + */ + public void requestDismissKeyguard(@NonNull Activity activity, + @Nullable KeyguardDismissCallback callback) { try { - final Handler actualHandler = handler != null - ? handler - : new Handler(Looper.getMainLooper()); mAm.dismissKeyguard(activity.getActivityToken(), new IKeyguardDismissCallback.Stub() { @Override public void onDismissError() throws RemoteException { - actualHandler.post(callback::onDismissError); + if (callback != null && !activity.isDestroyed()) { + activity.mHandler.post(callback::onDismissError); + } } @Override public void onDismissSucceeded() throws RemoteException { - actualHandler.post(callback::onDismissSucceeded); + if (callback != null && !activity.isDestroyed()) { + activity.mHandler.post(callback::onDismissSucceeded); + } } @Override public void onDismissCancelled() throws RemoteException { - actualHandler.post(callback::onDismissCancelled); + if (callback != null && !activity.isDestroyed()) { + activity.mHandler.post(callback::onDismissCancelled); + } } }); } catch (RemoteException e) { diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 00a8f46f7c2a..28fe3195839d 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -239,16 +239,11 @@ public class Notification implements Parcelable * The number of events that this notification represents. For example, in a new mail * notification, this could be the number of unread messages. * - * The system may or may not use this field to modify the appearance of the notification. For - * example, before {@link android.os.Build.VERSION_CODES#HONEYCOMB}, this number was - * superimposed over the icon in the status bar. Starting with - * {@link android.os.Build.VERSION_CODES#HONEYCOMB}, the template used by - * {@link Notification.Builder} has displayed the number in the expanded notification view. + * The system may or may not use this field to modify the appearance of the notification. * Starting with {@link android.os.Build.VERSION_CODES#O}, the number may be displayed as a * badge icon in Launchers that support badging. - * */ - public int number = 1; + public int number = 0; /** * The intent to execute when the expanded status entry is clicked. If @@ -1290,7 +1285,7 @@ public class Notification implements Parcelable * action is sent. These remote inputs are guaranteed to return true on a call to * {@link RemoteInput#isDataOnly}. * - * May return null if no data-only remote inputs were added. + * Returns null if there are no data-only remote inputs. * * This method exists so that legacy RemoteInput collectors that pre-date the addition * of non-textual RemoteInputs do not access these remote inputs. @@ -2681,21 +2676,12 @@ public class Notification implements Parcelable private int mPrimaryTextColor = COLOR_INVALID; private int mSecondaryTextColor = COLOR_INVALID; private int mActionBarColor = COLOR_INVALID; + private int mBackgroundColor = COLOR_INVALID; + private int mForegroundColor = COLOR_INVALID; /** * Constructs a new Builder with the defaults: * - - * <table> - * <tr><th align=right>priority</th> - * <td>{@link #PRIORITY_DEFAULT}</td></tr> - * <tr><th align=right>when</th> - * <td>now ({@link System#currentTimeMillis()})</td></tr> - * <tr><th align=right>audio stream</th> - * <td>{@link #STREAM_DEFAULT}</td></tr> - * </table> - * - * @param context * A {@link Context} that will be used by the Builder to construct the * RemoteViews. The Context will not be held past the lifetime of this Builder @@ -3854,10 +3840,62 @@ public class Notification implements Parcelable || mActionBarColor == COLOR_INVALID || mTextColorsAreForBackground != backgroundColor) { mTextColorsAreForBackground = backgroundColor; - mPrimaryTextColor = NotificationColorUtil.resolvePrimaryColor( - mContext, backgroundColor); - mSecondaryTextColor = NotificationColorUtil.resolveSecondaryColor( - mContext, backgroundColor); + if (mForegroundColor == COLOR_INVALID || !isColorized()) { + mPrimaryTextColor = NotificationColorUtil.resolvePrimaryColor(mContext, + backgroundColor); + mSecondaryTextColor = NotificationColorUtil.resolveSecondaryColor(mContext, + backgroundColor); + } else { + double backLum = NotificationColorUtil.calculateLuminance(backgroundColor); + double textLum = NotificationColorUtil.calculateLuminance(mForegroundColor); + double contrast = NotificationColorUtil.calculateContrast(mForegroundColor, + backgroundColor); + boolean textDark = backLum > textLum; + if (contrast < 4.5f) { + if (textDark) { + mSecondaryTextColor = NotificationColorUtil.findContrastColor( + mForegroundColor, + backgroundColor, + true /* findFG */, + 4.5f); + mPrimaryTextColor = NotificationColorUtil.changeColorLightness( + mSecondaryTextColor, -20); + } else { + mSecondaryTextColor = + NotificationColorUtil.findContrastColorAgainstDark( + mForegroundColor, + backgroundColor, + true /* findFG */, + 4.5f); + mPrimaryTextColor = NotificationColorUtil.changeColorLightness( + mSecondaryTextColor, 10); + } + } else { + mPrimaryTextColor = mForegroundColor; + mSecondaryTextColor = NotificationColorUtil.changeColorLightness( + mPrimaryTextColor, textDark ? 10 : -20); + if (NotificationColorUtil.calculateContrast(mSecondaryTextColor, + backgroundColor) < 4.5f) { + // oh well the secondary is not good enough + if (textDark) { + mSecondaryTextColor = NotificationColorUtil.findContrastColor( + mSecondaryTextColor, + backgroundColor, + true /* findFG */, + 4.5f); + } else { + mSecondaryTextColor + = NotificationColorUtil.findContrastColorAgainstDark( + mSecondaryTextColor, + backgroundColor, + true /* findFG */, + 4.5f); + } + mPrimaryTextColor = NotificationColorUtil.changeColorLightness( + mSecondaryTextColor, textDark ? -20 : 10); + } + } + } mActionBarColor = NotificationColorUtil.resolveActionBarColor(mContext, backgroundColor); } @@ -4845,7 +4883,7 @@ public class Notification implements Parcelable private int getBackgroundColor() { if (isColorized()) { - return mN.color; + return mBackgroundColor != COLOR_INVALID ? mBackgroundColor : mN.color; } else { return COLOR_DEFAULT; } @@ -4863,6 +4901,21 @@ public class Notification implements Parcelable return targetSdkVersion > Build.VERSION_CODES.M && targetSdkVersion < Build.VERSION_CODES.O; } + + /** + * Set a color palette to be used as the background and textColors + * + * @param backgroundColor the color to be used as the background + * @param foregroundColor the color to be used as the foreground + * + * @hide + */ + public void setColorPalette(int backgroundColor, int foregroundColor) { + mBackgroundColor = backgroundColor; + mForegroundColor = foregroundColor; + mTextColorsAreForBackground = COLOR_INVALID; + ensureColors(); + } } /** @@ -4899,6 +4952,18 @@ public class Notification implements Parcelable * @hide */ public boolean isColorized() { + if (isColorizedMedia()) { + return true; + } + return extras.getBoolean(EXTRA_COLORIZED) && isForegroundService(); + } + + /** + * @return true if this notification is colorized and it is a media notification + * + * @hide + */ + public boolean isColorizedMedia() { Class<? extends Style> style = getNotificationStyle(); if (MediaStyle.class.equals(style)) { Boolean colorized = (Boolean) extras.get(EXTRA_COLORIZED); @@ -4910,7 +4975,23 @@ public class Notification implements Parcelable return true; } } - return extras.getBoolean(EXTRA_COLORIZED) && isForegroundService(); + return false; + } + + + /** + * @return true if this is a media notification + * + * @hide + */ + public boolean isMediaNotification() { + Class<? extends Style> style = getNotificationStyle(); + if (MediaStyle.class.equals(style)) { + return true; + } else if (DecoratedMediaCustomViewStyle.class.equals(style)) { + return true; + } + return false; } private boolean hasLargeIcon() { diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 7c361b9f9853..6c55548c2ea4 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -422,7 +422,9 @@ public class NotificationManager * Creates a notification channel that notifications can be posted to. * * This can also be used to restore a deleted channel and to update an existing channel's - * name and description. The name and description should only be changed if the locale changes + * name and description. + * + * <p>The name and description should only be changed if the locale changes * or in response to the user renaming this channel. For example, if a user has a channel * named 'John Doe' that represents messages from a 'John Doe', and 'John Doe' changes his name * to 'John Smith,' the channel can be renamed to match. @@ -454,6 +456,8 @@ public class NotificationManager /** * Returns the notification channel settings for a given channel id. + * + * The channel must belong to your package, or it will not be returned. */ public NotificationChannel getNotificationChannel(String channelId) { INotificationManager service = getService(); @@ -465,7 +469,7 @@ public class NotificationManager } /** - * Returns all notification channels belonging to the calling app. + * Returns all notification channels belonging to the calling package. */ public List<NotificationChannel> getNotificationChannels() { INotificationManager service = getService(); @@ -478,6 +482,10 @@ public class NotificationManager /** * Deletes the given notification channel. + * + * <p>If you {@link #createNotificationChannel(NotificationChannel) create} a new channel with + * this same id, the deleted channel will be un-deleted with all of the same settings it + * had before it was deleted. */ public void deleteNotificationChannel(String channelId) { INotificationManager service = getService(); @@ -501,7 +509,8 @@ public class NotificationManager } /** - * Deletes the given notification channel group. + * Deletes the given notification channel group, and all notification channels that + * belong to it. */ public void deleteNotificationChannelGroup(String groupId) { INotificationManager service = getService(); diff --git a/core/java/android/app/PictureInPictureParams.java b/core/java/android/app/PictureInPictureParams.java index 875d59272267..e1df33b55281 100644 --- a/core/java/android/app/PictureInPictureParams.java +++ b/core/java/android/app/PictureInPictureParams.java @@ -238,7 +238,7 @@ public class PictureInPictureParams implements Parcelable { */ public void truncateActions(int size) { if (hasSetActions()) { - mUserActions = mUserActions.subList(0, size); + mUserActions = mUserActions.subList(0, Math.min(mUserActions.size(), size)); } } diff --git a/core/java/android/app/RemoteInput.java b/core/java/android/app/RemoteInput.java index d1dc85931404..8ab19c06df80 100644 --- a/core/java/android/app/RemoteInput.java +++ b/core/java/android/app/RemoteInput.java @@ -118,6 +118,11 @@ public final class RemoteInput implements Parcelable { return mChoices; } + /** + * Get possible non-textual inputs that are accepted. + * This can be {@code null} if the input does not accept non-textual values. + * See {@link Builder#setAllowDataType}. + */ public Set<String> getAllowedDataTypes() { return mAllowedDataTypes; } @@ -202,7 +207,9 @@ public final class RemoteInput implements Parcelable { } /** - * Specifies whether the user can provide arbitrary values. + * Specifies whether the user can provide arbitrary values. This allows an input + * to accept non-textual values. Examples of usage are an input that wants audio + * or an image. * * @param mimeType A mime type that results are allowed to come in. * Be aware that text results (see {@link #setAllowFreeFormInput} @@ -374,7 +381,12 @@ public final class RemoteInput implements Parcelable { } /** - * Same as {@link #addResultsToIntent} but for setting data results. + * Same as {@link #addResultsToIntent} but for setting data results. This is used + * for inputs that accept non-textual results (see {@link Builder#setAllowDataType}). + * Only one result can be provided for every mime type accepted by the RemoteInput. + * If multiple inputs of the same mime type are expected then multiple RemoteInputs + * should be used. + * * @param remoteInput The remote input for which results are being provided * @param intent The intent to add remote input results to. The {@link ClipData} * field of the intent will be modified to contain the results. diff --git a/core/java/android/app/WallpaperColors.java b/core/java/android/app/WallpaperColors.java deleted file mode 100644 index 5ed66cac5f8f..000000000000 --- a/core/java/android/app/WallpaperColors.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package android.app; - -import android.graphics.Color; -import android.os.Parcel; -import android.os.Parcelable; - -import android.util.Pair; - -import java.util.List; - -/** - * A class containing information about the colors of a wallpaper. - */ -public final class WallpaperColors implements Parcelable { - - public WallpaperColors(Parcel parcel) { - } - - /** - * Wallpaper color details containing a list of colors and their weights, - * as if it were an histogram. - * This list can be extracted from a bitmap by the Palette API. - * - * Dark text support will be calculated internally based on the histogram. - * - * @param colors list of pairs where each pair contains a color - * and number of occurrences/influence. - */ - public WallpaperColors(List<Pair<Color, Integer>> colors) { - } - - /** - * Wallpaper color details containing a list of colors and their weights, - * as if it were an histogram. - * Explicit dark text support. - * - * @param colors list of pairs where each pair contains a color - * and number of occurrences/influence. - * @param supportsDarkText can have dark text on top or not - */ - public WallpaperColors(List<Pair<Color, Integer>> colors, boolean supportsDarkText) { - } - - public static final Creator<WallpaperColors> CREATOR = new Creator<WallpaperColors>() { - @Override - public WallpaperColors createFromParcel(Parcel in) { - return new WallpaperColors(in); - } - - @Override - public WallpaperColors[] newArray(int size) { - return new WallpaperColors[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - } - - /** - * List of colors with their occurrences. The bigger the int, the more relevant the color. - * @return list of colors paired with their weights. - */ - public List<Pair<Color, Integer>> getColors() { - return null; - } - - /** - * Whether or not dark text is legible on top of this wallpaper. - * - * @return true if dark text is supported - */ - public boolean supportsDarkText() { - return false; - } -} diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 6d87de8e3001..db2f937e2ef2 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -17,8 +17,6 @@ package android.app; import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; import android.annotation.RawRes; import android.annotation.SdkConstant; import android.annotation.SystemApi; @@ -746,43 +744,6 @@ public class WallpaperManager { return getWallpaperFile(which, mContext.getUserId()); } - - /** - * Registers a listener to get notified when the wallpaper colors change. - * Callback might be called from an arbitrary background thread. - * - * @param listener A listener to register - */ - public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener) { - } - - /** - * Registers a listener to get notified when the wallpaper colors change - * @param listener A listener to register - * @param handler Where to call it from. Might be called from a background thread - * if null. - */ - public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener, - @Nullable Handler handler) { - } - - /** - * Stop listening to color updates. - * @param callback A callback to unsubscribe - */ - public void removeOnColorsChangedListener(@NonNull OnColorsChangedListener callback) { - } - - /** - * Get the primary colors of a wallpaper - * @param which wallpaper type. Must be either {@link #FLAG_SYSTEM} or - * {@link #FLAG_LOCK} - * @return a list of colors ordered by priority - */ - public @Nullable WallpaperColors getWallpaperColors(int which) { - return null; - } - /** * Version of {@link #getWallpaperFile(int)} that can access the wallpaper data * for a given user. The caller must hold the INTERACT_ACROSS_USERS_FULL @@ -1774,19 +1735,4 @@ public class WallpaperManager { mLatch.countDown(); } } - - /** - * Interface definition for a callback to be invoked when colors change on a wallpaper. - */ - public interface OnColorsChangedListener { - /** - * Called when colors change. - * A {@link android.app.WallpaperColors} object containing a simplified - * color histogram will be given. - * - * @param colors Wallpaper color info - * @param which A combination of {@link #FLAG_LOCK} and {@link #FLAG_SYSTEM} - */ - void onColorsChanged(WallpaperColors colors, int which); - } } diff --git a/core/java/android/app/admin/ConnectEvent.java b/core/java/android/app/admin/ConnectEvent.java index 5111443d7045..423ee52ee6a1 100644 --- a/core/java/android/app/admin/ConnectEvent.java +++ b/core/java/android/app/admin/ConnectEvent.java @@ -19,6 +19,9 @@ package android.app.admin; import android.os.Parcel; import android.os.Parcelable; +import java.net.InetAddress; +import java.net.UnknownHostException; + /** * A class that represents a connect library call event. */ @@ -44,8 +47,14 @@ public final class ConnectEvent extends NetworkEvent implements Parcelable { this.timestamp = in.readLong(); } - public String getIpAddress() { - return ipAddress; + public InetAddress getInetAddress() { + try { + // ipAddress is already an address, not a host name, no DNS resolution will happen. + return InetAddress.getByName(ipAddress); + } catch (UnknownHostException e) { + // Should never happen as we aren't passing a host name. + return InetAddress.getLoopbackAddress(); + } } public int getPort() { diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index f5df67b6035c..8fcabce61825 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -3030,17 +3030,24 @@ public class DevicePolicyManager { * keyring. The user's credential will need to be entered again in order to derive the * credential encryption key that will be stored back in the keyring for future use. * <p> - * This flag can only be used by a profile owner when locking a managed profile on an FBE - * device. + * This flag can only be used by a profile owner when locking a managed profile when + * {@link #getStorageEncryptionStatus} returns {@link #ENCRYPTION_STATUS_ACTIVE_PER_USER}. * <p> * In order to secure user data, the user will be stopped and restarted so apps should wait * until they are next run to perform further actions. */ + public static final int FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY = 1; + + /** + * Instead use {@link #FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY}. + * @removed + */ + @Deprecated public static final int FLAG_EVICT_CE_KEY = 1; /** @hide */ @Retention(RetentionPolicy.SOURCE) - @IntDef(flag=true, value={FLAG_EVICT_CE_KEY}) + @IntDef(flag=true, value={FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY}) public @interface LockNowFlag {} /** @@ -3072,15 +3079,17 @@ public class DevicePolicyManager { * This method can be called on the {@link DevicePolicyManager} instance returned by * {@link #getParentProfileInstance(ComponentName)} in order to lock the parent profile. * - * @param flags May be 0 or {@link #FLAG_EVICT_CE_KEY}. + * @param flags May be 0 or {@link #FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY}. * @throws SecurityException if the calling application does not own an active administrator * that uses {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} or the - * {@link #FLAG_EVICT_CE_KEY} flag is passed by an application that is not a profile + * {@link #FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY} flag is passed by an application + * that is not a profile * owner of a managed profile. - * @throws IllegalArgumentException if the {@link #FLAG_EVICT_CE_KEY} flag is passed when - * locking the parent profile. - * @throws UnsupportedOperationException if the {@link #FLAG_EVICT_CE_KEY} flag is passed on a - * non-FBE device. + * @throws IllegalArgumentException if the {@link #FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY} flag is + * passed when locking the parent profile. + * @throws UnsupportedOperationException if the {@link #FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY} + * flag is passed when {@link #getStorageEncryptionStatus} does not return + * {@link #ENCRYPTION_STATUS_ACTIVE_PER_USER}. */ public void lockNow(@LockNowFlag int flags) { if (mService != null) { diff --git a/core/java/android/app/admin/DnsEvent.java b/core/java/android/app/admin/DnsEvent.java index a3a3f586008d..c21725f0e86f 100644 --- a/core/java/android/app/admin/DnsEvent.java +++ b/core/java/android/app/admin/DnsEvent.java @@ -19,6 +19,12 @@ package android.app.admin; import android.os.Parcel; import android.os.Parcelable; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + /** * A class that represents a DNS lookup event. */ @@ -59,15 +65,28 @@ public final class DnsEvent extends NetworkEvent implements Parcelable { } /** Returns (possibly a subset of) the IP addresses returned. */ - public String[] getIpAddresses() { - return ipAddresses; + public List<InetAddress> getInetAddresses() { + if (ipAddresses == null || ipAddresses.length == 0) { + return Collections.emptyList(); + } + final List<InetAddress> inetAddresses = new ArrayList<>(ipAddresses.length); + for (final String ipAddress : ipAddresses) { + try { + // ipAddress is already an address, not a host name, no DNS resolution will happen. + inetAddresses.add(InetAddress.getByName(ipAddress)); + } catch (UnknownHostException e) { + // Should never happen as we aren't passing a host name. + } + } + return inetAddresses; } /** * Returns the number of IP addresses returned from the DNS lookup event. May be different from - * the length of ipAddresses if there were too many addresses to log. + * the length of the list returned by {@link #getInetAddresses()} if there were too many + * addresses to log. */ - public int getIpAddressesCount() { + public int getTotalResolvedAddressCount() { return ipAddressesCount; } diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java index d6b89a17c624..33535302bd5c 100644 --- a/core/java/android/app/assist/AssistStructure.java +++ b/core/java/android/app/assist/AssistStructure.java @@ -29,10 +29,12 @@ import android.view.ViewStructure.HtmlInfo.Builder; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.autofill.AutofillId; +import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; /** * Assist data automatically created by the platform's implementation of Assist and Autofill. @@ -62,6 +64,7 @@ public class AssistStructure implements Parcelable { ComponentName mActivityComponent; private boolean mIsHomeActivity; + private int mFlags; final ArrayList<WindowNode> mWindowNodes = new ArrayList<>(); @@ -184,6 +187,7 @@ public class AssistStructure implements Parcelable { mSanitizeOnWrite = as.mSanitizeOnWrite; mWriteStructure = as.waitForReady(); ComponentName.writeToParcel(as.mActivityComponent, out); + out.writeInt(as.mFlags); out.writeLong(as.mAcquisitionStartTime); out.writeLong(as.mAcquisitionEndTime); mNumWindows = as.mWindowNodes.size(); @@ -338,6 +342,7 @@ public class AssistStructure implements Parcelable { void go() { fetchData(); mActivityComponent = ComponentName.readFromParcel(mCurParcel); + mFlags = mCurParcel.readInt(); mAcquisitionStartTime = mCurParcel.readLong(); mAcquisitionEndTime = mCurParcel.readLong(); final int N = mCurParcel.readInt(); @@ -473,7 +478,7 @@ public class AssistStructure implements Parcelable { final int mDisplayId; final ViewNode mRoot; - WindowNode(AssistStructure assist, ViewRootImpl root, boolean forAutoFill) { + WindowNode(AssistStructure assist, ViewRootImpl root, boolean forAutoFill, int flags) { View view = root.getView(); Rect rect = new Rect(); view.getBoundsOnScreen(rect); @@ -488,8 +493,9 @@ public class AssistStructure implements Parcelable { ViewNodeBuilder builder = new ViewNodeBuilder(assist, mRoot, false); if ((root.getWindowFlags() & WindowManager.LayoutParams.FLAG_SECURE) != 0) { if (forAutoFill) { - // NOTE: flags are currently not supported, hence 0 - view.onProvideAutofillStructure(builder, 0); + final int autofillFlags = (flags & AutofillManager.FLAG_MANUAL_REQUEST) != 0 + ? View.AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS : 0; + view.onProvideAutofillStructure(builder, autofillFlags); } 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 @@ -499,8 +505,9 @@ public class AssistStructure implements Parcelable { } } if (forAutoFill) { - // NOTE: flags are currently not supported, hence 0 - view.dispatchProvideAutofillStructure(builder, 0); + final int autofillFlags = (flags & AutofillManager.FLAG_MANUAL_REQUEST) != 0 + ? View.AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS : 0; + view.dispatchProvideAutofillStructure(builder, autofillFlags); } else { view.dispatchProvideStructure(builder); } @@ -1788,7 +1795,7 @@ public class AssistStructure implements Parcelable { } @Override - public ArrayList<Pair<String, String>> getAttributes() { + public List<Pair<String, String>> getAttributes() { if (mAttributes == null && mNames != null) { mAttributes = new ArrayList<>(mNames.length); for (int i = 0; i < mNames.length; i++) { @@ -1869,20 +1876,22 @@ public class AssistStructure implements Parcelable { } /** @hide */ - public AssistStructure(Activity activity, boolean forAutoFill) { + public AssistStructure(Activity activity, boolean forAutoFill, int flags) { mHaveData = true; mActivityComponent = activity.getComponentName(); + mFlags = flags; ArrayList<ViewRootImpl> views = WindowManagerGlobal.getInstance().getRootViews( activity.getActivityToken()); for (int i=0; i<views.size(); i++) { ViewRootImpl root = views.get(i); - mWindowNodes.add(new WindowNode(this, root, forAutoFill)); + mWindowNodes.add(new WindowNode(this, root, forAutoFill, flags)); } } public AssistStructure() { mHaveData = true; mActivityComponent = null; + mFlags = 0; } /** @hide */ @@ -1909,6 +1918,7 @@ public class AssistStructure implements Parcelable { } Log.i(TAG, "Activity: " + mActivityComponent.flattenToShortString()); Log.i(TAG, "Sanitize on write: " + mSanitizeOnWrite); + Log.i(TAG, "Flags: " + mFlags); final int N = getWindowNodeCount(); for (int i=0; i<N; i++) { WindowNode node = getWindowNodeAt(i); @@ -2021,10 +2031,16 @@ public class AssistStructure implements Parcelable { return mActivityComponent; } + /** @hide */ + public int getFlags() { + return mFlags; + } + /** * Returns whether the activity associated with this AssistStructure was the home activity - * at the time the assist data was acquired. + * (Launcher) at the time the assist data was acquired. * @return Whether the activity was the home activity. + * @see android.content.Intent#CATEGORY_HOME */ public boolean isHomeActivity() { return mIsHomeActivity; diff --git a/core/java/android/app/usage/ExternalStorageStats.java b/core/java/android/app/usage/ExternalStorageStats.java index 10c9b5ff5a50..83ac779ee7db 100644 --- a/core/java/android/app/usage/ExternalStorageStats.java +++ b/core/java/android/app/usage/ExternalStorageStats.java @@ -16,6 +16,7 @@ package android.app.usage; +import android.annotation.BytesLong; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; @@ -37,7 +38,7 @@ public final class ExternalStorageStats implements Parcelable { * Return the total bytes used by all files in the shared/external storage * hosted on this volume. */ - public long getTotalBytes() { + public @BytesLong long getTotalBytes() { return totalBytes; } @@ -45,7 +46,7 @@ public final class ExternalStorageStats implements Parcelable { * Return the total bytes used by audio files in the shared/external storage * hosted on this volume. */ - public long getAudioBytes() { + public @BytesLong long getAudioBytes() { return audioBytes; } @@ -53,7 +54,7 @@ public final class ExternalStorageStats implements Parcelable { * Return the total bytes used by video files in the shared/external storage * hosted on this volume. */ - public long getVideoBytes() { + public @BytesLong long getVideoBytes() { return videoBytes; } @@ -61,7 +62,7 @@ public final class ExternalStorageStats implements Parcelable { * Return the total bytes used by image files in the shared/external storage * hosted on this volume. */ - public long getImageBytes() { + public @BytesLong long getImageBytes() { return imageBytes; } @@ -72,7 +73,7 @@ public final class ExternalStorageStats implements Parcelable { * This data is already accounted against individual apps as returned * through {@link StorageStats}. */ - public long getAppBytes() { + public @BytesLong long getAppBytes() { return appBytes; } diff --git a/core/java/android/app/usage/StorageStats.java b/core/java/android/app/usage/StorageStats.java index 26c702c0eb4e..3a277518977d 100644 --- a/core/java/android/app/usage/StorageStats.java +++ b/core/java/android/app/usage/StorageStats.java @@ -16,6 +16,7 @@ package android.app.usage; +import android.annotation.BytesLong; import android.content.Context; import android.os.Parcel; import android.os.Parcelable; @@ -33,18 +34,24 @@ public final class StorageStats implements Parcelable { /** {@hide} */ public long cacheBytes; /** - * Return the size of all code. This includes {@code APK} files and - * optimized compiler output. + * Return the size of app. This includes {@code APK} files, optimized + * compiler output, and unpacked native libraries. * <p> * If the primary external/shared storage is hosted on this storage device, * then this includes files stored under {@link Context#getObbDir()}. * <p> * Code is shared between all users on a multiuser device. */ - public long getCodeBytes() { + public @BytesLong long getAppBytes() { return codeBytes; } + /** @removed */ + @Deprecated + public long getCodeBytes() { + return getAppBytes(); + } + /** * Return the size of all data. This includes files stored under * {@link Context#getDataDir()}, {@link Context#getCacheDir()}, @@ -58,7 +65,7 @@ public final class StorageStats implements Parcelable { * <p> * Data is isolated for each user on a multiuser device. */ - public long getDataBytes() { + public @BytesLong long getDataBytes() { return dataBytes; } @@ -72,7 +79,7 @@ public final class StorageStats implements Parcelable { * <p> * Cached data is isolated for each user on a multiuser device. */ - public long getCacheBytes() { + public @BytesLong long getCacheBytes() { return cacheBytes; } diff --git a/core/java/android/app/usage/StorageStatsManager.java b/core/java/android/app/usage/StorageStatsManager.java index 5497d57ba264..d9d958c0653c 100644 --- a/core/java/android/app/usage/StorageStatsManager.java +++ b/core/java/android/app/usage/StorageStatsManager.java @@ -18,6 +18,7 @@ package android.app.usage; import static android.os.storage.StorageManager.convert; +import android.annotation.BytesLong; import android.annotation.NonNull; import android.annotation.TestApi; import android.annotation.WorkerThread; @@ -37,13 +38,16 @@ import java.io.IOException; import java.util.UUID; /** - * Provides access to detailed storage statistics. + * Access to detailed storage statistics. This provides a summary of how apps, + * users, and external/shared storage is utilizing disk space. * <p class="note"> - * Note: this API requires the permission - * {@code android.permission.PACKAGE_USAGE_STATS}, which is a system-level - * permission that will not be granted to normal apps. However, declaring the - * permission expresses your intention to use this API and an end user can then - * choose to grant this permission through the Settings application. + * Note: no permissions are required when calling these APIs for your own + * package or UID. However, requesting details for any other package requires + * the {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which + * is a system-level permission that will not be granted to normal apps. + * Declaring that permission expresses your intention to use this API and an end + * user can then choose to grant this permission through the Settings + * application. * </p> */ public class StorageStatsManager { @@ -73,19 +77,22 @@ public class StorageStatsManager { } /** - * Return the total size of the underlying media that is hosting this - * storage volume. + * Return the total size of the underlying physical media that is hosting + * this storage volume. * <p> - * To reduce end user confusion, this value matches the total storage size - * advertised in a retail environment, which is typically larger than the - * actual usable partition space. + * This value is best suited for visual display to end users, since it's + * designed to reflect the total storage size advertised in a retail + * environment. + * <p> + * Apps making logical decisions about disk space should always use + * {@link File#getTotalSpace()} instead of this value. * * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. * @throws IOException when the storage device isn't present. */ @WorkerThread - public long getTotalBytes(@NonNull UUID storageUuid) throws IOException { + public @BytesLong long getTotalBytes(@NonNull UUID storageUuid) throws IOException { try { return mService.getTotalBytes(convert(storageUuid), mContext.getOpPackageName()); } catch (ParcelableException e) { @@ -105,19 +112,20 @@ public class StorageStatsManager { /** * Return the free space on the requested storage volume. * <p> - * The free space is equivalent to {@link File#getUsableSpace()} plus the - * size of any cached data that can be automatically deleted by the system - * as additional space is needed. + * This value is best suited for visual display to end users, since it's + * designed to reflect both unused space <em>and</em> and cached space that + * could be reclaimed by the system. * <p> - * This method may take several seconds to calculate the requested values, - * so it should only be called from a worker thread. + * Apps making logical decisions about disk space should always use + * {@link StorageManager#getAllocatableBytes(UUID, int)} instead of this + * value. * * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. * @throws IOException when the storage device isn't present. */ @WorkerThread - public long getFreeBytes(@NonNull UUID storageUuid) throws IOException { + public @BytesLong long getFreeBytes(@NonNull UUID storageUuid) throws IOException { try { return mService.getFreeBytes(convert(storageUuid), mContext.getOpPackageName()); } catch (ParcelableException e) { @@ -137,9 +145,15 @@ public class StorageStatsManager { /** * Return storage statistics for a specific package on the requested storage * volume. - * <p> - * This method may take several seconds to calculate the requested values, - * so it should only be called from a worker thread. + * <p class="note"> + * Note: no permissions are required when calling this API for your own + * package. However, requesting details for any other package requires the + * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which + * is a system-level permission that will not be granted to normal apps. + * Declaring that permission expresses your intention to use this API and an + * end user can then choose to grant this permission through the Settings + * application. + * </p> * <p class="note"> * Note: if the requested package uses the {@code android:sharedUserId} * manifest feature, this call will be forced into a slower manual @@ -158,8 +172,9 @@ public class StorageStatsManager { * @see PackageInfo#packageName */ @WorkerThread - public @NonNull StorageStats queryStatsForPackage(@NonNull UUID storageUuid, String packageName, - UserHandle user) throws PackageManager.NameNotFoundException, IOException { + public @NonNull StorageStats queryStatsForPackage(@NonNull UUID storageUuid, + @NonNull String packageName, @NonNull UserHandle user) + throws PackageManager.NameNotFoundException, IOException { try { return mService.queryStatsForPackage(convert(storageUuid), packageName, user.getIdentifier(), mContext.getOpPackageName()); @@ -182,9 +197,15 @@ public class StorageStatsManager { /** * Return storage statistics for a specific UID on the requested storage * volume. - * <p> - * This method may take several seconds to calculate the requested values, - * so it should only be called from a worker thread. + * <p class="note"> + * Note: no permissions are required when calling this API for your own UID. + * However, requesting details for any other UID requires the + * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which + * is a system-level permission that will not be granted to normal apps. + * Declaring that permission expresses your intention to use this API and an + * end user can then choose to grant this permission through the Settings + * application. + * </p> * * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. @@ -194,7 +215,8 @@ public class StorageStatsManager { * @see ApplicationInfo#uid */ @WorkerThread - public StorageStats queryStatsForUid(@NonNull UUID storageUuid, int uid) throws IOException { + public @NonNull StorageStats queryStatsForUid(@NonNull UUID storageUuid, int uid) + throws IOException { try { return mService.queryStatsForUid(convert(storageUuid), uid, mContext.getOpPackageName()); @@ -215,9 +237,14 @@ public class StorageStatsManager { /** * Return storage statistics for a specific {@link UserHandle} on the * requested storage volume. - * <p> - * This method may take several seconds to calculate the requested values, - * so it should only be called from a worker thread. + * <p class="note"> + * Note: this API requires the + * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which + * is a system-level permission that will not be granted to normal apps. + * Declaring that permission expresses your intention to use this API and an + * end user can then choose to grant this permission through the Settings + * application. + * </p> * * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. @@ -226,8 +253,8 @@ public class StorageStatsManager { * @see android.os.Process#myUserHandle() */ @WorkerThread - public StorageStats queryStatsForUser(@NonNull UUID storageUuid, UserHandle user) - throws IOException { + public @NonNull StorageStats queryStatsForUser(@NonNull UUID storageUuid, + @NonNull UserHandle user) throws IOException { try { return mService.queryStatsForUser(convert(storageUuid), user.getIdentifier(), mContext.getOpPackageName()); @@ -248,9 +275,14 @@ public class StorageStatsManager { /** * Return shared/external storage statistics for a specific * {@link UserHandle} on the requested storage volume. - * <p> - * This method may take several seconds to calculate the requested values, - * so it should only be called from a worker thread. + * <p class="note"> + * Note: this API requires the + * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which + * is a system-level permission that will not be granted to normal apps. + * Declaring that permission expresses your intention to use this API and an + * end user can then choose to grant this permission through the Settings + * application. + * </p> * * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. @@ -258,8 +290,8 @@ public class StorageStatsManager { * @see android.os.Process#myUserHandle() */ @WorkerThread - public ExternalStorageStats queryExternalStatsForUser(@NonNull UUID storageUuid, - UserHandle user) throws IOException { + public @NonNull ExternalStorageStats queryExternalStatsForUser(@NonNull UUID storageUuid, + @NonNull UserHandle user) throws IOException { try { return mService.queryExternalStatsForUser(convert(storageUuid), user.getIdentifier(), mContext.getOpPackageName()); diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java index 713dbf43d331..0f01d62f8b69 100644 --- a/core/java/android/bluetooth/BluetoothGatt.java +++ b/core/java/android/bluetooth/BluetoothGatt.java @@ -159,8 +159,10 @@ public final class BluetoothGatt implements BluetoothProfile { mHandler.post(new Runnable() { @Override public void run() { - mCallback.onConnectionStateChange(BluetoothGatt.this, GATT_FAILURE, - BluetoothProfile.STATE_DISCONNECTED); + if (mCallback != null) { + mCallback.onConnectionStateChange(BluetoothGatt.this, GATT_FAILURE, + BluetoothProfile.STATE_DISCONNECTED); + } } }); @@ -192,7 +194,9 @@ public final class BluetoothGatt implements BluetoothProfile { mHandler.post(new Runnable() { @Override public void run() { - mCallback.onPhyUpdate(BluetoothGatt.this, txPhy, rxPhy, status); + if (mCallback != null) { + mCallback.onPhyUpdate(BluetoothGatt.this, txPhy, rxPhy, status); + } } }); } @@ -212,7 +216,9 @@ public final class BluetoothGatt implements BluetoothProfile { mHandler.post(new Runnable() { @Override public void run() { - mCallback.onPhyRead(BluetoothGatt.this, txPhy, rxPhy, status); + if (mCallback != null) { + mCallback.onPhyRead(BluetoothGatt.this, txPhy, rxPhy, status); + } } }); } @@ -235,7 +241,10 @@ public final class BluetoothGatt implements BluetoothProfile { mHandler.post(new Runnable() { @Override public void run() { - mCallback.onConnectionStateChange(BluetoothGatt.this, status, profileState); + if (mCallback != null) { + mCallback.onConnectionStateChange(BluetoothGatt.this, status, + profileState); + } } }); @@ -294,7 +303,9 @@ public final class BluetoothGatt implements BluetoothProfile { mHandler.post(new Runnable() { @Override public void run() { - mCallback.onServicesDiscovered(BluetoothGatt.this, status); + if (mCallback != null) { + mCallback.onServicesDiscovered(BluetoothGatt.this, status); + } } }); } @@ -344,7 +355,10 @@ public final class BluetoothGatt implements BluetoothProfile { mHandler.post(new Runnable() { @Override public void run() { - mCallback.onCharacteristicRead(BluetoothGatt.this, characteristic, status); + if (mCallback != null) { + mCallback.onCharacteristicRead(BluetoothGatt.this, characteristic, + status); + } } }); } @@ -390,7 +404,10 @@ public final class BluetoothGatt implements BluetoothProfile { mHandler.post(new Runnable() { @Override public void run() { - mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic, status); + if (mCallback != null) { + mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic, + status); + } } }); } @@ -416,7 +433,9 @@ public final class BluetoothGatt implements BluetoothProfile { mHandler.post(new Runnable() { @Override public void run() { - mCallback.onCharacteristicChanged(BluetoothGatt.this, characteristic); + if (mCallback != null) { + mCallback.onCharacteristicChanged(BluetoothGatt.this, characteristic); + } } }); } @@ -461,7 +480,9 @@ public final class BluetoothGatt implements BluetoothProfile { mHandler.post(new Runnable() { @Override public void run() { - mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status); + if (mCallback != null) { + mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status); + } } }); } @@ -505,7 +526,9 @@ public final class BluetoothGatt implements BluetoothProfile { mHandler.post(new Runnable() { @Override public void run() { - mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status); + if (mCallback != null) { + mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status); + } } }); } @@ -529,7 +552,9 @@ public final class BluetoothGatt implements BluetoothProfile { mHandler.post(new Runnable() { @Override public void run() { - mCallback.onReliableWriteCompleted(BluetoothGatt.this, status); + if (mCallback != null) { + mCallback.onReliableWriteCompleted(BluetoothGatt.this, status); + } } }); } @@ -548,7 +573,9 @@ public final class BluetoothGatt implements BluetoothProfile { mHandler.post(new Runnable() { @Override public void run() { - mCallback.onReadRemoteRssi(BluetoothGatt.this, rssi, status); + if (mCallback != null) { + mCallback.onReadRemoteRssi(BluetoothGatt.this, rssi, status); + } } }); } @@ -568,7 +595,9 @@ public final class BluetoothGatt implements BluetoothProfile { mHandler.post(new Runnable() { @Override public void run() { - mCallback.onMtuChanged(BluetoothGatt.this, mtu, status); + if (mCallback != null) { + mCallback.onMtuChanged(BluetoothGatt.this, mtu, status); + } } }); } @@ -590,8 +619,10 @@ public final class BluetoothGatt implements BluetoothProfile { mHandler.post(new Runnable() { @Override public void run() { - mCallback.onConnectionUpdated(BluetoothGatt.this, interval, latency, - timeout, status); + if (mCallback != null) { + mCallback.onConnectionUpdated(BluetoothGatt.this, interval, latency, + timeout, status); + } } }); } @@ -973,6 +1004,41 @@ public final class BluetoothGatt implements BluetoothProfile { } /** + * Reads the characteristic using its UUID from the associated remote device. + * + * <p>This is an asynchronous operation. The result of the read operation + * is reported by the {@link BluetoothGattCallback#onCharacteristicRead} + * callback. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. + * + * @param uuid UUID of characteristic to read from the remote device + * @return true, if the read operation was initiated successfully + * @hide + */ + public boolean readUsingCharacteristicUuid(UUID uuid, int startHandle, int endHandle) { + if (VDBG) Log.d(TAG, "readUsingCharacteristicUuid() - uuid: " + uuid); + if (mService == null || mClientIf == 0) return false; + + synchronized(mDeviceBusy) { + if (mDeviceBusy) return false; + mDeviceBusy = true; + } + + try { + mService.readUsingCharacteristicUuid(mClientIf, mDevice.getAddress(), + new ParcelUuid(uuid), startHandle, endHandle, AUTHENTICATION_NONE); + } catch (RemoteException e) { + Log.e(TAG,"",e); + mDeviceBusy = false; + return false; + } + + return true; + } + + + /** * Writes a given characteristic and its values to the associated remote device. * * <p>Once the write operation has been completed, the diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl index 12e9baaded91..e2d4f5ba4fda 100644 --- a/core/java/android/bluetooth/IBluetoothGatt.aidl +++ b/core/java/android/bluetooth/IBluetoothGatt.aidl @@ -59,6 +59,7 @@ interface IBluetoothGatt { in IAdvertisingSetCallback callback); void stopAdvertisingSet(in IAdvertisingSetCallback callback); + void getOwnAddress(in int advertiserId); void enableAdvertisingSet(in int advertiserId, in boolean enable, in int duration, in int maxExtAdvEvents); void setAdvertisingData(in int advertiserId, in AdvertiseData data); void setScanResponseData(in int advertiserId, in AdvertiseData data); @@ -80,6 +81,8 @@ interface IBluetoothGatt { void refreshDevice(in int clientIf, in String address); void discoverServices(in int clientIf, in String address); void readCharacteristic(in int clientIf, in String address, in int handle, in int authReq); + void readUsingCharacteristicUuid(in int clientIf, in String address, in ParcelUuid uuid, + in int startHandle, in int endHandle, in int authReq); void writeCharacteristic(in int clientIf, in String address, in int handle, in int writeType, in int authReq, in byte[] value); void readDescriptor(in int clientIf, in String address, in int handle, in int authReq); diff --git a/core/java/android/bluetooth/le/AdvertisingSet.java b/core/java/android/bluetooth/le/AdvertisingSet.java index 51571b2746a4..3021be1f8c02 100644 --- a/core/java/android/bluetooth/le/AdvertisingSet.java +++ b/core/java/android/bluetooth/le/AdvertisingSet.java @@ -181,7 +181,23 @@ public final class AdvertisingSet { } /** - * Returns advertiserId associated with thsi advertising set. + * Returns address associated with this advertising set. + * This method is exposed only for Bluetooth PTS tests, no app or system service + * should ever use it. + * + * This method requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission. + * @hide + */ + public void getOwnAddress(){ + try { + gatt.getOwnAddress(this.advertiserId); + } catch (RemoteException e) { + Log.e(TAG, "remote exception - ", e); + } + } + + /** + * Returns advertiserId associated with this advertising set. * * @hide */ diff --git a/core/java/android/bluetooth/le/AdvertisingSetCallback.java b/core/java/android/bluetooth/le/AdvertisingSetCallback.java index fe3b1cdd63a0..2c46e856db4a 100644 --- a/core/java/android/bluetooth/le/AdvertisingSetCallback.java +++ b/core/java/android/bluetooth/le/AdvertisingSetCallback.java @@ -143,4 +143,15 @@ public abstract class AdvertisingSetCallback { */ public void onPeriodicAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enable, int status) {} + + /** + * Callback triggered in response to {@link AdvertisingSet#getOwnAddress()} + * indicating result of the operation. + * + * @param advertisingSet The advertising set. + * @param addressType type of address. + * @param address advertising set bluetooth address. + * @hide + */ + public void onOwnAddressRead(AdvertisingSet advertisingSet, int addressType, String address) {} }
\ No newline at end of file diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java index 0c7958dc9a3c..67d56d5060e9 100644 --- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java +++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java @@ -544,6 +544,17 @@ public final class BluetoothLeAdvertiser { } @Override + public void onOwnAddressRead(int advertiserId, int addressType, String address) { + handler.post(new Runnable() { + @Override + public void run() { + AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId); + callback.onOwnAddressRead(advertisingSet, addressType, address); + } + }); + } + + @Override public void onAdvertisingSetStopped(int advertiserId) { handler.post(new Runnable() { @Override diff --git a/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl b/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl index 2c9f4baad520..3628c775b798 100644 --- a/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl +++ b/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl @@ -21,6 +21,7 @@ package android.bluetooth.le; */ oneway interface IAdvertisingSetCallback { void onAdvertisingSetStarted(in int advertiserId, in int tx_power, in int status); + void onOwnAddressRead(in int advertiserId, in int addressType, in String address); void onAdvertisingSetStopped(in int advertiserId); void onAdvertisingEnabled(in int advertiserId, in boolean enable, in int status); void onAdvertisingDataSet(in int advertiserId, in int status); diff --git a/core/java/android/bluetooth/le/ScanResult.java b/core/java/android/bluetooth/le/ScanResult.java index 5b2fa406cd3f..e552398e9e26 100644 --- a/core/java/android/bluetooth/le/ScanResult.java +++ b/core/java/android/bluetooth/le/ScanResult.java @@ -52,6 +52,16 @@ public final class ScanResult implements Parcelable { public static final int SID_NOT_PRESENT = 0xFF; /** + * TX power is not present in the packet. + */ + public static final int TX_POWER_NOT_PRESENT = 0x7F; + + /** + * Periodic advertising interval is not present in the packet. + */ + public static final int PERIODIC_INTERVAL_NOT_PRESENT = 0x00; + + /** * Mask for checking whether event type represents legacy advertisement. */ private static final int ET_LEGACY_MASK = 0x10; @@ -265,15 +275,16 @@ public final class ScanResult implements Parcelable { /** * Returns the transmit power in dBm. - * Valid range is [-127, 126]. A value of 127 indicates that the - * advertisement did not indicate TX power. + * Valid range is [-127, 126]. A value of {@link ScanResult#TX_POWER_NOT_PRESENT} + * indicates that the TX power is not present. */ public int getTxPower() { return mTxPower; } /** * Returns the periodic advertising interval in units of 1.25ms. - * Valid range is 6 (7.5ms) to 65536 (81918.75ms). A value of 0 means - * periodic advertising is not used for this scan result. + * Valid range is 6 (7.5ms) to 65536 (81918.75ms). A value of + * {@link ScanResult#PERIODIC_INTERVAL_NOT_PRESENT} means periodic + * advertising interval is not present. */ public int getPeriodicAdvertisingInterval() { return mPeriodicAdvertisingInterval; diff --git a/core/java/android/companion/BluetoothLEDeviceFilter.java b/core/java/android/companion/BluetoothLeDeviceFilter.java index e5ea4e94b67f..7a9ba1c3f402 100644 --- a/core/java/android/companion/BluetoothLEDeviceFilter.java +++ b/core/java/android/companion/BluetoothLeDeviceFilter.java @@ -47,10 +47,10 @@ import java.util.regex.Pattern; * * @see ScanFilter */ -public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { +public final class BluetoothLeDeviceFilter implements DeviceFilter<ScanResult> { private static final boolean DEBUG = false; - private static final String LOG_TAG = "BluetoothLEDeviceFilter"; + private static final String LOG_TAG = "BluetoothLeDeviceFilter"; private static final int RENAME_PREFIX_LENGTH_LIMIT = 10; @@ -66,7 +66,7 @@ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { private final int mRenameNameTo; 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, int renameNameFrom, int renameNameTo, boolean renameBytesReverseOrder) { @@ -186,7 +186,7 @@ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - BluetoothLEDeviceFilter that = (BluetoothLEDeviceFilter) o; + BluetoothLeDeviceFilter that = (BluetoothLeDeviceFilter) o; return mRenameBytesFrom == that.mRenameBytesFrom && mRenameBytesTo == that.mRenameBytesTo && mRenameBytesReverseOrder == that.mRenameBytesReverseOrder && @@ -242,10 +242,10 @@ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { '}'; } - public static final Creator<BluetoothLEDeviceFilter> CREATOR - = new Creator<BluetoothLEDeviceFilter>() { + public static final Creator<BluetoothLeDeviceFilter> CREATOR + = new Creator<BluetoothLeDeviceFilter>() { @Override - public BluetoothLEDeviceFilter createFromParcel(Parcel in) { + public BluetoothLeDeviceFilter createFromParcel(Parcel in) { Builder builder = new Builder() .setNamePattern(patternFromString(in.readString())) .setScanFilter(in.readParcelable(null)); @@ -273,8 +273,8 @@ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { } @Override - public BluetoothLEDeviceFilter[] newArray(int size) { - return new BluetoothLEDeviceFilter[size]; + public BluetoothLeDeviceFilter[] newArray(int size) { + return new BluetoothLeDeviceFilter[size]; } }; @@ -283,9 +283,9 @@ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { } /** - * Builder for {@link BluetoothLEDeviceFilter} + * Builder for {@link BluetoothLeDeviceFilter} */ - public static final class Builder extends OneTimeUseBuilder<BluetoothLEDeviceFilter> { + public static final class Builder extends OneTimeUseBuilder<BluetoothLeDeviceFilter> { private ScanFilter mScanFilter; private Pattern mNamePattern; private byte[] mRawDataFilter; @@ -418,9 +418,9 @@ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { /** @inheritDoc */ @Override @NonNull - public BluetoothLEDeviceFilter build() { + public BluetoothLeDeviceFilter build() { markUsed(); - return new BluetoothLEDeviceFilter(mNamePattern, mScanFilter, + return new BluetoothLeDeviceFilter(mNamePattern, mScanFilter, mRawDataFilter, mRawDataFilterMask, mRenamePrefix, mRenameSuffix, mRenameBytesFrom, mRenameBytesTo, diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java index 6703bd426282..5bc1f183196d 100644 --- a/core/java/android/content/ClipData.java +++ b/core/java/android/content/ClipData.java @@ -846,7 +846,7 @@ public class ClipData implements Parcelable { * Add a new Item to the overall ClipData container. * <p> This method will <em>not</em> update the list of available MIME types in the * {@link ClipDescription}. It should be used only when adding items which do not add new - * MIME types to this clip. If this is not the case, use {@link #addItem(Item, ContentResolver)} + * MIME types to this clip. If this is not the case, use {@link #addItem(ContentResolver, Item)} * or call {@link #ClipData(CharSequence, String[], Item)} with a complete list of MIME types. * @param item Item to be added. */ @@ -857,15 +857,21 @@ public class ClipData implements Parcelable { mItems.add(item); } + /** @removed use #addItem(ContentResolver, Item) instead */ + @Deprecated + public void addItem(Item item, ContentResolver resolver) { + addItem(resolver, item); + } + /** * Add a new Item to the overall ClipData container. * <p> Unlike {@link #addItem(Item)}, this method will update the list of available MIME types * in the {@link ClipDescription}. - * @param item Item to be added. * @param resolver ContentResolver used to get information about the URI possibly contained in * the item. + * @param item Item to be added. */ - public void addItem(Item item, ContentResolver resolver) { + public void addItem(ContentResolver resolver, Item item) { addItem(item); if (item.getHtmlText() != null) { diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 5f7947fea333..e013662616ed 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1840,6 +1840,14 @@ public class Intent implements Parcelable, Cloneable { public static final String EXTRA_SPLIT_NAME = "android.intent.extra.SPLIT_NAME"; /** + * Intent extra: A {@link ComponentName} value. + * <p> + * Type: String + * </p> + */ + public static final String EXTRA_COMPONENT_NAME = "android.intent.extra.COMPONENT_NAME"; + + /** * Intent extra: An extra for specifying whether a result is needed. * <p> * Type: boolean @@ -3228,6 +3236,7 @@ public class Intent implements Parcelable, Cloneable { * caused the broadcast. * @hide */ + @SystemApi public static final String ACTION_GLOBAL_BUTTON = "android.intent.action.GLOBAL_BUTTON"; /** @@ -4422,6 +4431,21 @@ public class Intent implements Parcelable, Cloneable { public static final String EXTRA_VERSION_CODE = "android.intent.extra.VERSION_CODE"; /** + * The app that triggered the ephemeral installation. + * @hide + */ + public static final String EXTRA_CALLING_PACKAGE + = "android.intent.extra.CALLING_PACKAGE"; + + /** + * Optional calling app provided bundle containing additional launch information the + * installer may use. + * @hide + */ + public static final String EXTRA_VERIFICATION_BUNDLE + = "android.intent.extra.VERIFICATION_BUNDLE"; + + /** * A Bundle forming a mapping of potential target package names to different extras Bundles * to add to the default intent extras in {@link #EXTRA_INTENT} when used with * {@link #ACTION_CHOOSER}. Each key should be a package name. The package need not diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 6c5d26a9706f..06f7916be4b6 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -1205,7 +1205,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { dest.writeInt(largestWidthLimitDp); if (storageUuid != null) { dest.writeInt(1); - dest.writeUuid(storageUuid); + dest.writeLong(storageUuid.getMostSignificantBits()); + dest.writeLong(storageUuid.getLeastSignificantBits()); } else { dest.writeInt(0); } @@ -1271,7 +1272,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { compatibleWidthLimitDp = source.readInt(); largestWidthLimitDp = source.readInt(); if (source.readInt() != 0) { - storageUuid = source.readUuid(); + storageUuid = new UUID(source.readLong(), source.readLong()); volumeUuid = StorageManager.convert(storageUuid); } scanSourceDir = source.readString(); diff --git a/core/java/android/content/pm/InstantAppRequest.java b/core/java/android/content/pm/InstantAppRequest.java index b45169d324be..27d28287b6ae 100644 --- a/core/java/android/content/pm/InstantAppRequest.java +++ b/core/java/android/content/pm/InstantAppRequest.java @@ -17,6 +17,7 @@ package android.content.pm; import android.content.Intent; +import android.os.Bundle; /** * Information needed to make an instant application resolution request. @@ -33,13 +34,18 @@ public final class InstantAppRequest { public final String callingPackage; /** ID of the user requesting the instant application */ public final int userId; + /** + * Optional extra bundle provided by the source application to the installer for additional + * verification. */ + public final Bundle verificationBundle; public InstantAppRequest(AuxiliaryResolveInfo responseObj, Intent origIntent, - String resolvedType, String callingPackage, int userId) { + String resolvedType, String callingPackage, int userId, Bundle verificationBundle) { this.responseObj = responseObj; this.origIntent = origIntent; this.resolvedType = resolvedType; this.callingPackage = callingPackage; this.userId = userId; + this.verificationBundle = verificationBundle; } -}
\ No newline at end of file +} diff --git a/core/java/android/content/pm/InstrumentationInfo.java b/core/java/android/content/pm/InstrumentationInfo.java index f6f1be63baee..3faa9517d17a 100644 --- a/core/java/android/content/pm/InstrumentationInfo.java +++ b/core/java/android/content/pm/InstrumentationInfo.java @@ -19,7 +19,6 @@ package android.content.pm; import android.os.Parcel; import android.os.Parcelable; import android.util.SparseArray; -import android.util.SparseIntArray; /** * Information you can retrieve about a particular piece of test @@ -38,7 +37,7 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable { * runs in the main process of the targetPackage. Can either be a comma-separated list * of process names or '*' for any process that launches to run targetPackage code. */ - public String targetProcess; + public String targetProcesses; /** * Full path to the base APK for this application. @@ -122,7 +121,7 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable { public InstrumentationInfo(InstrumentationInfo orig) { super(orig); targetPackage = orig.targetPackage; - targetProcess = orig.targetProcess; + targetProcesses = orig.targetProcesses; sourceDir = orig.sourceDir; publicSourceDir = orig.publicSourceDir; splitNames = orig.splitNames; @@ -151,7 +150,7 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable { public void writeToParcel(Parcel dest, int parcelableFlags) { super.writeToParcel(dest, parcelableFlags); dest.writeString(targetPackage); - dest.writeString(targetProcess); + dest.writeString(targetProcesses); dest.writeString(sourceDir); dest.writeString(publicSourceDir); dest.writeStringArray(splitNames); @@ -181,7 +180,7 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable { private InstrumentationInfo(Parcel source) { super(source); targetPackage = source.readString(); - targetProcess = source.readString(); + targetProcesses = source.readString(); sourceDir = source.readString(); publicSourceDir = source.readString(); splitNames = source.readStringArray(); diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 7bfde751e155..426f3cf792aa 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -19,6 +19,7 @@ package android.content.pm; import android.content.ComponentName; import android.content.Intent; import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Bundle; import android.util.SparseArray; import java.util.List; @@ -215,11 +216,13 @@ public abstract class PackageManagerInternal { * @param origIntent The original intent that triggered ephemeral resolution * @param resolvedType The resolved type of the intent * @param callingPackage The name of the package requesting the ephemeral application + * @param verificationBundle Optional bundle to pass to the installer for additional + * verification * @param userId The ID of the user that triggered ephemeral resolution */ public abstract void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj, Intent origIntent, String resolvedType, String callingPackage, - int userId); + Bundle verificationBundle, int userId); /** * Grants access to the package metadata for an ephemeral application. @@ -333,4 +336,9 @@ public abstract class PackageManagerInternal { * @param isolatedUid isolated uid that is no longer being used. */ public abstract void removeIsolatedUid(int isolatedUid); + + /** + * Return the taget SDK version for the app with the given UID. + */ + public abstract int getUidTargetSdkVersion(int uid); } diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index e4db0f07b801..766eab9dac4d 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -547,6 +547,8 @@ public class PackageParser { */ public interface Callback { boolean hasFeature(String feature); + String[] getOverlayPaths(String targetPackageName, String targetPath); + String[] getOverlayApks(String targetPackageName); } /** @@ -563,6 +565,14 @@ public class PackageParser { @Override public boolean hasFeature(String feature) { return mPm.hasSystemFeature(feature); } + + @Override public String[] getOverlayPaths(String targetPackageName, String targetPath) { + return null; + } + + @Override public String[] getOverlayApks(String targetPackageName) { + return null; + } } /** @@ -1054,7 +1064,19 @@ public class PackageParser { try { final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath()); - return fromCacheEntry(bytes); + Package p = fromCacheEntry(bytes); + if (mCallback != null) { + String[] overlayApks = mCallback.getOverlayApks(p.packageName); + if (overlayApks != null && overlayApks.length > 0) { + for (String overlayApk : overlayApks) { + // If a static RRO is updated, return null. + if (!isCacheUpToDate(new File(overlayApk), cacheFile)) { + return null; + } + } + } + } + return p; } catch (Exception e) { Slog.w(TAG, "Error reading package cache: ", e); @@ -1238,7 +1260,7 @@ public class PackageParser { parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME); final String[] outError = new String[1]; - final Package pkg = parseBaseApk(res, parser, flags, outError); + final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError); if (pkg == null) { throw new PackageParserException(mParseError, apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]); @@ -1938,6 +1960,7 @@ public class PackageParser { * need to consider whether they should be supported by split APKs and child * packages. * + * @param apkPath The package apk file path * @param res The resources from which to resolve values * @param parser The manifest parser * @param flags Flags how to parse @@ -1947,7 +1970,7 @@ public class PackageParser { * @throws XmlPullParserException * @throws IOException */ - private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags, + private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, IOException { final String splitName; final String pkgName; @@ -1967,6 +1990,15 @@ public class PackageParser { return null; } + if (mCallback != null) { + String[] overlayPaths = mCallback.getOverlayPaths(pkgName, apkPath); + if (overlayPaths != null && overlayPaths.length > 0) { + for (String overlayPath : overlayPaths) { + res.getAssets().addOverlayPath(overlayPath); + } + } + } + final Package pkg = new Package(pkgName); TypedArray sa = res.obtainAttributes(parser, @@ -3268,8 +3300,8 @@ public class PackageParser { a.info.targetPackage = str != null ? str.intern() : null; str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestInstrumentation_targetProcess); - a.info.targetProcess = str != null ? str.intern() : null; + com.android.internal.R.styleable.AndroidManifestInstrumentation_targetProcesses); + a.info.targetProcesses = str != null ? str.intern() : null; a.info.handleProfiling = sa.getBoolean( com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling, @@ -7205,8 +7237,8 @@ public class PackageParser { info.targetPackage = info.targetPackage.intern(); } - if (info.targetProcess != null) { - info.targetProcess = info.targetProcess.intern(); + if (info.targetProcesses != null) { + info.targetProcesses = info.targetProcesses.intern(); } } diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 061346c18bbe..aa35a6610db7 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -189,7 +189,7 @@ public class Camera { * * <p>In {@link android.os.Build.VERSION_CODES#O Android O} this broadcast has been brought * back, but only for <em>registered</em> receivers. Apps that are actively running can - * against listen to the broadcast if they want an immediate clear signal about a picture + * again listen to the broadcast if they want an immediate clear signal about a picture * being taken, however anything doing heavy work (or needing to be launched) as a result of * this should still use JobScheduler.</p> */ @@ -208,12 +208,11 @@ public class Camera { * * <p>In {@link android.os.Build.VERSION_CODES#O Android O} this broadcast has been brought * back, but only for <em>registered</em> receivers. Apps that are actively running can - * against listen to the broadcast if they want an immediate clear signal about a video + * again listen to the broadcast if they want an immediate clear signal about a video * being taken, however anything doing heavy work (or needing to be launched) as a result of * this should still use JobScheduler.</p> */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - @Deprecated public static final String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO"; /** diff --git a/core/java/android/hardware/HardwareBuffer.java b/core/java/android/hardware/HardwareBuffer.java index 9d217d3652a0..7049628b3590 100644 --- a/core/java/android/hardware/HardwareBuffer.java +++ b/core/java/android/hardware/HardwareBuffer.java @@ -70,37 +70,34 @@ public final class HardwareBuffer implements Parcelable, AutoCloseable { /** @hide */ @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = true, value = {USAGE0_CPU_READ, USAGE0_CPU_READ_OFTEN, USAGE0_CPU_WRITE, - USAGE0_CPU_WRITE_OFTEN, USAGE0_GPU_SAMPLED_IMAGE, USAGE0_GPU_COLOR_OUTPUT, - USAGE0_GPU_STORAGE_IMAGE, USAGE0_GPU_CUBEMAP, USAGE0_GPU_DATA_BUFFER, - USAGE0_PROTECTED_CONTENT, USAGE0_SENSOR_DIRECT_DATA, USAGE0_VIDEO_ENCODE}) - public @interface Usage0 {}; - - /** Usage0: the buffer will sometimes be read by the CPU */ - public static final long USAGE0_CPU_READ = (1 << 1); - /** Usage0: the buffer will often be read by the CPU*/ - public static final long USAGE0_CPU_READ_OFTEN = (1 << 2 | USAGE0_CPU_READ); - /** Usage0: the buffer will sometimes be written to by the CPU */ - public static final long USAGE0_CPU_WRITE = (1 << 5); - /** Usage0: the buffer will often be written to by the CPU */ - public static final long USAGE0_CPU_WRITE_OFTEN = (1 << 6 | USAGE0_CPU_WRITE); - /** Usage0: the buffer will be read from by the GPU */ - public static final long USAGE0_GPU_SAMPLED_IMAGE = (1 << 10); - /** Usage0: the buffer will be written to by the GPU */ - public static final long USAGE0_GPU_COLOR_OUTPUT = (1 << 11); - /** Usage0: the buffer will be read from and written to by the GPU */ - public static final long USAGE0_GPU_STORAGE_IMAGE = (USAGE0_GPU_SAMPLED_IMAGE | - USAGE0_GPU_COLOR_OUTPUT); - /** Usage0: the buffer will be used as a cubemap texture */ - public static final long USAGE0_GPU_CUBEMAP = (1 << 13); - /** Usage0: the buffer will be used as a shader storage or uniform buffer object*/ - public static final long USAGE0_GPU_DATA_BUFFER = (1 << 14); - /** Usage0: the buffer must not be used outside of a protected hardware path */ - public static final long USAGE0_PROTECTED_CONTENT = (1 << 18); - /** Usage0: the buffer will be used for sensor direct data */ - public static final long USAGE0_SENSOR_DIRECT_DATA = (1 << 29); - /** Usage0: the buffer will be read by a hardware video encoder */ - public static final long USAGE0_VIDEO_ENCODE = (1 << 21); + @IntDef(flag = true, value = {USAGE_CPU_READ_RARELY, USAGE_CPU_READ_OFTEN, + USAGE_CPU_WRITE_RARELY, USAGE_CPU_WRITE_OFTEN, USAGE_GPU_SAMPLED_IMAGE, + USAGE_GPU_COLOR_OUTPUT, USAGE_PROTECTED_CONTENT, USAGE_VIDEO_ENCODE, + USAGE_GPU_DATA_BUFFER, USAGE_SENSOR_DIRECT_DATA}) + public @interface Usage {}; + + /** Usage: The buffer will sometimes be read by the CPU */ + public static final long USAGE_CPU_READ_RARELY = 2; + /** Usage: The buffer will often be read by the CPU */ + public static final long USAGE_CPU_READ_OFTEN = 3; + + /** Usage: The buffer will sometimes be written to by the CPU */ + public static final long USAGE_CPU_WRITE_RARELY = 2 << 4; + /** Usage: The buffer will often be written to by the CPU */ + public static final long USAGE_CPU_WRITE_OFTEN = 3 << 4; + + /** Usage: The buffer will be read from by the GPU */ + public static final long USAGE_GPU_SAMPLED_IMAGE = 1 << 8; + /** Usage: The buffer will be written to by the GPU */ + public static final long USAGE_GPU_COLOR_OUTPUT = 1 << 9; + /** Usage: The buffer must not be used outside of a protected hardware path */ + public static final long USAGE_PROTECTED_CONTENT = 1 << 14; + /** Usage: The buffer will be read by a hardware video encoder */ + public static final long USAGE_VIDEO_ENCODE = 1 << 16; + /** Usage: The buffer will be used for sensor direct data */ + public static final long USAGE_SENSOR_DIRECT_DATA = 1 << 23; + /** Usage: The buffer will be used as a shader storage or uniform buffer object */ + public static final long USAGE_GPU_DATA_BUFFER = 1 << 24; // The approximate size of a native AHardwareBuffer object. private static final long NATIVE_HARDWARE_BUFFER_SIZE = 232; @@ -116,13 +113,11 @@ public final class HardwareBuffer implements Parcelable, AutoCloseable { * {@link #RGBX_8888}, {@link #RGB_565}, {@link #RGB_888}, {@link #RGBA_1010102}, {@link #BLOB} * @param layers The number of layers in the buffer * @param usage Flags describing how the buffer will be used, one of - * {@link #USAGE0_CPU_READ}, {@link #USAGE0_CPU_READ_OFTEN}, {@link #USAGE0_CPU_WRITE}, - * {@link #USAGE0_CPU_WRITE_OFTEN}, {@link #USAGE0_GPU_SAMPLED_IMAGE}, - * {@link #USAGE0_GPU_COLOR_OUTPUT},{@link #USAGE0_GPU_STORAGE_IMAGE}, - * {@link #USAGE0_GPU_CUBEMAP}, {@link #USAGE0_GPU_DATA_BUFFER}, - * {@link #USAGE0_PROTECTED_CONTENT}, {@link #USAGE0_SENSOR_DIRECT_DATA}, - * {@link #USAGE0_VIDEO_ENCODE} - * + * {@link #USAGE_CPU_READ_RARELY}, {@link #USAGE_CPU_READ_OFTEN}, + * {@link #USAGE_CPU_WRITE_RARELY}, {@link #USAGE_CPU_WRITE_OFTEN}, + * {@link #USAGE_GPU_SAMPLED_IMAGE}, {@link #USAGE_GPU_COLOR_OUTPUT}, + * {@link #USAGE_GPU_DATA_BUFFER}, {@link #USAGE_PROTECTED_CONTENT}, + * {@link #USAGE_SENSOR_DIRECT_DATA}, {@link #USAGE_VIDEO_ENCODE} * @return A <code>HardwareBuffer</code> instance if successful, or throws an * IllegalArgumentException if the dimensions passed are invalid (either zero, negative, or * too large to allocate), if the format is not supported, if the requested number of layers @@ -130,7 +125,7 @@ public final class HardwareBuffer implements Parcelable, AutoCloseable { */ @NonNull public static HardwareBuffer create(int width, int height, @Format int format, int layers, - @Usage0 long usage) { + @Usage long usage) { if (!HardwareBuffer.isSupportedFormat(format)) { throw new IllegalArgumentException("Invalid pixel format " + format); } diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java index 80cbde75efd2..0dab5d7b1453 100644 --- a/core/java/android/hardware/SystemSensorManager.java +++ b/core/java/android/hardware/SystemSensorManager.java @@ -589,9 +589,9 @@ public class SystemSensorManager extends SensorManager { "Width if HaradwareBuffer must be greater than " + MIN_DIRECT_CHANNEL_BUFFER_SIZE); } - if ((hardwareBuffer.getUsage() & HardwareBuffer.USAGE0_SENSOR_DIRECT_DATA) == 0) { + if ((hardwareBuffer.getUsage() & HardwareBuffer.USAGE_SENSOR_DIRECT_DATA) == 0) { throw new IllegalArgumentException( - "HardwareBuffer must set usage flag USAGE0_SENSOR_DIRECT_DATA"); + "HardwareBuffer must set usage flag USAGE_SENSOR_DIRECT_DATA"); } size = hardwareBuffer.getWidth(); id = nativeCreateDirectChannel( diff --git a/core/java/android/metrics/LogMaker.java b/core/java/android/metrics/LogMaker.java index 3c6baa76558a..2bb43bd36be3 100644 --- a/core/java/android/metrics/LogMaker.java +++ b/core/java/android/metrics/LogMaker.java @@ -170,6 +170,27 @@ public class LogMaker { } /** + * This will be set by the system when the log is persisted. + * Client-supplied values will be ignored. + * + * @param uid to replace the existing setting. + * @hide + */ + public LogMaker setUid(int uid) { + entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_UID, uid); + return this; + } + + /** + * Remove the UID property. + * @hide + */ + public LogMaker clearUid() { + entries.remove(MetricsEvent.RESERVED_FOR_LOGBUILDER_UID); + return this; + } + + /** * The name of the counter or histogram. * Only useful for counter or histogram category objects. * @param name to replace the existing setting. @@ -319,6 +340,16 @@ public class LogMaker { } } + /** @return the UID of the log, or -1. */ + public int getUid() { + Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_UID); + 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); diff --git a/core/java/android/metrics/MetricsReader.java b/core/java/android/metrics/MetricsReader.java index 5be977ae183d..5f356ca00d88 100644 --- a/core/java/android/metrics/MetricsReader.java +++ b/core/java/android/metrics/MetricsReader.java @@ -93,6 +93,7 @@ public class MetricsReader { } final LogMaker log = new LogMaker(objects) .setTimestamp(eventTimestampMs) + .setUid(event.getUid()) .setProcessId(event.getProcessId()); if (log.getCategory() == MetricsEvent.METRICS_CHECKPOINT) { if (log.getSubtype() == mCheckpointTag) { @@ -155,11 +156,13 @@ public class MetricsReader { public static class Event { long mTimeMillis; int mPid; + int mUid; Object mData; - public Event(long timeMillis, int pid, Object data) { + public Event(long timeMillis, int pid, int uid, Object data) { mTimeMillis = timeMillis; mPid = pid; + mUid = uid; mData = data; } @@ -167,6 +170,7 @@ public class MetricsReader { mTimeMillis = TimeUnit.MILLISECONDS.convert( nativeEvent.getTimeNanos(), TimeUnit.NANOSECONDS); mPid = nativeEvent.getProcessId(); + mUid = nativeEvent.getUid(); mData = nativeEvent.getData(); } @@ -178,6 +182,10 @@ public class MetricsReader { return mPid; } + public int getUid() { + return mUid; + } + public Object getData() { return mData; } diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index b854cbf2d0f8..2f2e79af57d4 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -2974,11 +2974,6 @@ public class ConnectivityManager { } /** - * Note: this is a deprecated version of - * {@link #requestNetwork(NetworkRequest, int, NetworkCallback)} - please transition code to use - * the unhidden version of the function. - * TODO: replace all callers with the new version of the API - * * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited * by a timeout. * @@ -2991,7 +2986,7 @@ public class ConnectivityManager { * request that timed out is not an error. * * <p>Do not use this method to poll for the existence of specific networks (e.g. with a small - * timeout) - the {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)} is provided + * timeout) - {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)} is provided * for that purpose. Calling this method will attempt to bring up the requested network. * * <p>This method requires the caller to hold either the @@ -3000,13 +2995,11 @@ public class ConnectivityManager { * {@link android.provider.Settings.System#canWrite}.</p> * * @param request {@link NetworkRequest} describing this request. - * @param networkCallback The callbacks to be utilized for this request. Note - * the callbacks must not be shared - they uniquely specify - * this request. + * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note + * the callback must not be shared - it uniquely specifies this request. * @param timeoutMs The time in milliseconds to attempt looking for a suitable network * before {@link NetworkCallback#onUnavailable()} is called. The timeout must * be a positive value (i.e. >0). - * @hide */ public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback, int timeoutMs) { @@ -3017,43 +3010,6 @@ public class ConnectivityManager { requestNetwork(request, networkCallback, timeoutMs, legacyType, getDefaultHandler()); } - /** - * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited - * by a timeout. - * - * This function behaves identically to the non-timed-out version - * {@link #requestNetwork(NetworkRequest, NetworkCallback)}, but if a suitable network - * is not found within the given time (in milliseconds) the - * {@link NetworkCallback#onUnavailable()} callback is called. The request can still be - * released normally by calling {@link #unregisterNetworkCallback(NetworkCallback)} but does - * not have to be released if timed-out (it is automatically released). Unregistering a - * request that timed out is not an error. - * - * <p>Do not use this method to poll for the existence of specific networks (e.g. with a small - * timeout) - {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)} is provided - * for that purpose. Calling this method will attempt to bring up the requested network. - * - * <p>This method requires the caller to hold either the - * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission - * or the ability to modify system settings as determined by - * {@link android.provider.Settings.System#canWrite}.</p> - * - * @param request {@link NetworkRequest} describing this request. - * @param timeoutMs The time in milliseconds to attempt looking for a suitable network - * before {@link NetworkCallback#onUnavailable()} is called. The timeout must - * be a positive value (i.e. >0). - * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note - * the callback must not be shared - it uniquely specifies this request. - */ - public void requestNetwork(NetworkRequest request, int timeoutMs, - NetworkCallback networkCallback) { - if (timeoutMs <= 0) { - throw new IllegalArgumentException("Non-positive timeoutMs: " + timeoutMs); - } - int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities); - requestNetwork(request, networkCallback, timeoutMs, legacyType, getDefaultHandler()); - } - /** * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited @@ -3076,14 +3032,14 @@ public class ConnectivityManager { * {@link android.provider.Settings.System#canWrite}.</p> * * @param request {@link NetworkRequest} describing this request. - * @param timeoutMs The time in milliseconds to attempt looking for a suitable network - * before {@link NetworkCallback#onUnavailable} is called. * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note * the callback must not be shared - it uniquely specifies this request. * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. + * @param timeoutMs The time in milliseconds to attempt looking for a suitable network + * before {@link NetworkCallback#onUnavailable} is called. */ - public void requestNetwork(NetworkRequest request, int timeoutMs, - NetworkCallback networkCallback, Handler handler) { + public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback, + Handler handler, int timeoutMs) { if (timeoutMs <= 0) { throw new IllegalArgumentException("Non-positive timeoutMs"); } @@ -3402,8 +3358,8 @@ public class ConnectivityManager { /** * It is acceptable to briefly use multipath data to provide seamless connectivity for * time-sensitive user-facing operations when the system default network is temporarily - * unresponsive. The amount of data should be limited (less than one megabyte), and the - * operation should be infrequent to ensure that data usage is limited. + * unresponsive. The amount of data should be limited (less than one megabyte for every call to + * this method), and the operation should be infrequent to ensure that data usage is limited. * * An example of such an operation might be a time-sensitive foreground activity, such as a * voice command, that the user is performing while walking out of range of a Wi-Fi network. diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java index 167c46d6ded0..9b5ff29d592e 100644 --- a/core/java/android/os/Bundle.java +++ b/core/java/android/os/Bundle.java @@ -25,7 +25,6 @@ import android.util.SparseArray; import java.io.Serializable; import java.util.ArrayList; import java.util.List; -import java.util.UUID; /** * A mapping from String keys to various {@link Parcelable} values. @@ -477,18 +476,6 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { } /** - * Inserts a UUID value into the mapping of this Bundle, replacing - * any existing value for the given key. Either key or value may be null. - * - * @param key a String, or null - * @param value a UUID object, or null - */ - public void putUuid(@Nullable String key, @Nullable UUID value) { - unparcel(); - mMap.put(key, value); - } - - /** * Inserts an array of Parcelable values into the mapping of this Bundle, * replacing any existing value for the given key. Either key or value may * be null. @@ -871,26 +858,6 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { * value is explicitly associated with the key. * * @param key a String, or null - * @return a UUID value, or null - */ - @Nullable - public UUID getUuid(@Nullable String key) { - unparcel(); - final Object o = mMap.get(key); - try { - return (UUID) o; - } catch (ClassCastException e) { - typeWarning(key, o, "UUID", e); - return null; - } - } - - /** - * Returns the value associated with the given key, or null if - * no mapping of the desired type exists for the given key or a null - * value is explicitly associated with the key. - * - * @param key a String, or null * @return a Bundle value, or null */ @Nullable diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index c1647c74f363..28bdacfaea9c 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -50,7 +50,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.UUID; /** * Container for a message (data and object references) that can @@ -242,7 +241,6 @@ public final class Parcel { private static final int VAL_SIZE = 26; private static final int VAL_SIZEF = 27; private static final int VAL_DOUBLEARRAY = 28; - private static final int VAL_UUID = 29; // The initial int32 in a Binder call's reply Parcel header: // Keep these in sync with libbinder's binder/Status.h. @@ -831,15 +829,6 @@ public final class Parcel { } /** - * Flatten a UUID into the parcel at the current dataPosition(), - * growing dataCapacity() if needed. - */ - public final void writeUuid(UUID val) { - writeLong(val.getMostSignificantBits()); - writeLong(val.getLeastSignificantBits()); - } - - /** * Flatten a List into the parcel at the current dataPosition(), growing * dataCapacity() if needed. The List values are written using * {@link #writeValue} and must follow the specification there. @@ -1687,9 +1676,6 @@ public final class Parcel { } else if (v instanceof double[]) { writeInt(VAL_DOUBLEARRAY); writeDoubleArray((double[]) v); - } else if (v instanceof UUID) { - writeInt(VAL_UUID); - writeUuid((UUID) v); } else { Class<?> clazz = v.getClass(); if (clazz.isArray() && clazz.getComponentType() == Object.class) { @@ -2194,13 +2180,6 @@ public final class Parcel { } /** - * Read a UUID from the parcel at the current dataPosition(). - */ - public final UUID readUuid() { - return new UUID(readLong(), readLong()); - } - - /** * Read and return a byte[] object from the parcel. */ public final byte[] createByteArray() { @@ -2750,9 +2729,6 @@ public final class Parcel { case VAL_DOUBLEARRAY: return createDoubleArray(); - case VAL_UUID: - return readUuid(); - default: int off = dataPosition() - 4; throw new RuntimeException( diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index f95a34cd7ec8..52b2f52c452e 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -64,7 +64,7 @@ import java.util.List; */ public class UserManager { - private static String TAG = "UserManager"; + private static final String TAG = "UserManager"; private final IUserManager mService; private final Context mContext; @@ -218,6 +218,23 @@ public class UserManager { public static final String DISALLOW_BLUETOOTH = "no_bluetooth"; /** + * Specifies if outgoing bluetooth sharing is disallowed on the device. Device owner and profile + * owner can set this restriction. When it is set by device owner, all users on this device will + * be affected. + * + * <p>Default is <code>true</code> for managed profiles and false for otherwise. When a device + * upgrades to {@link android.os.Build.VERSION_CODES#O}, the system sets it for all existing + * managed profiles. + * + * <p>Key for user restrictions. + * <p>Type: Boolean + * @see DevicePolicyManager#addUserRestriction(ComponentName, String) + * @see DevicePolicyManager#clearUserRestriction(ComponentName, String) + * @see #getUserRestrictions() + */ + public static final String DISALLOW_BLUETOOTH_SHARING = "no_bluetooth_sharing"; + + /** * Specifies if a user is disallowed from transferring files over * USB. This can only be set by device owners and profile owners on the primary user. * The default value is <code>false</code>. diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index baa29b078dd8..bd43d6a3c218 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -19,14 +19,18 @@ package android.os.storage; import static android.net.TrafficStats.GB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; +import android.annotation.BytesLong; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; +import android.annotation.SystemApi; +import android.annotation.WorkerThread; import android.app.ActivityThread; import android.content.ContentResolver; import android.content.Context; +import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageMoveObserver; import android.content.pm.PackageManager; @@ -135,6 +139,7 @@ public class StorageManager { * thus it cannot be used to uniquely identify a particular physical device. * * @see #getUuidForPath(File) + * @see ApplicationInfo#storageUuid */ public static final UUID UUID_DEFAULT = UUID .fromString("41217664-9172-527a-b3d5-edabb50a7d69"); @@ -166,6 +171,7 @@ public class StorageManager { * @see #ACTION_MANAGE_STORAGE * @see #UUID_DEFAULT * @see #getUuidForPath(File) + * @see Intent#putExtra(String, java.io.Serializable) */ public static final String EXTRA_UUID = "android.os.storage.extra.UUID"; @@ -1414,6 +1420,7 @@ public class StorageManager { public @NonNull ParcelFileDescriptor openProxyFileDescriptor( int mode, ProxyFileDescriptorCallback callback, Handler handler, ThreadFactory factory) throws IOException { + Preconditions.checkNotNull(callback); MetricsLogger.count(mContext, "storage_open_proxy_file_descriptor", 1); // Retry is needed because the mount point mFuseAppLoop is using may be unmounted before // invoking StorageManagerService#openProxyFileDescriptor. In this case, we need to re-mount @@ -1460,19 +1467,7 @@ public class StorageManager { } } - /** - * Opens seekable ParcelFileDescriptor that routes file operation requests to - * ProxyFileDescriptorCallback. - * - * @param mode The desired access mode, must be one of - * {@link ParcelFileDescriptor#MODE_READ_ONLY}, - * {@link ParcelFileDescriptor#MODE_WRITE_ONLY}, or - * {@link ParcelFileDescriptor#MODE_READ_WRITE} - * @param callback Callback to process file operation requests issued on returned file - * descriptor. - * @return Seekable ParcelFileDescriptor. - * @throws IOException - */ + /** {@hide} */ public @NonNull ParcelFileDescriptor openProxyFileDescriptor( int mode, ProxyFileDescriptorCallback callback) throws IOException { @@ -1496,6 +1491,7 @@ public class StorageManager { public @NonNull ParcelFileDescriptor openProxyFileDescriptor( int mode, ProxyFileDescriptorCallback callback, Handler handler) throws IOException { + Preconditions.checkNotNull(handler); return openProxyFileDescriptor(mode, callback, handler, null); } @@ -1533,7 +1529,8 @@ public class StorageManager { * doesn't support cache quotas. * @see #getCacheSizeBytes(UUID) */ - public long getCacheQuotaBytes(@NonNull UUID storageUuid) throws IOException { + @WorkerThread + public @BytesLong long getCacheQuotaBytes(@NonNull UUID storageUuid) throws IOException { try { final ApplicationInfo app = mContext.getApplicationInfo(); return mStorageManager.getCacheQuotaBytes(convert(storageUuid), app.uid); @@ -1573,7 +1570,8 @@ public class StorageManager { * doesn't support cache quotas. * @see #getCacheQuotaBytes(UUID) */ - public long getCacheSizeBytes(@NonNull UUID storageUuid) throws IOException { + @WorkerThread + public @BytesLong long getCacheSizeBytes(@NonNull UUID storageUuid) throws IOException { try { final ApplicationInfo app = mContext.getApplicationInfo(); return mStorageManager.getCacheSizeBytes(convert(storageUuid), app.uid); @@ -1631,8 +1629,10 @@ public class StorageManager { * @see #getAllocatableBytes(UUID, int) * @see #allocateBytes(UUID, long, int) * @see #allocateBytes(FileDescriptor, long, int) + * @hide */ @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE) + @SystemApi public static final int FLAG_ALLOCATE_AGGRESSIVE = 1; /** @hide */ @@ -1656,7 +1656,7 @@ public class StorageManager { * the returned value will fail. * <p> * If the returned value is not large enough for the data you'd like to - * store, you can launch {@link #ACTION_MANAGE_STORAGE} with the + * persist, you can launch {@link #ACTION_MANAGE_STORAGE} with the * {@link #EXTRA_UUID} and {@link #EXTRA_REQUESTED_BYTES} options to help * involve the user in freeing up disk space. * <p class="note"> @@ -1670,13 +1670,19 @@ public class StorageManager { * vary widely depending on the underlying storage device. The * UUID for a specific path can be obtained using * {@link #getUuidForPath(File)}. - * @param flags to apply to the request. * @return the maximum number of new bytes that the calling app can allocate * using {@link #allocateBytes(UUID, long, int)} or * {@link #allocateBytes(FileDescriptor, long, int)}. * @throws IOException when the storage device isn't present, or when it * doesn't support allocating space. */ + public @BytesLong long getAllocatableBytes(@NonNull UUID storageUuid) + throws IOException { + return getAllocatableBytes(storageUuid, 0); + } + + /** @hide */ + @SystemApi public long getAllocatableBytes(@NonNull UUID storageUuid, @AllocateFlags int flags) throws IOException { try { @@ -1713,14 +1719,20 @@ public class StorageManager { * allocate disk space. The UUID for a specific path can be * obtained using {@link #getUuidForPath(File)}. * @param bytes the number of bytes to allocate. - * @param flags to apply to the request. * @throws IOException when the storage device isn't present, or when it * doesn't support allocating space, or if the device had * trouble allocating the requested space. * @see #getAllocatableBytes(UUID, int) */ - public void allocateBytes(@NonNull UUID storageUuid, long bytes, @AllocateFlags int flags) + public void allocateBytes(@NonNull UUID storageUuid, @BytesLong long bytes) throws IOException { + allocateBytes(storageUuid, bytes, 0); + } + + /** @hide */ + @SystemApi + public void allocateBytes(@NonNull UUID storageUuid, @BytesLong long bytes, + @AllocateFlags int flags) throws IOException { try { mStorageManager.allocateBytes(convert(storageUuid), bytes, flags); } catch (ParcelableException e) { @@ -1732,7 +1744,7 @@ public class StorageManager { /** @removed */ @Deprecated - public void allocateBytes(@NonNull File path, long bytes, @AllocateFlags int flags) + public void allocateBytes(@NonNull File path, @BytesLong long bytes, @AllocateFlags int flags) throws IOException { allocateBytes(getUuidForPath(path), bytes, flags); } @@ -1756,14 +1768,19 @@ public class StorageManager { * requested size, it will be extended without modifying any * existing contents. If the open file is larger than this * requested size, it will be truncated. - * @param flags to apply to the request. * @throws IOException when the storage device isn't present, or when it * doesn't support allocating space, or if the device had * trouble allocating the requested space. * @see #getAllocatableBytes(UUID, int) * @see Environment#isExternalStorageEmulated(File) */ - public void allocateBytes(FileDescriptor fd, long bytes, @AllocateFlags int flags) + public void allocateBytes(FileDescriptor fd, @BytesLong long bytes) throws IOException { + allocateBytes(fd, bytes, 0); + } + + /** @hide */ + @SystemApi + public void allocateBytes(FileDescriptor fd, @BytesLong long bytes, @AllocateFlags int flags) throws IOException { final File file = ParcelFileDescriptor.getFile(fd); for (int i = 0; i < 3; i++) { diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java index 6c038c787d59..1013b0f0af23 100644 --- a/core/java/android/provider/FontsContract.java +++ b/core/java/android/provider/FontsContract.java @@ -607,43 +607,6 @@ public class FontsContract { } /** - * Build a Typeface from an array of {@link FontInfo}. Results that are marked as not ready - * will be skipped. - * - * @param context A {@link Context} that will be used to fetch the font contents. - * @param cancellationSignal A signal to cancel the operation in progress, or null if none. If - * the operation is canceled, then {@link - * android.os.OperationCanceledException} will be thrown. - * @param fonts An array of {@link FontInfo} to be used to create a Typeface. - * @param weight A weight value to be used for selecting a font from a font family. - * @param italic {@code true} if this font is of italic style. This will be used for font - * selection from a font family. - * @param fallbackFontName A fallback font name used if this method fails to create the - * Typeface. By passing {@code null}, this method returns {@code null} - * if typeface creation fails. - * @return A Typeface object. May return {@code null} if that is the value passed to {@code - * fallBackFontName}. - */ - public static Typeface buildTypeface(@NonNull Context context, - @Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts, - int weight, boolean italic, @Nullable String fallbackFontName) { - if (context.isRestricted()) { - // TODO: Should we allow if the peer process is system or myself? - return null; - } - final Map<Uri, ByteBuffer> uriBuffer = - prepareFontData(context, fonts, cancellationSignal); - if (uriBuffer.isEmpty()) { - return null; - } - return new Typeface.Builder(fonts, uriBuffer) - .setFallback(fallbackFontName) - .setWeight(weight) - .setItalic(italic) - .build(); - } - - /** * Build a Typeface from an array of {@link FontInfo} * * Results that are marked as not ready will be skipped. diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index cbd41c365188..78a7ea31183d 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -7065,6 +7065,12 @@ public final class Settings { INSTANT_APP_SETTINGS.add(ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR); INSTANT_APP_SETTINGS.add(ACCESSIBILITY_CAPTIONING_TYPEFACE); INSTANT_APP_SETTINGS.add(ACCESSIBILITY_CAPTIONING_FONT_SCALE); + INSTANT_APP_SETTINGS.add(ACCESSIBILITY_CAPTIONING_WINDOW_COLOR); + INSTANT_APP_SETTINGS.add(ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED); + INSTANT_APP_SETTINGS.add(ACCESSIBILITY_DISPLAY_DALTONIZER); + INSTANT_APP_SETTINGS.add(ACCESSIBILITY_AUTOCLICK_DELAY); + INSTANT_APP_SETTINGS.add(ACCESSIBILITY_AUTOCLICK_ENABLED); + INSTANT_APP_SETTINGS.add(ACCESSIBILITY_LARGE_POINTER_ICON); INSTANT_APP_SETTINGS.add(DEFAULT_INPUT_METHOD); INSTANT_APP_SETTINGS.add(ENABLED_INPUT_METHODS); @@ -7711,13 +7717,36 @@ public final class Settings { "location_background_throttle_interval_ms"; /** + * Most frequent location update interval in milliseconds that proximity alert is allowed + * to request. + * @hide + */ + public static final String LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS = + "location_background_throttle_proximity_alert_interval_ms"; + + /** * Packages that are whitelisted for background throttling (throttling will not be applied). * @hide */ public static final String LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST = "location_background_throttle_package_whitelist"; - /** + /** + * The interval in milliseconds at which wifi scan requests will be throttled when they are + * coming from the background. + * @hide + */ + public static final String WIFI_SCAN_BACKGROUND_THROTTLE_INTERVAL_MS = + "wifi_scan_background_throttle_interval_ms"; + + /** + * Packages that are whitelisted to be exempt for wifi background throttling. + * @hide + */ + public static final String WIFI_SCAN_BACKGROUND_THROTTLE_PACKAGE_WHITELIST = + "wifi_scan_background_throttle_package_whitelist"; + + /** * Whether TV will switch to MHL port when a mobile device is plugged in. * (0 = false, 1 = true) * @hide diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java index e04fae7bc2b5..69f3f6723244 100644 --- a/core/java/android/service/autofill/Dataset.java +++ b/core/java/android/service/autofill/Dataset.java @@ -16,7 +16,7 @@ package android.service.autofill; -import static android.view.autofill.Helper.DEBUG; +import static android.view.autofill.Helper.sDebug; import android.annotation.NonNull; import android.annotation.Nullable; @@ -24,7 +24,6 @@ import android.content.IntentSender; import android.os.Parcel; import android.os.Parcelable; import android.view.autofill.AutofillId; -import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; import android.widget.RemoteViews; import com.android.internal.util.Preconditions; @@ -90,7 +89,7 @@ public final class Dataset implements Parcelable { @Override public String toString() { - if (!DEBUG) return super.toString(); + if (!sDebug) return super.toString(); return new StringBuilder("Dataset " + mId + " [") .append("fieldIds=").append(mFieldIds) diff --git a/core/java/android/service/autofill/FillContext.java b/core/java/android/service/autofill/FillContext.java index 8a28c45d145f..d6616bfb8d66 100644 --- a/core/java/android/service/autofill/FillContext.java +++ b/core/java/android/service/autofill/FillContext.java @@ -16,7 +16,7 @@ package android.service.autofill; -import static android.view.autofill.Helper.DEBUG; +import static android.view.autofill.Helper.sDebug; import android.annotation.NonNull; import android.app.assist.AssistStructure; @@ -74,11 +74,9 @@ public final class FillContext implements Parcelable { @Override public String toString() { - if (!DEBUG) { - return super.toString(); - } else { - return "FillContext [mRequestId=" + mRequestId + "]"; - } + if (!sDebug) return super.toString(); + + return "FillContext [reqId=" + mRequestId + "]"; } @Override diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java index 5c8f3cec9c59..42c0151298b0 100644 --- a/core/java/android/service/autofill/FillResponse.java +++ b/core/java/android/service/autofill/FillResponse.java @@ -17,7 +17,7 @@ package android.service.autofill; import static android.service.autofill.FillRequest.INVALID_REQUEST_ID; -import static android.view.autofill.Helper.DEBUG; +import static android.view.autofill.Helper.sDebug; import android.annotation.NonNull; import android.annotation.Nullable; @@ -394,7 +394,7 @@ public final class FillResponse implements Parcelable { ///////////////////////////////////// @Override public String toString() { - if (!DEBUG) return super.toString(); + if (!sDebug) return super.toString(); return new StringBuilder( "FillResponse : [mRequestId=" + mRequestId) diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java index 94e5e3ec0d50..277c6223985b 100644 --- a/core/java/android/service/autofill/SaveInfo.java +++ b/core/java/android/service/autofill/SaveInfo.java @@ -16,7 +16,7 @@ package android.service.autofill; -import static android.view.autofill.Helper.DEBUG; +import static android.view.autofill.Helper.sDebug; import android.annotation.IntDef; import android.annotation.NonNull; @@ -387,7 +387,7 @@ public final class SaveInfo implements Parcelable { ///////////////////////////////////// @Override public String toString() { - if (!DEBUG) return super.toString(); + if (!sDebug) return super.toString(); return new StringBuilder("SaveInfo: [type=") .append(DebugUtils.flagsToString(SaveInfo.class, "SAVE_DATA_TYPE_", mType)) diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index 00bd30456c9e..76c96bd41475 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -1094,9 +1094,9 @@ public abstract class NotificationListenerService extends Service { /** * Request that the service be unbound. * - * <p>This will no longer receive updates until - * {@link #requestRebind(ComponentName)} is called. - * The service will likely be kiled by the system after this call. + * <p>Once this is called, you will no longer receive updates and no method calls are + * guaranteed to be successful, until you next receive the {@link #onListenerConnected()} event. + * The service will likely be killed by the system after this call. * * <p>The service should wait for the {@link #onListenerConnected()} event * before performing this operation. I know it's tempting, but you must wait. diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java index 56b267fb2c9d..c35423fb09c6 100644 --- a/core/java/android/service/quicksettings/TileService.java +++ b/core/java/android/service/quicksettings/TileService.java @@ -80,8 +80,13 @@ import com.android.internal.R; public class TileService extends Service { /** - * An activity that provides a user interface for adjusting TileService preferences. - * Optional but recommended for apps that implement a TileService. + * An activity that provides a user interface for adjusting TileService + * preferences. Optional but recommended for apps that implement a + * TileService. + * <p> + * This intent may also define a {@link Intent#EXTRA_COMPONENT_NAME} value + * to indicate the {@link ComponentName} that caused the preferences to be + * opened. */ @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String ACTION_QS_TILE_PREFERENCES @@ -130,13 +135,6 @@ public class TileService extends Service { public static final String EXTRA_TOKEN = "token"; /** - * May be included when {@link #ACTION_QS_TILE_PREFERENCES} is launched from a tile. - * This extra may contain the {@link ComponentName} of the tile that triggered - * the preferences to be opened. - */ - public static final String EXTRA_COMPONENT = "android.service.quicksettings.extra.COMPONENT"; - - /** * @hide */ public static final String EXTRA_STATE = "state"; @@ -445,7 +443,7 @@ public class TileService extends Service { */ public static final void requestListeningState(Context context, ComponentName component) { Intent intent = new Intent(ACTION_REQUEST_LISTENING); - intent.putExtra(EXTRA_COMPONENT, component); + intent.putExtra(Intent.EXTRA_COMPONENT_NAME, component); intent.setPackage("com.android.systemui"); context.sendBroadcast(intent, Manifest.permission.BIND_QUICK_SETTINGS_TILE); } diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 98780a7d73d5..6bbb0ff9861b 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -16,8 +16,6 @@ package android.service.wallpaper; -import android.annotation.Nullable; -import android.app.WallpaperColors; import android.content.res.TypedArray; import android.graphics.Canvas; import android.util.MergedConfiguration; @@ -544,24 +542,6 @@ public abstract class WallpaperService extends Service { */ public void onSurfaceDestroyed(SurfaceHolder holder) { } - - /** - * Notifies the engine that wallpaper colors changed significantly. - * This will trigger a {@link #onComputeWallpaperColors()} call. - */ - public void invalidateColors() { - } - - /** - * Notifies the system about what colors the wallpaper is using. - * You might return null if no color information is available at the moment. In that case - * you might want to call {@link #invalidateColors()} in a near future. - * - * @return List of wallpaper colors and their weights. - */ - public @Nullable WallpaperColors onComputeWallpaperColors() { - return null; - } protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) { out.print(prefix); out.print("mInitializing="); out.print(mInitializing); diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java index 6d4281b9e0f7..92f218b4155a 100644 --- a/core/java/android/util/EventLog.java +++ b/core/java/android/util/EventLog.java @@ -68,6 +68,7 @@ public class EventLog { private static final int THREAD_OFFSET = 8; private static final int SECONDS_OFFSET = 12; private static final int NANOSECONDS_OFFSET = 16; + private static final int UID_OFFSET = 24; // Layout for event log v1 format, v2 and v3 use HEADER_SIZE_OFFSET private static final int V1_PAYLOAD_START = 20; @@ -91,6 +92,20 @@ public class EventLog { return mBuffer.getInt(PROCESS_OFFSET); } + /** + * @return the UID which wrote the log entry + * @hide + */ + @SystemApi + public int getUid() { + try { + return mBuffer.getInt(UID_OFFSET); + } catch (IndexOutOfBoundsException e) { + // buffer won't contain the UID if the caller doesn't have permission. + return -1; + } + } + /** @return the thread ID which wrote the log entry */ public int getThreadId() { return mBuffer.getInt(THREAD_OFFSET); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index a18381b9b425..4029a42554db 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -1173,6 +1173,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8; + /** @hide */ + @IntDef( + flag = true, + value = {AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS}) + @Retention(RetentionPolicy.SOURCE) + public @interface AutofillFlags {} + + /** + * Flag requesting you to add views not-important for autofill to the assist data. + */ + public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1; + /** * This view is enabled. Interpretation varies by subclass. * Use with ENABLED_MASK when calling setFlags. @@ -2745,8 +2757,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * 1 PFLAG3_IS_AUTOFILLED * 1 PFLAG3_FINGER_DOWN * 1 PFLAG3_FOCUSED_BY_DEFAULT - * __ unused - * 11 PFLAG3_IMPORTANT_FOR_AUTOFILL + * 1111 PFLAG3_IMPORTANT_FOR_AUTOFILL * 1 PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE * 1 PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED * 1 PFLAG3_TEMPORARY_DETACH @@ -2978,14 +2989,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * Shift for the bits in {@link #mPrivateFlags3} related to the * "importantForAutofill" attribute. */ - static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 21; + static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19; /** * Mask for obtaining the bits which specify how to determine * whether a view is important for autofill. */ static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO - | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO) + | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO + | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS + | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS) << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT; /** @@ -7292,7 +7305,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * * @param structure Fill in with structured view data. The default implementation * fills in all data that can be inferred from the view itself. - * @param flags optional flags (currently {@code 0}). + * @param flags optional flags. + * + * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS */ public void onProvideAutofillStructure(ViewStructure structure, int flags) { onProvideStructureForAssistOrAutofill(structure, true); @@ -7546,6 +7561,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Sets the mode for determining whether this View is important for autofill. * + * <p>This property controls how this view is presented to the autofill components + * which help users to fill credentials, addresses, etc. For example, views + * that contain labels and input fields are useful for autofill components to + * determine the user context and provide values for the inputs. Note that the + * user can always override this by manually triggering autotill which would + * expose the view to the autofill provider. + * + * <p>The platform determines the importance for autofill automatically but you + * can use this method to customize the behavior. See the autofill modes below + * for more details. + * * <p>See {@link #setImportantForAutofill(int)} for more info about this mode. * * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES}, @@ -7599,24 +7625,40 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * * @return whether the view is considered important for autofill. * + * @see #setImportantForAutofill(int) * @see #IMPORTANT_FOR_AUTOFILL_AUTO * @see #IMPORTANT_FOR_AUTOFILL_YES * @see #IMPORTANT_FOR_AUTOFILL_NO + * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS + * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS */ public final boolean isImportantForAutofill() { - final int flag = getImportantForAutofill(); + // Check parent mode to ensure we're not hidden. + ViewParent parent = mParent; + while (parent instanceof View) { + final int parentImportance = ((View) parent).getImportantForAutofill(); + if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS + || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) { + return false; + } + parent = parent.getParent(); + } - // First, check if view explicity set it to YES or NO - if ((flag & IMPORTANT_FOR_AUTOFILL_YES) != 0) { + final int importance = getImportantForAutofill(); + + // First, check the explicit states. + if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS + || importance == IMPORTANT_FOR_AUTOFILL_YES) { return true; } - if ((flag & IMPORTANT_FOR_AUTOFILL_NO) != 0) { + if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS + || importance == IMPORTANT_FOR_AUTOFILL_NO) { return false; } // Then use some heuristics to handle AUTO. - // Always include views that have a explicity resource id. + // Always include views that have an explicit resource id. final int id = mID; if (id != NO_ID && !isViewIdGenerated(id)) { final Resources res = getResources(); @@ -7642,9 +7684,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return mContext.getSystemService(AutofillManager.class); } - /** @hide */ - public boolean isAutofillable() { - return getAutofillType() != AUTOFILL_TYPE_NONE && !isAutofillBlocked(); + private boolean isAutofillable() { + return getAutofillType() != AUTOFILL_TYPE_NONE && isImportantForAutofill(); } private void populateVirtualStructure(ViewStructure structure, @@ -7728,26 +7769,33 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * set the {@link AutofillId} in the structure (for example, by calling * {@code structure.setAutofillId(getAutofillId())}). * + * <p>When providing your implementation you need to decide how to handle + * the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag which instructs you + * to report all views to the structure regardless if {@link #isImportantForAutofill()} + * returns true. We encourage you respect the importance property for a better + * user experience in your app. If the flag is not set then you should filter out + * not important views to optimize autofill performance in your app. + * * @param structure Fill in with structured view data. - * @param flags optional flags (currently {@code 0}). + * @param flags optional flags. + * + * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS */ - public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure, int flags) { + public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure, + @AutofillFlags int flags) { dispatchProvideStructureForAssistOrAutofill(structure, true); } private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure, boolean forAutofill) { - boolean blocked = forAutofill ? isAutofillBlocked() : isAssistBlocked(); - if (!blocked) { - if (forAutofill) { - structure.setAutofillId(getAutofillId()); - // NOTE: flags are not currently supported, hence 0 - onProvideAutofillStructure(structure, 0); - onProvideAutofillVirtualStructure(structure, 0); - } else { - onProvideStructure(structure); - onProvideVirtualStructure(structure); - } + if (forAutofill) { + structure.setAutofillId(getAutofillId()); + // NOTE: flags are not currently supported, hence 0 + onProvideAutofillStructure(structure, 0); + onProvideAutofillVirtualStructure(structure, 0); + } else if (!isAssistBlocked()) { + onProvideStructure(structure); + onProvideVirtualStructure(structure); } else { structure.setClassName(getAccessibilityClassName().toString()); structure.setAssistBlocked(true); @@ -9585,22 +9633,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * @hide - * Indicates whether this view will participate in data collection through - * {@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 autofill is not blocked, - * else {@code true}. - */ - public boolean isAutofillBlocked() { - // TODO(b/36171235): properly implement it using isImportantForAutofill() - return false; - } - - /** - * @hide * Controls whether assist data collection from this view and its children is enabled * (that is, whether {@link #onProvideStructure} and * {@link #onProvideVirtualStructure} will be called). The default value is false, @@ -21085,7 +21117,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @Nullable public final <T extends View> T findViewById(@IdRes int id) { - if (id < 0) { + if (id == NO_ID) { return null; } return findViewTraversal(id); diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index b78348237864..18c1b8c3ad22 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -57,7 +57,6 @@ import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.LayoutAnimationController; import android.view.animation.Transformation; - import com.android.internal.R; import java.util.ArrayList; @@ -3442,12 +3441,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * default {@link View} implementation. */ @Override - public void dispatchProvideAutofillStructure(ViewStructure structure, int flags) { + public void dispatchProvideAutofillStructure(ViewStructure structure, + @AutofillFlags int flags) { super.dispatchProvideAutofillStructure(structure, flags); - if (isAutofillBlocked() || structure.getChildCount() != 0) { + if (structure.getChildCount() != 0) { return; } - final ChildListForAutoFill children = getChildrenForAutofill(); + final ChildListForAutoFill children = getChildrenForAutofill(flags); final int childrenCount = children.size(); structure.setChildCount(childrenCount); for (int i = 0; i < childrenCount; i++) { @@ -3463,14 +3463,14 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * level descendants that are important for autofill. The returned * child list object is pooled and the caller must recycle it once done. * @hide */ - private @NonNull ChildListForAutoFill getChildrenForAutofill() { + private @NonNull ChildListForAutoFill getChildrenForAutofill(@AutofillFlags int flags) { final ChildListForAutoFill children = ChildListForAutoFill.obtain(); - populateChildrenForAutofill(children); + populateChildrenForAutofill(children, flags); return children; } /** @hide */ - private void populateChildrenForAutofill(ArrayList<View> list) { + private void populateChildrenForAutofill(ArrayList<View> list, @AutofillFlags int flags) { final int childrenCount = mChildrenCount; if (childrenCount <= 0) { return; @@ -3482,10 +3482,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder); final View child = (preorderedList == null) ? mChildren[childIndex] : preorderedList.get(childIndex); - if (child.isImportantForAutofill()) { + if ((flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0 + || child.isImportantForAutofill()) { list.add(child); } else if (child instanceof ViewGroup) { - ((ViewGroup) child).populateChildrenForAutofill(list); + ((ViewGroup) child).populateChildrenForAutofill(list, flags); } } } @@ -5413,6 +5414,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (mDefaultFocus != null) { clearDefaultFocus(mDefaultFocus); } + if (mFocusedInCluster != null) { + clearFocusedInCluster(mFocusedInCluster); + } if (clearChildFocus) { clearChildFocus(focused); if (!rootViewRequestFocus()) { diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java index fb910b83e927..f71589c6c5ef 100644 --- a/core/java/android/view/ViewStructure.java +++ b/core/java/android/view/ViewStructure.java @@ -26,7 +26,7 @@ import android.util.Pair; import android.view.autofill.AutofillId; import android.view.autofill.AutofillValue; -import java.util.ArrayList; +import java.util.List; /** * Container for storing additional per-view data generated by {@link View#onProvideStructure @@ -429,7 +429,7 @@ public abstract class ViewStructure { * @return list of key/value pairs; could contain pairs with the same keys. */ @Nullable - public abstract ArrayList<Pair<String, String>> getAttributes(); + public abstract List<Pair<String, String>> getAttributes(); /** * Builder for {@link HtmlInfo} objects. diff --git a/core/java/android/view/autofill/AutofillId.java b/core/java/android/view/autofill/AutofillId.java index 268f7f3557d1..1cee529b9d62 100644 --- a/core/java/android/view/autofill/AutofillId.java +++ b/core/java/android/view/autofill/AutofillId.java @@ -15,8 +15,6 @@ */ package android.view.autofill; -import static android.view.autofill.Helper.DEBUG; - import android.os.Parcel; import android.os.Parcelable; import android.view.View; @@ -92,11 +90,9 @@ public final class AutofillId implements Parcelable { @Override public String toString() { - if (!DEBUG) return super.toString(); - final StringBuilder builder = new StringBuilder().append(mViewId); if (mVirtual) { - builder.append(":").append(mVirtualId); + builder.append(':').append(mVirtualId); } return builder.toString(); } diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 9ee0cb1f811e..94ca562cedc8 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -16,8 +16,8 @@ package android.view.autofill; -import static android.view.autofill.Helper.DEBUG; -import static android.view.autofill.Helper.VERBOSE; +import static android.view.autofill.Helper.sDebug; +import static android.view.autofill.Helper.sVerbose; import android.annotation.IntDef; import android.annotation.NonNull; @@ -94,7 +94,8 @@ public final class AutofillManager { * <p> * Type: {@link android.os.Bundle} */ - public static final String EXTRA_DATA_EXTRAS = "android.view.autofill.extra.DATA_EXTRAS"; + public static final String EXTRA_CLIENT_STATE = + "android.view.autofill.extra.EXTRA_CLIENT_STATE"; static final String SESSION_ID_TAG = "android:sessionId"; static final String LAST_AUTOFILLED_DATA_TAG = "android:lastAutoFilledData"; @@ -107,11 +108,15 @@ public final class AutofillManager { @Deprecated public static final int FLAG_MANUAL_REQUEST = 0x1; - // TODO(b/37563972): start from 0x1 once FLAG_MANUAL_REQUEST is gone - /** @hide */ public static final int FLAG_START_SESSION = 0x80000000; - /** @hide */ public static final int FLAG_VIEW_ENTERED = 0x40000000; - /** @hide */ public static final int FLAG_VIEW_EXITED = 0x20000000; - /** @hide */ public static final int FLAG_VALUE_CHANGED = 0x10000000; + /** @hide */ public static final int ACTION_START_SESSION = 1; + /** @hide */ public static final int ACTION_VIEW_ENTERED = 2; + /** @hide */ public static final int ACTION_VIEW_EXITED = 3; + /** @hide */ public static final int ACTION_VALUE_CHANGED = 4; + + + /** @hide */ public static final int FLAG_ADD_CLIENT_ENABLED = 0x1; + /** @hide */ public static final int FLAG_ADD_CLIENT_DEBUG = 0x2; + /** @hide */ public static final int FLAG_ADD_CLIENT_VERBOSE = 0x4; private final MetricsLogger mMetricsLogger = new MetricsLogger(); @@ -239,7 +244,7 @@ public final class AutofillManager { Log.w(TAG, "Session " + mSessionId + " could not be restored"); mSessionId = NO_SESSION; } else { - if (DEBUG) { + if (sDebug) { Log.d(TAG, "session " + mSessionId + " was restored"); } @@ -356,21 +361,7 @@ public final class AutofillManager { * @param view view requesting the new autofill context. */ public void requestAutofill(@NonNull View view) { - if (!hasAutofillFeature()) { - return; - } - synchronized (mLock) { - ensureServiceClientAddedIfNeededLocked(); - - if (!mEnabled) { - return; - } - - final AutofillId id = getAutofillId(view); - final AutofillValue value = view.getAutofillValue(); - - startSessionLocked(id, view.getWindowToken(), null, value, FLAG_MANUAL_REQUEST); - } + notifyViewEntered(view, FLAG_MANUAL_REQUEST); } /** @@ -385,19 +376,7 @@ public final class AutofillManager { * @param bounds child boundaries, relative to the top window. */ public void requestAutofill(@NonNull View view, int childId, @NonNull Rect bounds) { - if (!hasAutofillFeature()) { - return; - } - synchronized (mLock) { - ensureServiceClientAddedIfNeededLocked(); - - if (!mEnabled) { - return; - } - - final AutofillId id = getAutofillId(view, childId); - startSessionLocked(id, view.getWindowToken(), bounds, null, FLAG_MANUAL_REQUEST); - } + notifyViewEntered(view, childId, bounds, FLAG_MANUAL_REQUEST); } /** @@ -406,6 +385,10 @@ public final class AutofillManager { * @param view {@link View} that was entered. */ public void notifyViewEntered(@NonNull View view) { + notifyViewEntered(view, 0); + } + + private void notifyViewEntered(@NonNull View view, int flags) { if (!hasAutofillFeature()) { return; } @@ -423,10 +406,10 @@ public final class AutofillManager { if (mSessionId == NO_SESSION) { // Starts new session. - startSessionLocked(id, view.getWindowToken(), null, value, 0); + startSessionLocked(id, view.getWindowToken(), null, value, flags); } else { // Update focus on existing session. - updateSessionLocked(id, null, value, FLAG_VIEW_ENTERED); + updateSessionLocked(id, null, value, ACTION_VIEW_ENTERED, flags); } } } @@ -452,7 +435,7 @@ public final class AutofillManager { final AutofillId id = getAutofillId(view); // Update focus on existing session. - updateSessionLocked(id, null, null, FLAG_VIEW_EXITED); + updateSessionLocked(id, null, null, ACTION_VIEW_EXITED, 0); } } } @@ -481,6 +464,10 @@ public final class AutofillManager { * @param bounds child boundaries, relative to the top window. */ public void notifyViewEntered(@NonNull View view, int childId, @NonNull Rect bounds) { + notifyViewEntered(view, childId, bounds, 0); + } + + private void notifyViewEntered(View view, int childId, Rect bounds, int flags) { if (!hasAutofillFeature()) { return; } @@ -497,10 +484,10 @@ public final class AutofillManager { if (mSessionId == NO_SESSION) { // Starts new session. - startSessionLocked(id, view.getWindowToken(), bounds, null, 0); + startSessionLocked(id, view.getWindowToken(), bounds, null, flags); } else { // Update focus on existing session. - updateSessionLocked(id, bounds, null, FLAG_VIEW_ENTERED); + updateSessionLocked(id, bounds, null, ACTION_VIEW_ENTERED, flags); } } } @@ -528,7 +515,7 @@ public final class AutofillManager { final AutofillId id = getAutofillId(view, childId); // Update focus on existing session. - updateSessionLocked(id, null, null, FLAG_VIEW_EXITED); + updateSessionLocked(id, null, null, ACTION_VIEW_EXITED, 0); } } } @@ -580,7 +567,7 @@ public final class AutofillManager { value = view.getAutofillValue(); } - updateSessionLocked(id, null, value, FLAG_VALUE_CHANGED); + updateSessionLocked(id, null, value, ACTION_VALUE_CHANGED, 0); } } @@ -601,7 +588,7 @@ public final class AutofillManager { } final AutofillId id = getAutofillId(view, childId); - updateSessionLocked(id, null, value, FLAG_VALUE_CHANGED); + updateSessionLocked(id, null, value, ACTION_VALUE_CHANGED, 0); } } @@ -708,7 +695,7 @@ public final class AutofillManager { // set the EXTRA_AUTHENTICATION_RESULT extra, but it could cause weird results if the // service set the extra and returned RESULT_CANCELED... - if (DEBUG) Log.d(TAG, "onAuthenticationResult(): d=" + data); + if (sDebug) Log.d(TAG, "onAuthenticationResult(): d=" + data); synchronized (mLock) { if (mSessionId == NO_SESSION || data == null) { @@ -735,8 +722,8 @@ public final class AutofillManager { private void startSessionLocked(@NonNull AutofillId id, @NonNull IBinder windowToken, @NonNull Rect bounds, @NonNull AutofillValue value, int flags) { - if (DEBUG) { - Log.d(TAG, "startSessionLocked(): id=" + id + ", bounds=" + bounds + ", value=" + value + if (sVerbose) { + Log.v(TAG, "startSessionLocked(): id=" + id + ", bounds=" + bounds + ", value=" + value + ", flags=" + flags); } @@ -744,7 +731,7 @@ public final class AutofillManager { mSessionId = mService.startSession(mContext.getActivityToken(), windowToken, mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(), mCallback != null, flags, mContext.getOpPackageName()); - AutofillClient client = getClientLocked(); + final AutofillClient client = getClientLocked(); if (client != null) { client.autofillCallbackResetableStateAvailable(); } @@ -754,9 +741,7 @@ public final class AutofillManager { } private void finishSessionLocked() { - if (DEBUG) { - Log.d(TAG, "finishSessionLocked()"); - } + if (sVerbose) Log.v(TAG, "finishSessionLocked()"); try { mService.finishSession(mSessionId, mContext.getUserId()); @@ -769,9 +754,7 @@ public final class AutofillManager { } private void cancelSessionLocked() { - if (DEBUG) { - Log.d(TAG, "cancelSessionLocked()"); - } + if (sVerbose) Log.v(TAG, "cancelSessionLocked()"); try { mService.cancelSession(mSessionId, mContext.getUserId()); @@ -787,16 +770,16 @@ public final class AutofillManager { mTrackedViews = null; } - private void updateSessionLocked(AutofillId id, Rect bounds, AutofillValue value, int flags) { - if (DEBUG) { - if (VERBOSE || (flags & FLAG_VIEW_EXITED) != 0) { - Log.d(TAG, "updateSessionLocked(): id=" + id + ", bounds=" + bounds - + ", value=" + value + ", flags=" + flags); - } + private void updateSessionLocked(AutofillId id, Rect bounds, AutofillValue value, int action, + int flags) { + if (sVerbose && action != ACTION_VIEW_EXITED) { + Log.v(TAG, "updateSessionLocked(): id=" + id + ", bounds=" + bounds + + ", value=" + value + ", action=" + action + ", flags=" + flags); } try { - mService.updateSession(mSessionId, id, bounds, value, flags, mContext.getUserId()); + mService.updateSession(mSessionId, id, bounds, value, action, flags, + mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -810,7 +793,10 @@ public final class AutofillManager { if (mServiceClient == null) { mServiceClient = new AutofillManagerClient(this); try { - mEnabled = mService.addClient(mServiceClient, mContext.getUserId()); + final int flags = mService.addClient(mServiceClient, mContext.getUserId()); + mEnabled = (flags & FLAG_ADD_CLIENT_ENABLED) != 0; + sDebug = (flags & FLAG_ADD_CLIENT_DEBUG) != 0; + sVerbose = (flags & FLAG_ADD_CLIENT_VERBOSE) != 0; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1192,8 +1178,8 @@ public final class AutofillManager { } } - if (DEBUG) { - Log.d(TAG, "TrackedViews(trackedIds=" + trackedIds + "): " + if (sVerbose) { + Log.v(TAG, "TrackedViews(trackedIds=" + trackedIds + "): " + " mVisibleTrackedIds=" + mVisibleTrackedIds + " mInvisibleTrackedIds=" + mInvisibleTrackedIds); } @@ -1213,7 +1199,7 @@ public final class AutofillManager { AutofillId id = getAutofillId(view); AutofillClient client = getClientLocked(); - if (DEBUG) { + if (sDebug) { Log.d(TAG, "notifyViewVisibilityChange(): id=" + id + " isVisible=" + isVisible); } @@ -1254,8 +1240,8 @@ public final class AutofillManager { if (client.getViewVisibility(id.getViewId())) { updatedVisibleTrackedIds = addToSet(updatedVisibleTrackedIds, id); - if (DEBUG) { - Log.i(TAG, "onVisibleForAutofill() " + id + " became visible"); + if (sDebug) { + Log.d(TAG, "onVisibleForAutofill() " + id + " became visible"); } } else { updatedInvisibleTrackedIds = addToSet(updatedInvisibleTrackedIds, id); @@ -1270,8 +1256,8 @@ public final class AutofillManager { } else { updatedInvisibleTrackedIds = addToSet(updatedInvisibleTrackedIds, id); - if (DEBUG) { - Log.i(TAG, "onVisibleForAutofill() " + id + " became invisible"); + if (sDebug) { + Log.d(TAG, "onVisibleForAutofill() " + id + " became invisible"); } } } diff --git a/core/java/android/view/autofill/AutofillValue.java b/core/java/android/view/autofill/AutofillValue.java index b1a9d90cc4ca..b57dab56318e 100644 --- a/core/java/android/view/autofill/AutofillValue.java +++ b/core/java/android/view/autofill/AutofillValue.java @@ -20,8 +20,7 @@ import static android.view.View.AUTOFILL_TYPE_DATE; import static android.view.View.AUTOFILL_TYPE_LIST; import static android.view.View.AUTOFILL_TYPE_TEXT; import static android.view.View.AUTOFILL_TYPE_TOGGLE; -import static android.view.autofill.Helper.DEBUG; -import static android.view.autofill.Helper.VERBOSE; +import static android.view.autofill.Helper.sDebug; import android.annotation.NonNull; import android.annotation.Nullable; @@ -171,12 +170,17 @@ public final class AutofillValue implements Parcelable { @Override public String toString() { - if (!DEBUG) return super.toString(); + if (!sDebug) return super.toString(); - final String sanitizedValue = isText() && !VERBOSE - ? ((CharSequence) mValue).length() + "_chars" : mValue.toString(); - - return "[type=" + mType + ", value=" + sanitizedValue + "]"; + final StringBuilder string = new StringBuilder() + .append("[type=").append(mType) + .append(", value="); + if (isText()) { + string.append(((CharSequence) mValue).length()).append("_chars"); + } else { + string.append(mValue); + } + return string.append(']').toString(); } ///////////////////////////////////// diff --git a/core/java/android/view/autofill/Helper.java b/core/java/android/view/autofill/Helper.java index 2b25ae7aa5e8..829e7f3aa5ac 100644 --- a/core/java/android/view/autofill/Helper.java +++ b/core/java/android/view/autofill/Helper.java @@ -25,15 +25,16 @@ import java.util.Set; /** @hide */ public final class Helper { - // TODO(b/36141126): set to false and remove guard from places that should always be on - public static final boolean DEBUG = true; - public static final boolean VERBOSE = false; + // Debug-level flags are defined when service is bound. + public static boolean sDebug = false; + public static boolean sVerbose = false; + public static final String REDACTED = "[REDACTED]"; static StringBuilder append(StringBuilder builder, Bundle bundle) { - if (bundle == null) { + if (bundle == null || !sDebug) { builder.append("N/A"); - } else if (!VERBOSE) { + } else if (!sVerbose) { builder.append(REDACTED); } else { final Set<String> keySet = bundle.keySet(); diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl index 9417bd07a267..f28d8bad595a 100644 --- a/core/java/android/view/autofill/IAutoFillManager.aidl +++ b/core/java/android/view/autofill/IAutoFillManager.aidl @@ -30,7 +30,8 @@ import android.view.autofill.IAutoFillManagerClient; * {@hide} */ interface IAutoFillManager { - boolean addClient(in IAutoFillManagerClient client, int userId); + // Returns flags: FLAG_ADD_CLIENT_ENABLED | FLAG_ADD_CLIENT_DEBUG | FLAG_ADD_CLIENT_VERBOSE + int addClient(in IAutoFillManagerClient client, int userId); int startSession(IBinder activityToken, IBinder windowToken, in IBinder appCallback, in AutofillId autoFillId, in Rect bounds, in AutofillValue value, int userId, boolean hasCallback, int flags, String packageName); @@ -38,7 +39,7 @@ interface IAutoFillManager { boolean restoreSession(int sessionId, in IBinder activityToken, in IBinder appCallback); void setWindow(int sessionId, in IBinder windowToken); void updateSession(int sessionId, in AutofillId id, in Rect bounds, - in AutofillValue value, int flags, int userId); + in AutofillValue value, int action, int flags, int userId); void finishSession(int sessionId, int userId); void cancelSession(int sessionId, int userId); void setAuthenticationResult(in Bundle data, int sessionId, int userId); diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 6213a63e108a..52c82a71fb7e 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -2255,6 +2255,7 @@ public class WebView extends AbsoluteLayout /** * Sets the {@link TextClassifier} for this WebView. + * @hide */ public void setTextClassifier(@Nullable TextClassifier textClassifier) { mProvider.setTextClassifier(textClassifier); @@ -2263,6 +2264,7 @@ public class WebView extends AbsoluteLayout /** * Returns the {@link TextClassifier} used by this WebView. * If no TextClassifier has been set, this WebView uses the default set by the system. + * @hide */ @NonNull public TextClassifier getTextClassifier() { @@ -2506,6 +2508,7 @@ public class WebView extends AbsoluteLayout super.onDetachedFromWindowInternal(); } + /** @hide */ @Override public void onMovedToDisplay(int displayId, Configuration config) { mProvider.getViewDelegate().onMovedToDisplay(displayId, config); diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 4ae35103a814..27e3fe523642 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -3836,9 +3836,11 @@ public class Editor { } if (mTextView.canRequestAutofill()) { + final int mode = mTextView.getText().length() <= 0 + ? MenuItem.SHOW_AS_ACTION_IF_ROOM : MenuItem.SHOW_AS_ACTION_NEVER; menu.add(Menu.NONE, TextView.ID_AUTOFILL, MENU_ITEM_ORDER_AUTOFILL, com.android.internal.R.string.autofill) - .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + .setShowAsAction(mode); } updateSelectAllItem(menu); diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java index ff3c85c99f53..88c3c5b6101e 100644 --- a/core/java/android/widget/LinearLayout.java +++ b/core/java/android/widget/LinearLayout.java @@ -258,9 +258,9 @@ public class LinearLayout extends ViewGroup { mUseLargestChild = a.getBoolean(R.styleable.LinearLayout_measureWithLargestChild, false); - setDividerDrawable(a.getDrawable(R.styleable.LinearLayout_divider)); mShowDividers = a.getInt(R.styleable.LinearLayout_showDividers, SHOW_DIVIDER_NONE); mDividerPadding = a.getDimensionPixelSize(R.styleable.LinearLayout_dividerPadding, 0); + setDividerDrawable(a.getDrawable(R.styleable.LinearLayout_divider)); final int version = context.getApplicationInfo().targetSdkVersion; mAllowInconsistentMeasurement = version <= Build.VERSION_CODES.M; diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 99b9bd2bfb5f..492010c414fa 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -126,6 +126,7 @@ import android.view.ContextMenu; import android.view.DragEvent; import android.view.Gravity; import android.view.HapticFeedbackConstants; +import android.view.InputDevice; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.MotionEvent; @@ -395,6 +396,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private TextClassifier mTextClassifier; + // A flag to prevent repeated movements from escaping the enclosing text view. The idea here is + // that if a user is holding down a movement key to traverse text, we shouldn't also traverse + // the view hierarchy. On the other hand, if the user is using the movement key to traverse + // views (i.e. the first movement was to traverse out of this view, or this view was traversed + // into by the user holding the movement key down) then we shouldn't prevent the focus from + // changing. + private boolean mPreventDefaultMovement; + private TextUtils.TruncateAt mEllipsize; static class Drawables { @@ -7155,6 +7164,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return KEY_EVENT_NOT_HANDLED; } + // If this is the initial keydown, we don't want to prevent a movement away from this view. + // While this shouldn't be necessary because any time we're preventing default movement we + // should be restricting the focus to remain within this view, thus we'll also receive + // the key up event, occasionally key up events will get dropped and we don't want to + // prevent the user from traversing out of this on the next key down. + if (event.getRepeatCount() == 0 && !KeyEvent.isModifierKey(keyCode)) { + mPreventDefaultMovement = false; + } + switch (keyCode) { case KeyEvent.KEYCODE_ENTER: if (event.hasNoModifiers()) { @@ -7286,16 +7304,23 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } if (doDown) { if (mMovement.onKeyDown(this, (Spannable) mText, keyCode, event)) { + if (event.getRepeatCount() == 0 && !KeyEvent.isModifierKey(keyCode)) { + mPreventDefaultMovement = true; + } return KEY_DOWN_HANDLED_BY_MOVEMENT_METHOD; } } - // Consume arrows to prevent focus leaving the editor. - if (isDirectionalNavigationKey(keyCode)) { + // Consume arrows from keyboard devices to prevent focus leaving the editor. + // DPAD/JOY devices (Gamepads, TV remotes) often lack a TAB key so allow those + // to move focus with arrows. + if (event.getSource() == InputDevice.SOURCE_KEYBOARD + && isDirectionalNavigationKey(keyCode)) { return KEY_EVENT_HANDLED; } } - return KEY_EVENT_NOT_HANDLED; + return mPreventDefaultMovement && !KeyEvent.isModifierKey(keyCode) + ? KEY_EVENT_HANDLED : KEY_EVENT_NOT_HANDLED; } /** @@ -7328,6 +7353,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return super.onKeyUp(keyCode, event); } + if (!KeyEvent.isModifierKey(keyCode)) { + mPreventDefaultMovement = false; + } + switch (keyCode) { case KeyEvent.KEYCODE_DPAD_CENTER: if (event.hasNoModifiers()) { @@ -9304,6 +9333,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } private void notifyAutoFillManagerAfterTextChangedIfNeeded() { + // It is important to not check whether the view is important for autofill + // since the user can trigger autofill manually on not important views. if (!isAutofillable()) { return; } @@ -9316,6 +9347,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } + private boolean isAutofillable() { + // It is important to not check whether the view is important for autofill + // since the user can trigger autofill manually on not important views. + return getAutofillType() != AUTOFILL_TYPE_NONE; + } + void updateAfterEdit() { invalidate(); int curs = getSelectionStart(); @@ -10192,6 +10229,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } boolean canRequestAutofill() { + if (!isAutofillable()) { + return false; + } final AutofillManager afm = mContext.getSystemService(AutofillManager.class); if (afm != null) { return afm.isEnabled(); diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java index c6b6a7fb999f..d2e97897c042 100644 --- a/core/java/com/android/internal/content/PackageMonitor.java +++ b/core/java/com/android/internal/content/PackageMonitor.java @@ -65,6 +65,7 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver { int mChangeType; int mChangeUserId = UserHandle.USER_NULL; boolean mSomePackagesChanged; + String[] mModifiedComponents; String[] mTempArray = new String[1]; @@ -269,6 +270,18 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver { } return false; } + + public boolean isComponentModified(String className) { + if (className == null || mModifiedComponents == null) { + return false; + } + for (int i = mModifiedComponents.length - 1; i >= 0; i--) { + if (className.equals(mModifiedComponents[i])) { + return true; + } + } + return false; + } public void onSomePackagesChanged() { } @@ -301,6 +314,7 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver { mDisappearingPackages = mAppearingPackages = null; mSomePackagesChanged = false; + mModifiedComponents = null; String action = intent.getAction(); if (Intent.ACTION_PACKAGE_ADDED.equals(action)) { @@ -358,13 +372,13 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver { } else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) { String pkg = getPackageName(intent); int uid = intent.getIntExtra(Intent.EXTRA_UID, 0); - String[] components = intent.getStringArrayExtra( + mModifiedComponents = intent.getStringArrayExtra( Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST); if (pkg != null) { mModifiedPackages = mTempArray; mTempArray[0] = pkg; mChangeType = PACKAGE_PERMANENT_CHANGE; - if (onPackageChanged(pkg, uid, components)) { + if (onPackageChanged(pkg, uid, mModifiedComponents)) { mSomePackagesChanged = true; } onPackageModified(pkg); diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java index 5cb66e501393..2c97f8bd5971 100644 --- a/core/java/com/android/internal/util/NotificationColorUtil.java +++ b/core/java/com/android/internal/util/NotificationColorUtil.java @@ -257,7 +257,7 @@ public class NotificationColorUtil { * @return a color with the same hue as {@param color}, potentially darkened to meet the * contrast ratio. */ - private static int findContrastColor(int color, int other, boolean findFg, double minRatio) { + public static int findContrastColor(int color, int other, boolean findFg, double minRatio) { int fg = findFg ? color : other; int bg = findFg ? other : color; if (ColorUtilsFromCompat.calculateContrast(fg, bg) >= minRatio) { @@ -402,16 +402,17 @@ public class NotificationColorUtil { } /** - * Lighten a color by a specified value + * Change a color by a specified value * @param baseColor the base color to lighten * @param amount the amount to lighten the color from 0 to 100. This corresponds to the L - * increase in the LAB color space. - * @return the lightened color + * increase in the LAB color space. A negative value will darken the color and + * a positive will lighten it. + * @return the changed color */ - public static int lightenColor(int baseColor, int amount) { + public static int changeColorLightness(int baseColor, int amount) { final double[] result = ColorUtilsFromCompat.getTempDouble3Array(); ColorUtilsFromCompat.colorToLAB(baseColor, result); - result[0] = Math.min(100, result[0] + amount); + result[0] = Math.max(Math.min(100, result[0] + amount), 0); return ColorUtilsFromCompat.LABToColor(result[0], result[1], result[2]); } @@ -491,6 +492,15 @@ public class NotificationColorUtil { return useDark; } + public static double calculateLuminance(int backgroundColor) { + return ColorUtilsFromCompat.calculateLuminance(backgroundColor); + } + + + public static double calculateContrast(int foregroundColor, int backgroundColor) { + return ColorUtilsFromCompat.calculateContrast(foregroundColor, backgroundColor); + } + /** * Framework copy of functions needed from android.support.v4.graphics.ColorUtils. */ diff --git a/core/java/com/android/internal/widget/MediaNotificationView.java b/core/java/com/android/internal/widget/MediaNotificationView.java index afb2a5efcf95..bbebcc21f80e 100644 --- a/core/java/com/android/internal/widget/MediaNotificationView.java +++ b/core/java/com/android/internal/widget/MediaNotificationView.java @@ -23,7 +23,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; -import android.widget.RelativeLayout; import android.widget.RemoteViews; /** @@ -34,8 +33,7 @@ import android.widget.RemoteViews; @RemoteViews.RemoteView public class MediaNotificationView extends FrameLayout { - private final int mMaxImageSize; - private final int mImageMinTopMargin; + private final int mSmallImageSize; private final int mNotificationContentMarginEnd; private final int mNotificationContentImageMarginEnd; private ImageView mRightIcon; @@ -57,72 +55,68 @@ public class MediaNotificationView extends FrameLayout { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int mode = MeasureSpec.getMode(widthMeasureSpec); boolean hasIcon = mRightIcon.getVisibility() != GONE; + if (!hasIcon) { + resetHeaderIndention(); + } + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int mode = MeasureSpec.getMode(widthMeasureSpec); + boolean reMeasure = false; if (hasIcon && mode != MeasureSpec.UNSPECIFIED) { - measureChild(mActions, widthMeasureSpec, heightMeasureSpec); int size = MeasureSpec.getSize(widthMeasureSpec); size = size - mActions.getMeasuredWidth(); ViewGroup.MarginLayoutParams layoutParams = (MarginLayoutParams) mRightIcon.getLayoutParams(); int imageEndMargin = layoutParams.getMarginEnd(); size -= imageEndMargin; - size = Math.min(size, mMaxImageSize); - size = Math.max(size, mRightIcon.getMinimumWidth()); - layoutParams.width = size; - layoutParams.height = size; - mRightIcon.setLayoutParams(layoutParams); + int fullHeight = getMeasuredHeight(); + if (size < fullHeight) { + size = mSmallImageSize; + } else { + size = fullHeight; + } + if (layoutParams.width != size || layoutParams.height != size) { + layoutParams.width = size; + layoutParams.height = size; + mRightIcon.setLayoutParams(layoutParams); + reMeasure = true; + } // lets ensure that the main column doesn't run into the image - ViewGroup.MarginLayoutParams mainParams + ViewGroup.MarginLayoutParams params = (MarginLayoutParams) mMainColumn.getLayoutParams(); int marginEnd = size + imageEndMargin + mNotificationContentMarginEnd; - if (marginEnd != mainParams.getMarginEnd()) { - mainParams.setMarginEnd(marginEnd); - mMainColumn.setLayoutParams(mainParams); + if (marginEnd != params.getMarginEnd()) { + params.setMarginEnd(marginEnd); + mMainColumn.setLayoutParams(params); + reMeasure = true; } - - } - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - ViewGroup.MarginLayoutParams iconParams = - (MarginLayoutParams) mRightIcon.getLayoutParams(); - int topMargin = getMeasuredHeight() - mRightIcon.getMeasuredHeight() - - iconParams.bottomMargin; - // If the topMargin is high enough we can also remove the header constraint! - boolean reMeasure = false; - if (!hasIcon || topMargin >= mImageMinTopMargin) { - reMeasure = resetHeaderIndention(); - } else { - int paddingEnd = mNotificationContentImageMarginEnd; - ViewGroup.MarginLayoutParams headerParams = - (MarginLayoutParams) mHeader.getLayoutParams(); - int newMarginEnd = mRightIcon.getMeasuredWidth() + iconParams.getMarginEnd(); - if (headerParams.getMarginEnd() != newMarginEnd) { - headerParams.setMarginEnd(newMarginEnd); - mHeader.setLayoutParams(headerParams); + int headerMarginEnd = size + imageEndMargin; + params = (MarginLayoutParams) mHeader.getLayoutParams(); + if (params.getMarginEnd() != headerMarginEnd) { + params.setMarginEnd(headerMarginEnd); + mHeader.setLayoutParams(params); reMeasure = true; } - if (mHeader.getPaddingEnd() != paddingEnd) { + if (mHeader.getPaddingEnd() != mNotificationContentImageMarginEnd) { mHeader.setPaddingRelative(mHeader.getPaddingStart(), mHeader.getPaddingTop(), - paddingEnd, + mNotificationContentImageMarginEnd, mHeader.getPaddingBottom()); reMeasure = true; } } if (reMeasure) { - measureChildWithMargins(mHeader, widthMeasureSpec, 0, heightMeasureSpec, 0); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } - private boolean resetHeaderIndention() { - boolean remeasure = false; + private void resetHeaderIndention() { if (mHeader.getPaddingEnd() != mNotificationContentMarginEnd) { mHeader.setPaddingRelative(mHeader.getPaddingStart(), mHeader.getPaddingTop(), mNotificationContentMarginEnd, mHeader.getPaddingBottom()); - remeasure = true; } ViewGroup.MarginLayoutParams headerParams = (MarginLayoutParams) mHeader.getLayoutParams(); @@ -130,19 +124,14 @@ public class MediaNotificationView extends FrameLayout { if (headerParams.getMarginEnd() != 0) { headerParams.setMarginEnd(0); mHeader.setLayoutParams(headerParams); - remeasure = true; } - return remeasure; } public MediaNotificationView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - mMaxImageSize = context.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.media_notification_expanded_image_max_size); - mImageMinTopMargin = (int) (context.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.notification_content_margin_top) - + getResources().getDisplayMetrics().density * 2); + mSmallImageSize = context.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.media_notification_expanded_image_small_size); mNotificationContentMarginEnd = context.getResources().getDimensionPixelSize( com.android.internal.R.dimen.notification_content_margin_end); mNotificationContentImageMarginEnd = context.getResources().getDimensionPixelSize( diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp index 292454bd0875..d3d68826affe 100644 --- a/core/jni/android/graphics/Path.cpp +++ b/core/jni/android/graphics/Path.cpp @@ -26,6 +26,7 @@ #include "SkPath.h" #include "SkPathOps.h" +#include "SkGeometry.h" // WARNING: Internal Skia Header #include <Caches.h> #include <vector> @@ -355,8 +356,9 @@ public: } } - static void createVerbSegments(SkPath::Verb verb, const SkPoint* points, - std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths, float errorSquared) { + static void createVerbSegments(const SkPath::Iter& pathIter, SkPath::Verb verb, + const SkPoint* points, std::vector<SkPoint>& segmentPoints, + std::vector<float>& lengths, float errorSquared, float errorConic) { switch (verb) { case SkPath::kMove_Verb: addMove(segmentPoints, lengths, points[0]); @@ -375,8 +377,27 @@ public: addBezier(points, cubicBezierCalculation, segmentPoints, lengths, errorSquared, true); break; + case SkPath::kConic_Verb: { + SkAutoConicToQuads converter; + const SkPoint* quads = converter.computeQuads( + points, pathIter.conicWeight(), errorConic); + for (int i = 0; i < converter.countQuads(); i++) { + // Note: offset each subsequent quad by 2, since end points are shared + const SkPoint* quad = quads + i * 2; + addBezier(quad, quadraticBezierCalculation, segmentPoints, lengths, + errorConic, false); + } + break; + } default: - // Leave element as NULL, Conic sections are not supported. + static_assert(SkPath::kMove_Verb == 0 + && SkPath::kLine_Verb == 1 + && SkPath::kQuad_Verb == 2 + && SkPath::kConic_Verb == 3 + && SkPath::kCubic_Verb == 4 + && SkPath::kClose_Verb == 5 + && SkPath::kDone_Verb == 6, + "Path enum changed, new types may have been added."); break; } } @@ -398,9 +419,11 @@ public: std::vector<SkPoint> segmentPoints; std::vector<float> lengths; float errorSquared = acceptableError * acceptableError; + float errorConic = acceptableError / 2; // somewhat arbitrary while ((verb = pathIter.next(points, false)) != SkPath::kDone_Verb) { - createVerbSegments(verb, points, segmentPoints, lengths, errorSquared); + createVerbSegments(pathIter, verb, points, segmentPoints, lengths, + errorSquared, errorConic); } if (segmentPoints.empty()) { diff --git a/core/jni/android_hardware_HardwareBuffer.cpp b/core/jni/android_hardware_HardwareBuffer.cpp index 4b31c91c708c..ba2345083661 100644 --- a/core/jni/android_hardware_HardwareBuffer.cpp +++ b/core/jni/android_hardware_HardwareBuffer.cpp @@ -80,14 +80,10 @@ static jlong android_hardware_HardwareBuffer_create(JNIEnv* env, jobject clazz, } return NULL; } - uint64_t producerUsage = 0; - uint64_t consumerUsage = 0; - android_hardware_HardwareBuffer_convertToGrallocUsageBits( - &producerUsage, &consumerUsage, usage, 0); + uint64_t grallocUsage = AHardwareBuffer_convertToGrallocUsageBits(usage); sp<GraphicBuffer> buffer = new GraphicBuffer(width, height, pixelFormat, layers, - android_convertGralloc1To0Usage(producerUsage, consumerUsage), - std::string("HardwareBuffer pid [") + std::to_string(getpid()) +"]"); + grallocUsage, std::string("HardwareBuffer pid [") + std::to_string(getpid()) +"]"); status_t error = buffer->initCheck(); if (error < 0) { if (kDebugGraphicBuffer) { @@ -145,11 +141,7 @@ static jint android_hardware_HardwareBuffer_getLayers(JNIEnv* env, static jlong android_hardware_HardwareBuffer_getUsage(JNIEnv* env, jobject clazz, jlong nativeObject) { GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject); - uint64_t usage0 = 0; - uint64_t usage1 = 0; - android_hardware_HardwareBuffer_convertFromGrallocUsageBits(&usage0, &usage1, - buffer->getUsage(), buffer->getUsage()); - return usage0; + return AHardwareBuffer_convertFromGrallocUsageBits(buffer->getUsage()); } // ---------------------------------------------------------------------------- @@ -221,14 +213,8 @@ uint32_t android_hardware_HardwareBuffer_convertToPixelFormat(uint32_t format) { return AHardwareBuffer_convertToPixelFormat(format); } -void android_hardware_HardwareBuffer_convertToGrallocUsageBits(uint64_t* outProducerUsage, - uint64_t* outConsumerUsage, uint64_t usage0, uint64_t usage1) { - AHardwareBuffer_convertToGrallocUsageBits(outProducerUsage, outConsumerUsage, usage0, usage1); -} - -void android_hardware_HardwareBuffer_convertFromGrallocUsageBits(uint64_t* outUsage0, - uint64_t* outUsage1, uint64_t producerUsage, uint64_t consumerUsage) { - AHardwareBuffer_convertFromGrallocUsageBits(outUsage0, outUsage1, producerUsage, consumerUsage); +uint64_t android_hardware_HardwareBuffer_convertToGrallocUsageBits(uint64_t usage) { + return AHardwareBuffer_convertToGrallocUsageBits(usage); } } // namespace android diff --git a/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h b/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h index 3545c565fb12..c452b74c802b 100644 --- a/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h +++ b/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h @@ -32,22 +32,19 @@ extern jobject android_hardware_HardwareBuffer_createFromAHardwareBuffer( JNIEnv* env, AHardwareBuffer* hardwareBuffer); /* Convert from HAL_PIXEL_FORMAT values to AHARDWAREBUFFER_FORMAT values. */ -extern uint32_t android_hardware_HardwareBuffer_convertFromPixelFormat( - uint32_t format); +extern uint32_t android_hardware_HardwareBuffer_convertFromPixelFormat(uint32_t format); /* Convert from AHARDWAREBUFFER_FORMAT values to HAL_PIXEL_FORMAT values. */ -extern uint32_t android_hardware_HardwareBuffer_convertToPixelFormat( - uint32_t format); +extern uint32_t android_hardware_HardwareBuffer_convertToPixelFormat(uint32_t format); /* Convert from AHARDWAREBUFFER_USAGE* flags to to gralloc usage flags. */ -extern void android_hardware_HardwareBuffer_convertToGrallocUsageBits( - uint64_t* outProducerUsage, uint64_t* outConsumerUsage, uint64_t usage0, - uint64_t usage1); - -/* Convert from gralloc usage flags to to AHARDWAREBUFFER_USAGE0* flags. */ -extern void android_hardware_HardwareBuffer_convertFromGrallocUsageBits( - uint64_t* outUsage0, uint64_t* outUsage1, uint64_t producerUsage, - uint64_t consumerUsage); +extern uint64_t android_hardware_HardwareBuffer_convertToGrallocUsageBits(uint64_t usage); + +inline void android_hardware_HardwareBuffer_convertToGrallocUsageBits( + uint64_t* outProducerUsage, uint64_t* outConsumerUsage, uint64_t usage, uint64_t) { + outProducerUsage[0] = outConsumerUsage[0] = + android_hardware_HardwareBuffer_convertToGrallocUsageBits(usage); +} } // namespace android diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index eacb02fa8364..8bf96e368a98 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1697,7 +1697,8 @@ <permission android:name="android.permission.CACHE_CONTENT" android:protectionLevel="signature" /> - <!-- Allows an application to aggressively allocate disk space. + <!-- @SystemApi @hide + Allows an application to aggressively allocate disk space. <p>Not for use by third-party applications. --> <permission android:name="android.permission.ALLOCATE_AGGRESSIVE" diff --git a/core/res/res/layout/autofill_save.xml b/core/res/res/layout/autofill_save.xml index 2f7ad3a61406..cbea275af034 100644 --- a/core/res/res/layout/autofill_save.xml +++ b/core/res/res/layout/autofill_save.xml @@ -94,6 +94,7 @@ android:layout_height="wrap_content" style="@style/Widget.Material.Button.Colored" android:text="@string/autofill_save_yes"> + <requestFocus /> </Button> </com.android.internal.widget.ButtonBarLayout> diff --git a/core/res/res/layout/notification_template_material_big_media.xml b/core/res/res/layout/notification_template_material_big_media.xml index 04ea12d4f9fe..532f28e56392 100644 --- a/core/res/res/layout/notification_template_material_big_media.xml +++ b/core/res/res/layout/notification_template_material_big_media.xml @@ -23,6 +23,13 @@ android:background="#00000000" android:tag="bigMediaNarrow" > + <!-- The size will actually be determined at runtime --> + <ImageView android:id="@+id/right_icon" + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_gravity="top|end" + android:scaleType="centerCrop" + /> <include layout="@layout/notification_template_header" android:layout_width="match_parent" android:layout_height="53dp" @@ -60,14 +67,4 @@ <!-- media buttons will be added here --> </LinearLayout> </LinearLayout> - - <ImageView android:id="@+id/right_icon" - android:layout_width="@dimen/media_notification_expanded_image_max_size" - android:layout_height="@dimen/media_notification_expanded_image_max_size" - android:minWidth="40dp" - android:layout_marginEnd="16dp" - android:layout_marginBottom="20dp" - android:layout_gravity="bottom|end" - android:scaleType="centerCrop" - /> </com.android.internal.widget.MediaNotificationView> diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml index 4c6420790031..4be53e04ef67 100644 --- a/core/res/res/layout/notification_template_material_media.xml +++ b/core/res/res/layout/notification_template_material_media.xml @@ -23,6 +23,13 @@ android:background="#00000000" android:tag="media" > + <ImageView android:id="@+id/right_icon" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:adjustViewBounds="true" + android:layout_gravity="top|end" + android:scaleType="centerCrop" + /> <include layout="@layout/notification_template_header" android:layout_width="fill_parent" android:layout_height="53dp" /> @@ -61,5 +68,4 @@ <!-- media buttons will be added here --> </LinearLayout> </LinearLayout> - <include layout="@layout/notification_template_right_icon" /> </FrameLayout> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 95ba94209343..c88367476984 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -897,7 +897,7 @@ will run against. If not specified, only runs in the main process of the targetPackage. Can either be a comma-separated list of process names or '*' for any process that launches to run targetPackage code. --> - <attr name="targetProcess" format="string" /> + <attr name="targetProcesses" format="string" /> <!-- Flag indicating that an Instrumentation class wants to take care of starting/stopping profiling itself, rather than relying on @@ -2355,7 +2355,7 @@ is a period then it is appended to your package name. --> <attr name="name" /> <attr name="targetPackage" /> - <attr name="targetProcess" /> + <attr name="targetProcesses" /> <attr name="label" /> <attr name="icon" /> <attr name="roundIcon" /> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index c5316c6133cc..ef6c21fd90c0 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -208,8 +208,8 @@ <!-- The minimum height of the content if there are at least two lines or a picture--> <dimen name="notification_min_content_height">41dp</dimen> - <!-- The maximum size of the image in the expanded media notification --> - <dimen name="media_notification_expanded_image_max_size">94dp</dimen> + <!-- The small size of the image if the height drawing doesn't work anymore --> + <dimen name="media_notification_expanded_image_small_size">72dp</dimen> <!-- The maximum size of the image in the expanded media notification --> <dimen name="media_notification_expanded_image_margin_bottom">20dp</dimen> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index e13026b1360e..1fbcac247ac9 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2778,7 +2778,7 @@ <public name="paddingVertical" /> <public name="fontStyle" /> <public name="keyboardNavigationCluster" /> - <public name="targetProcess" /> + <public name="targetProcesses" /> <public name="nextClusterForward" /> <public name="__removed1" /> <public name="colorError" /> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 63a5cfd7376c..0ea9b3961979 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -598,11 +598,9 @@ <java-symbol type="string" name="badPin" /> <java-symbol type="string" name="badPuk" /> <java-symbol type="string" name="byteShort" /> - <java-symbol type="string" name="capability_desc_canRequestEnhancedWebAccessibility" /> <java-symbol type="string" name="capability_title_canRequestFilterKeyEvents" /> <java-symbol type="string" name="capability_desc_canRequestTouchExploration" /> <java-symbol type="string" name="capability_desc_canRetrieveWindowContent" /> - <java-symbol type="string" name="capability_title_canRequestEnhancedWebAccessibility" /> <java-symbol type="string" name="capability_desc_canRequestFilterKeyEvents" /> <java-symbol type="string" name="capability_title_canRequestTouchExploration" /> <java-symbol type="string" name="capability_title_canRetrieveWindowContent" /> @@ -2616,7 +2614,7 @@ <java-symbol type="string" name="new_sms_notification_title" /> <java-symbol type="string" name="new_sms_notification_content" /> - <java-symbol type="dimen" name="media_notification_expanded_image_max_size" /> + <java-symbol type="dimen" name="media_notification_expanded_image_small_size" /> <java-symbol type="dimen" name="media_notification_expanded_image_margin_bottom" /> <java-symbol type="dimen" name="notification_content_image_margin_end" /> diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml index d80ff1d1e313..75179463f0c4 100644 --- a/core/res/res/values/themes_device_defaults.xml +++ b/core/res/res/values/themes_device_defaults.xml @@ -744,6 +744,7 @@ easier. <item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item> <item name="colorSecondary">@color/secondary_device_default_settings_light</item> <item name="colorAccent">@color/accent_device_default_light</item> + <item name="colorEdgeEffect">@android:color/black</item> </style> <!-- @hide DeviceDefault theme for a window that should use Settings theme colors diff --git a/core/tests/coretests/src/android/metrics/LogMakerTest.java b/core/tests/coretests/src/android/metrics/LogMakerTest.java index 63c1f87178aa..ada59cd84931 100644 --- a/core/tests/coretests/src/android/metrics/LogMakerTest.java +++ b/core/tests/coretests/src/android/metrics/LogMakerTest.java @@ -179,6 +179,14 @@ public class LogMakerTest extends TestCase { assertEquals(-1, builder.getProcessId()); } + public void testSetAndClearUid() { + LogMaker builder = new LogMaker(0); + builder.setUid(1); + assertEquals(1, builder.getUid()); + builder.clearUid(); + assertEquals(-1, builder.getUid()); + } + public void testGiantLogOmitted() { LogMaker badBuilder = new LogMaker(0); StringBuilder b = new StringBuilder(); diff --git a/core/tests/coretests/src/android/metrics/MetricsReaderTest.java b/core/tests/coretests/src/android/metrics/MetricsReaderTest.java index d06f522433db..d10b3519bccf 100644 --- a/core/tests/coretests/src/android/metrics/MetricsReaderTest.java +++ b/core/tests/coretests/src/android/metrics/MetricsReaderTest.java @@ -26,6 +26,8 @@ import java.util.Collection; public class MetricsReaderTest extends TestCase { private static final int FULL_N = 10; private static final int CHECKPOINTED_N = 4; + private static final int PID = 1; + private static final int UID = 2; class FakeLogReader extends MetricsReader.LogReader { MetricsReader.Event[] mEvents; @@ -36,7 +38,8 @@ public class MetricsReaderTest extends TestCase { for (int i = 0; i < FULL_N; i++) { mEvents[i] = new MetricsReader.Event( 1000L + i, - 1, + PID, + UID, new LogMaker(i).serialize()); } } @@ -88,6 +91,13 @@ public class MetricsReaderTest extends TestCase { } } + public void testPidUid() { + mReader.read(0); + LogMaker log = mReader.next(); + assertEquals(PID, log.getProcessId()); + assertEquals(UID, log.getUid()); + } + public void testBlockingRead_readResetsHorizon() { mReader.read(1000); assertEquals(1000, mLogReader.mHorizonMs); diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index ba24eec0fb04..a4b137889388 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -213,6 +213,7 @@ public class SettingsBackupTest { Settings.Global.LANG_ID_UPDATE_CONTENT_URL, Settings.Global.LANG_ID_UPDATE_METADATA_URL, Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS, + Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS, Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST, Settings.Global.LOCATION_SETTINGS_LINK_TO_PERMISSIONS_ENABLED, Settings.Global.LOCK_SOUND, diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java index 363137321f5f..098cdc67555d 100644 --- a/graphics/java/android/graphics/Path.java +++ b/graphics/java/android/graphics/Path.java @@ -16,8 +16,10 @@ package android.graphics; +import android.annotation.FloatRange; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.Size; import dalvik.annotation.optimization.CriticalNative; import dalvik.annotation.optimization.FastNative; @@ -805,7 +807,12 @@ public class Path { * the error is less than half a pixel. * @return An array of components for points approximating the Path. */ - public float[] approximate(float acceptableError) { + @NonNull + @Size(min = 6, multiple = 3) + public float[] approximate(@FloatRange(from = 0) float acceptableError) { + if (acceptableError < 0) { + throw new IllegalArgumentException("AcceptableError must be greater than or equal to 0"); + } return nApproximate(mNativePath, acceptableError); } diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java index 24fb673887fe..97edf220e242 100644 --- a/graphics/java/android/graphics/SurfaceTexture.java +++ b/graphics/java/android/graphics/SurfaceTexture.java @@ -16,14 +16,14 @@ package android.graphics; -import java.lang.ref.WeakReference; - import android.annotation.Nullable; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.view.Surface; +import java.lang.ref.WeakReference; + /** * Captures frames from an image stream as an OpenGL ES texture. * @@ -345,14 +345,17 @@ public class SurfaceTexture { * Always call this method when you are done with SurfaceTexture. Failing * to do so may delay resource deallocation for a significant amount of * time. + * + * @see #isReleased() */ public void release() { nativeRelease(); } /** - * Returns true if the SurfaceTexture was released - * @hide + * Returns true if the SurfaceTexture was released. + * + * @see #release() */ public boolean isReleased() { return nativeIsReleased(); @@ -400,7 +403,6 @@ public class SurfaceTexture { private native void nativeReleaseTexImage(); private native int nativeDetachFromGLContext(); private native int nativeAttachToGLContext(int texName); - private native int nativeGetQueuedCount(); private native void nativeRelease(); private native boolean nativeIsReleased(); } diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index 09840a575609..f661f29bb7f9 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -6664,6 +6664,10 @@ status_t DynamicRefTable::addMapping(const String16& packageName, uint8_t packag return NO_ERROR; } +void DynamicRefTable::addMapping(uint8_t buildPackageId, uint8_t runtimePackageId) { + mLookupTable[buildPackageId] = runtimePackageId; +} + status_t DynamicRefTable::lookupResourceId(uint32_t* resId) const { uint32_t res = *resId; size_t packageId = Res_GETPACKAGE(res) + 1; diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index 306ff9a7c42c..7a6e37d41b7c 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -1610,6 +1610,8 @@ public: // the given package. status_t addMapping(const String16& packageName, uint8_t packageId); + void addMapping(uint8_t buildPackageId, uint8_t runtimePackageId); + // Performs the actual conversion of build-time resource ID to run-time // resource ID. status_t lookupResourceId(uint32_t* resId) const; diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index fde0e4760d61..5ef49dc5fecd 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -7,7 +7,7 @@ BUGREPORT_FONT_CACHE_USAGE := false # Enables fine-grained GLES error checking # If set to true, every GLES call is wrapped & error checked # Has moderate overhead -HWUI_ENABLE_OPENGL_VALIDATION := true +HWUI_ENABLE_OPENGL_VALIDATION := false hwui_src_files := \ hwui/Bitmap.cpp \ diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp index 9246237aeffb..64b2c4564d7b 100644 --- a/libs/hwui/PathTessellator.cpp +++ b/libs/hwui/PathTessellator.cpp @@ -1005,6 +1005,14 @@ bool PathTessellator::approximatePathOutlineVertices(const SkPath& path, bool fo break; } default: + static_assert(SkPath::kMove_Verb == 0 + && SkPath::kLine_Verb == 1 + && SkPath::kQuad_Verb == 2 + && SkPath::kConic_Verb == 3 + && SkPath::kCubic_Verb == 4 + && SkPath::kClose_Verb == 5 + && SkPath::kDone_Verb == 6, + "Path enum changed, new types may have been added"); break; } } diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h index 0c7bb6079fea..dd457867ea42 100644 --- a/libs/hwui/tests/common/TestUtils.h +++ b/libs/hwui/tests/common/TestUtils.h @@ -88,7 +88,8 @@ namespace uirenderer { }; \ INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, OpenGL); \ INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaGL); \ - INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); \ + /* Temporarily disabling Vulkan until we can figure out a way to stub out the driver */ \ + /* INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); */ \ void test_case_name##_##test_name##_RenderThreadTest::doTheThing(renderthread::RenderThread& renderThread) /** @@ -111,7 +112,8 @@ namespace uirenderer { static void doTheThing(renderthread::RenderThread& renderThread); \ }; \ INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaGL); \ - INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); \ + /* Temporarily disabling Vulkan until we can figure out a way to stub out the driver */ \ + /* INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); */ \ void test_case_name##_##test_name##_RenderThreadTest::doTheThing(renderthread::RenderThread& renderThread) /** diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java index 06555c1fa90b..ccdf5ae7fbf5 100644 --- a/media/java/android/media/ImageReader.java +++ b/media/java/android/media/ImageReader.java @@ -728,15 +728,15 @@ public class ImageReader implements AutoCloseable { if (format == ImageFormat.PRIVATE) { // Usage need to be either USAGE0_GPU_SAMPLED_IMAGE or USAGE0_VIDEO_ENCODE or combined. - boolean isAllowed = (usage == HardwareBuffer.USAGE0_GPU_SAMPLED_IMAGE); - isAllowed = isAllowed || (usage == HardwareBuffer.USAGE0_VIDEO_ENCODE); + boolean isAllowed = (usage == HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE); + isAllowed = isAllowed || (usage == HardwareBuffer.USAGE_VIDEO_ENCODE); isAllowed = isAllowed || (usage == - (HardwareBuffer.USAGE0_VIDEO_ENCODE | HardwareBuffer.USAGE0_GPU_SAMPLED_IMAGE)); + (HardwareBuffer.USAGE_VIDEO_ENCODE | HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE)); return isAllowed; } else { // Usage need to make the buffer CPU readable for explicit format. - return ((usage == HardwareBuffer.USAGE0_CPU_READ) || - (usage == HardwareBuffer.USAGE0_CPU_READ_OFTEN)); + return ((usage == HardwareBuffer.USAGE_CPU_READ_RARELY) || + (usage == HardwareBuffer.USAGE_CPU_READ_OFTEN)); } } diff --git a/packages/CarrierDefaultApp/AndroidManifest.xml b/packages/CarrierDefaultApp/AndroidManifest.xml index e450283312c3..2ef1cf59ffc5 100644 --- a/packages/CarrierDefaultApp/AndroidManifest.xml +++ b/packages/CarrierDefaultApp/AndroidManifest.xml @@ -33,6 +33,7 @@ <receiver android:name="com.android.carrierdefaultapp.CarrierDefaultBroadcastReceiver"> <intent-filter> <action android:name="com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED" /> + <action android:name="com.android.internal.telephony.CARRIER_SIGNAL_RESET" /> </intent-filter> </receiver> <service android:name="com.android.carrierdefaultapp.ProvisionObserver" diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java index e1125d9d503a..d5d0b7926c83 100644 --- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java +++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java @@ -91,6 +91,10 @@ public class CustomConfigLoader { arg1 = intent.getStringExtra(TelephonyIntents.EXTRA_APN_TYPE_KEY); arg2 = intent.getStringExtra(TelephonyIntents.EXTRA_ERROR_CODE_KEY); break; + case TelephonyIntents.ACTION_CARRIER_SIGNAL_RESET: + configs = b.getStringArray(CarrierConfigManager + .KEY_CARRIER_DEFAULT_ACTIONS_ON_RESET); + break; default: Rlog.e(TAG, "load carrier config failure with un-configured key: " + intent.getAction()); diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java index 11c858f4fb0a..2a4ab0f550e5 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java @@ -35,7 +35,7 @@ import android.bluetooth.le.ScanResult; import android.bluetooth.le.ScanSettings; import android.companion.AssociationRequest; import android.companion.BluetoothDeviceFilter; -import android.companion.BluetoothLEDeviceFilter; +import android.companion.BluetoothLeDeviceFilter; import android.companion.DeviceFilter; import android.companion.ICompanionDeviceDiscoveryService; import android.companion.ICompanionDeviceDiscoveryServiceCallback; @@ -79,7 +79,7 @@ public class DeviceDiscoveryService extends Service { private ScanSettings mDefaultScanSettings = new ScanSettings.Builder().build(); private List<DeviceFilter<?>> mFilters; - private List<BluetoothLEDeviceFilter> mBLEFilters; + private List<BluetoothLeDeviceFilter> mBLEFilters; private List<BluetoothDeviceFilter> mBluetoothFilters; private List<WifiDeviceFilter> mWifiFilters; private List<ScanFilter> mBLEScanFilters; @@ -144,8 +144,8 @@ public class DeviceDiscoveryService extends Service { mFilters = request.getDeviceFilters(); mWifiFilters = CollectionUtils.filter(mFilters, WifiDeviceFilter.class); mBluetoothFilters = CollectionUtils.filter(mFilters, BluetoothDeviceFilter.class); - mBLEFilters = CollectionUtils.filter(mFilters, BluetoothLEDeviceFilter.class); - mBLEScanFilters = CollectionUtils.map(mBLEFilters, BluetoothLEDeviceFilter::getScanFilter); + mBLEFilters = CollectionUtils.filter(mFilters, BluetoothLeDeviceFilter.class); + mBLEScanFilters = CollectionUtils.map(mBLEFilters, BluetoothLeDeviceFilter::getScanFilter); reset(); } else if (DEBUG) Log.i(LOG_TAG, "startDiscovery: duplicate request: " + request); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 48429e8b2b05..a6347c67efd8 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -898,13 +898,14 @@ public class SettingsProvider extends ContentProvider { Slog.v(LOG_TAG, "getGlobalSetting(" + name + ")"); } - // Ensure the caller can access the setting. - enforceSettingReadable(name, SETTINGS_TYPE_GLOBAL, UserHandle.getCallingUserId()); - // Get the value. synchronized (mLock) { - return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_GLOBAL, + Setting setting = mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM, name); + // Ensure the caller can access the setting before we return it. + enforceSettingReadable(setting, name, SETTINGS_TYPE_GLOBAL, + UserHandle.getCallingUserId()); + return setting; } } @@ -1062,9 +1063,6 @@ public class SettingsProvider extends ContentProvider { // Resolve the userId on whose behalf the call is made. final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); - // Ensure the caller can access the setting. - enforceSettingReadable(name, SETTINGS_TYPE_SECURE, UserHandle.getCallingUserId()); - // Determine the owning user as some profile settings are cloned from the parent. final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name); @@ -1078,6 +1076,7 @@ public class SettingsProvider extends ContentProvider { // As of Android O, the SSAID is read from an app-specific entry in table // SETTINGS_FILE_SSAID, unless accessed by a system process. + // All apps are allowed to access their SSAID, so we skip the permission check. if (isNewSsaidSetting(name)) { PackageInfo callingPkg = getCallingPackageInfo(owningUserId); synchronized (mLock) { @@ -1087,8 +1086,12 @@ public class SettingsProvider extends ContentProvider { // Not the SSAID; do a straight lookup synchronized (mLock) { - return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SECURE, + Setting setting = mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SECURE, owningUserId, name); + // Ensure the caller can access the setting before we return it. + enforceSettingReadable(setting, name, SETTINGS_TYPE_SECURE, + UserHandle.getCallingUserId()); + return setting; } } @@ -1289,15 +1292,18 @@ public class SettingsProvider extends ContentProvider { // Resolve the userId on whose behalf the call is made. final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); - // Ensure the caller can access the setting. - enforceSettingReadable(name, SETTINGS_TYPE_SYSTEM, UserHandle.getCallingUserId()); // Determine the owning user as some profile settings are cloned from the parent. final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name); // Get the value. synchronized (mLock) { - return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SYSTEM, owningUserId, name); + Setting setting = mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SYSTEM, + owningUserId, name); + // Ensure the caller can access the setting before we return it. + enforceSettingReadable(setting, name, SETTINGS_TYPE_SYSTEM, + UserHandle.getCallingUserId()); + return setting; } } @@ -1644,14 +1650,22 @@ public class SettingsProvider extends ContentProvider { } } - private void enforceSettingReadable(String settingName, int settingsType, int userId) { + private void enforceSettingReadable(Setting setting, String settingName, int settingsType, + int userId) { if (UserHandle.getAppId(Binder.getCallingUid()) < Process.FIRST_APPLICATION_UID) { return; } ApplicationInfo ai = getCallingApplicationInfoOrThrow(); + // Installed apps are allowed to read all settings. if (!ai.isInstantApp()) { return; } + // Instant Apps are allowed to read settings defined by applications. + // TODO: Replace this with an API that allows the setting application to say if a setting + // shoud/shouldn't be accessible. + if (!setting.isDefaultFromSystem()) { + return; + } if (!getInstantAppAccessibleSettings(settingsType).contains(settingName)) { throw new SecurityException("Setting " + settingName + " is not accessible from" + " ephemeral package " + getCallingPackage()); diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml index 2f5222744a86..1efa3a81e5ab 100644 --- a/packages/SystemUI/res-keyguard/values/strings.xml +++ b/packages/SystemUI/res-keyguard/values/strings.xml @@ -102,6 +102,9 @@ <string name="keyguard_widget_12_hours_format" translatable="false">h\uee01mm</string> <!-- Time format strings for fall-back clock widget --> <string name="keyguard_widget_24_hours_format" translatable="false">kk\uee01mm</string> + <!-- The character used in keyguard_widget_12_hours_format and keyguard_widget_24_hours_format + to represent a ":". --> + <string name="keyguard_fancy_colon" translatable="false">\uee01</string> <!-- Accessibility description of the PIN password view. [CHAR_LIMIT=none] --> <string name="keyguard_accessibility_pin_area">PIN area</string> diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml index 0c9858dc8397..6fe00c02508f 100644 --- a/packages/SystemUI/res/layout/notification_info.xml +++ b/packages/SystemUI/res/layout/notification_info.xml @@ -74,8 +74,9 @@ android:orientation="horizontal"> <!-- Channel Text --> <LinearLayout - android:layout_width="wrap_content" + android:layout_width="0dp" android:layout_height="wrap_content" + android:layout_weight="1" android:orientation="vertical"> <!-- Channel Name --> <TextView @@ -113,7 +114,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="end|center_vertical" - android:layout_weight="1" android:contentDescription="@string/notification_channel_switch_accessibility" android:background="@null" /> </LinearLayout> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockAccessibilityDelegate.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockAccessibilityDelegate.java new file mode 100644 index 000000000000..80509a689a64 --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockAccessibilityDelegate.java @@ -0,0 +1,67 @@ +/* + * 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.keyguard; + +import android.content.Context; +import android.text.TextUtils; +import android.view.View; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; +import android.widget.TextView; + +/** + * Replaces fancy colons with regular colons. Only works on TextViews. + */ +class KeyguardClockAccessibilityDelegate extends View.AccessibilityDelegate { + private final String mFancyColon; + + public KeyguardClockAccessibilityDelegate(Context context) { + mFancyColon = context.getString(R.string.keyguard_fancy_colon); + } + + @Override + public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(host, event); + CharSequence text = event.getContentDescription(); + if (!TextUtils.isEmpty(text)) { + event.setContentDescription(replaceFancyColon(text)); + } + } + + @Override + public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { + CharSequence text = ((TextView) host).getText(); + if (!TextUtils.isEmpty(text)) { + event.getText().add(replaceFancyColon(text)); + } + } + + @Override + public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(host, info); + if (!TextUtils.isEmpty(info.getText())) { + info.setText(replaceFancyColon(info.getText())); + } + if (!TextUtils.isEmpty(info.getContentDescription())) { + info.setContentDescription(replaceFancyColon(info.getContentDescription())); + } + } + + private CharSequence replaceFancyColon(CharSequence text) { + return text.toString().replace(mFancyColon, ":"); + } +} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java index 162faa595ed3..d4d69ffd3b7c 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java @@ -38,7 +38,6 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.widget.LockPatternUtils; import com.android.systemui.ChargingView; -import java.util.Arrays; import java.util.Locale; public class KeyguardStatusView extends GridLayout { @@ -121,6 +120,7 @@ public class KeyguardStatusView extends GridLayout { mClockView = findViewById(R.id.clock_view); mDateView.setShowCurrentUserTime(true); mClockView.setShowCurrentUserTime(true); + mClockView.setAccessibilityDelegate(new KeyguardClockAccessibilityDelegate(mContext)); mOwnerInfo = findViewById(R.id.owner_info); mBatteryDoze = findViewById(R.id.battery_doze); mVisibleInDoze = new View[]{mBatteryDoze, mClockView}; diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 7a6ac571f9e0..67a29895958e 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -197,6 +197,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private int mFingerprintRunningState = FINGERPRINT_STATE_STOPPED; private LockPatternUtils mLockPatternUtils; + // If FP daemon dies, keyguard should retry after a short delay + private int mHardwareUnavailableRetryCount = 0; + private static final int HW_UNAVAILABLE_TIMEOUT = 3000; // ms + private static final int HW_UNAVAILABLE_RETRY_MAX = 3; + private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { @@ -471,6 +476,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } + private Runnable mRetryFingerprintAuthentication = new Runnable() { + @Override + public void run() { + Log.w(TAG, "Retrying fingerprint after HW unavailable, attempt " + + mHardwareUnavailableRetryCount); + updateFingerprintListeningState(); + } + }; + private void handleFingerprintError(int msgId, String errString) { if (msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED && mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING_RESTARTING) { @@ -479,6 +493,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } else { setFingerprintRunningState(FINGERPRINT_STATE_STOPPED); } + + if (msgId == FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE) { + if (mHardwareUnavailableRetryCount < HW_UNAVAILABLE_RETRY_MAX) { + mHardwareUnavailableRetryCount++; + mHandler.removeCallbacks(mRetryFingerprintAuthentication); + mHandler.postDelayed(mRetryFingerprintAuthentication, HW_UNAVAILABLE_TIMEOUT); + } + } + for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -940,6 +963,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } private void handleScreenTurnedOff() { + mHardwareUnavailableRetryCount = 0; final int count = mCallbacks.size(); for (int i = 0; i < count; i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); @@ -1072,6 +1096,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } private void updateFingerprintListeningState() { + mHandler.removeCallbacks(mRetryFingerprintAuthentication); boolean shouldListenForFingerprint = shouldListenForFingerprint(); if (mFingerprintRunningState == FINGERPRINT_STATE_RUNNING && !shouldListenForFingerprint) { stopListeningForFingerprint(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java index b5c1bd9ff9db..dc9176f66bb2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java @@ -240,7 +240,7 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener i.setPackage(mComponent.getPackageName()); i = resolveIntent(i); if (i != null) { - i.putExtra(TileService.EXTRA_COMPONENT, mComponent); + i.putExtra(Intent.EXTRA_COMPONENT_NAME, mComponent); i.putExtra(TileService.EXTRA_STATE, mTile.getState()); return i; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java index d9c3cc3fd61f..d2f3bb603077 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java @@ -313,7 +313,7 @@ public class TileServices extends IQSService.Stub { public void onReceive(Context context, Intent intent) { if (TileService.ACTION_REQUEST_LISTENING.equals(intent.getAction())) { requestListening( - (ComponentName) intent.getParcelableExtra(TileService.EXTRA_COMPONENT)); + (ComponentName) intent.getParcelableExtra(Intent.EXTRA_COMPONENT_NAME)); } } }; diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java index 0b4498c487a8..802cb8315484 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java @@ -161,50 +161,7 @@ class BackgroundTaskLoader implements Runnable { // If we've stopped the loader, then fall through to the above logic to wait on // the load thread if (ssp != null) { - // Load the next item from the queue - final Task t = mLoadQueue.nextTask(); - if (t != null) { - Drawable cachedIcon = mIconCache.get(t.key); - - // Load the icon if it is stale or we haven't cached one yet - if (cachedIcon == null) { - cachedIcon = ssp.getBadgedTaskDescriptionIcon(t.taskDescription, - t.key.userId, mContext.getResources()); - - if (cachedIcon == null) { - ActivityInfo info = ssp.getActivityInfo( - t.key.getComponent(), t.key.userId); - if (info != null) { - if (DEBUG) Log.d(TAG, "Loading icon: " + t.key); - cachedIcon = ssp.getBadgedActivityIcon(info, t.key.userId); - } - } - - if (cachedIcon == null) { - cachedIcon = mDefaultIcon; - } - - // At this point, even if we can't load the icon, we will set the - // default icon. - mIconCache.put(t.key, cachedIcon); - } - - if (DEBUG) Log.d(TAG, "Loading thumbnail: " + t.key); - ThumbnailData cachedThumbnailData = ssp.getTaskThumbnail(t.key.id, - true /* reducedResolution */); - - if (cachedThumbnailData.thumbnail == null) { - cachedThumbnailData.thumbnail = mDefaultThumbnail; - } - - if (!mCancelled) { - // Notify that the task data has changed - final Drawable newIcon = cachedIcon; - final ThumbnailData newThumbnailData = cachedThumbnailData; - mMainThreadHandler.post( - () -> t.notifyTaskDataLoaded(newThumbnailData, newIcon)); - } - } + processLoadQueueItem(ssp); } // If there are no other items in the list, then just wait until something is added @@ -222,6 +179,57 @@ class BackgroundTaskLoader implements Runnable { } } } + + /** + * This needs to be in a separate method to work around an surprising interpreter behavior: + * The register will keep the local reference to cachedThumbnailData even if it falls out of + * scope. Putting it into a method fixes this issue. + */ + private void processLoadQueueItem(SystemServicesProxy ssp) { + // Load the next item from the queue + final Task t = mLoadQueue.nextTask(); + if (t != null) { + Drawable cachedIcon = mIconCache.get(t.key); + + // Load the icon if it is stale or we haven't cached one yet + if (cachedIcon == null) { + cachedIcon = ssp.getBadgedTaskDescriptionIcon(t.taskDescription, + t.key.userId, mContext.getResources()); + + if (cachedIcon == null) { + ActivityInfo info = ssp.getActivityInfo( + t.key.getComponent(), t.key.userId); + if (info != null) { + if (DEBUG) Log.d(TAG, "Loading icon: " + t.key); + cachedIcon = ssp.getBadgedActivityIcon(info, t.key.userId); + } + } + + if (cachedIcon == null) { + cachedIcon = mDefaultIcon; + } + + // At this point, even if we can't load the icon, we will set the + // default icon. + mIconCache.put(t.key, cachedIcon); + } + + if (DEBUG) Log.d(TAG, "Loading thumbnail: " + t.key); + final ThumbnailData cachedThumbnailData = ssp.getTaskThumbnail(t.key.id, + true /* reducedResolution */); + + if (cachedThumbnailData.thumbnail == null) { + cachedThumbnailData.thumbnail = mDefaultThumbnail; + } + + if (!mCancelled) { + // Notify that the task data has changed + final Drawable finalIcon = cachedIcon; + mMainThreadHandler.post( + () -> t.notifyTaskDataLoaded(cachedThumbnailData, finalIcon)); + } + } + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java index 469f3ad45c56..d7eab9772677 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java @@ -172,6 +172,11 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView private int mOverrideTint; private float mOverrideAmount; private boolean mShadowHidden; + private boolean mWasActivatedOnDown; + /** + * Similar to mDimmed but is also true if it's not dimmable but should be + */ + private boolean mNeedsDimming; public ActivatableNotificationView(Context context, AttributeSet attrs) { super(context, attrs); @@ -223,7 +228,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView @Override public boolean onInterceptTouchEvent(MotionEvent ev) { - if (mDimmed && !mActivated && ev.getActionMasked() == MotionEvent.ACTION_DOWN + if (mNeedsDimming && !mActivated && ev.getActionMasked() == MotionEvent.ACTION_DOWN && disallowSingleClick(ev) && !isTouchExplorationEnabled()) { return true; } @@ -245,7 +250,10 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView @Override public boolean onTouchEvent(MotionEvent event) { boolean result; - if (mDimmed && !isTouchExplorationEnabled() && isInteractive()) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + mWasActivatedOnDown = mActivated; + } + if ((mNeedsDimming && !mActivated) && !isTouchExplorationEnabled() && isInteractive()) { boolean wasActivated = mActivated; result = handleTouchEventDimmed(event); if (wasActivated && result && event.getAction() == MotionEvent.ACTION_UP) { @@ -282,9 +290,21 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView } private boolean handleTouchEventDimmed(MotionEvent event) { + if (mNeedsDimming && !mDimmed) { + // We're actually dimmed, but our content isn't dimmable, let's ensure we have a ripple + super.onTouchEvent(event); + } return mDoubleTapHelper.onTouchEvent(event, getActualHeight()); } + @Override + public boolean performClick() { + if (mWasActivatedOnDown || !mNeedsDimming) { + return super.performClick(); + } + return false; + } + private void makeActive() { mFalsingManager.onNotificationActive(); startActivateAnimation(false /* reverse */); @@ -298,6 +318,9 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView if (!isAttachedToWindow()) { return; } + if (!isDimmable()) { + return; + } int widthHalf = mBackgroundNormal.getWidth()/2; int heightHalf = mBackgroundNormal.getActualHeight()/2; float radius = (float) Math.sqrt(widthHalf*widthHalf + heightHalf*heightHalf); @@ -371,6 +394,8 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView } public void setDimmed(boolean dimmed, boolean fade) { + mNeedsDimming = dimmed; + dimmed &= isDimmable(); if (mDimmed != dimmed) { mDimmed = dimmed; resetBackgroundAlpha(); @@ -382,6 +407,10 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView } } + public boolean isDimmable() { + return true; + } + public void setDark(boolean dark, boolean fade, long delay) { super.setDark(dark, fade, delay); if (mDark == dark) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index dff09bda8844..8c1b334fe570 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -16,7 +16,7 @@ package com.android.systemui.statusbar; -import static com.android.systemui.statusbar.notification.NotificationInflater.InflationExceptionHandler; +import static com.android.systemui.statusbar.notification.NotificationInflater.InflationCallback; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -47,6 +47,7 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.RemoteViews; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.NotificationColorUtil; @@ -61,7 +62,6 @@ import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem; import com.android.systemui.statusbar.NotificationGuts.GutsContent; import com.android.systemui.statusbar.notification.HybridNotificationView; -import com.android.systemui.statusbar.notification.InflationException; import com.android.systemui.statusbar.notification.NotificationInflater; import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.notification.VisualStabilityManager; @@ -314,14 +314,13 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } } - public void updateNotification(NotificationData.Entry entry) throws InflationException { + public void updateNotification(NotificationData.Entry entry) { mEntry = entry; mStatusBarNotification = entry.notification; mNotificationInflater.inflateNotificationViews(); - onNotificationUpdated(); } - private void onNotificationUpdated() { + public void onNotificationUpdated() { for (NotificationContentView l : mLayouts) { l.onNotificationUpdated(mEntry); } @@ -361,6 +360,14 @@ public class ExpandableNotificationRow extends ActivatableNotificationView expandedIcon.setStaticDrawableColor(color); } + @Override + public boolean isDimmable() { + if (!getShowingLayout().isDimmable()) { + return false; + } + return super.isDimmable(); + } + private void updateLimits() { for (NotificationContentView l : mLayouts) { updateLimitsForView(l); @@ -482,9 +489,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView boolean childInGroup = StatusBar.ENABLE_CHILD_NOTIFICATIONS && isChildInGroup; mNotificationParent = childInGroup ? parent : null; mPrivateLayout.setIsChildInGroup(childInGroup); - if (mNotificationInflater.setIsChildInGroup(childInGroup)) { - onNotificationUpdated(); - } + mNotificationInflater.setIsChildInGroup(childInGroup); resetBackgroundAlpha(); updateBackgroundForGroupState(); updateClickAndFocus(); @@ -1111,14 +1116,19 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mNotificationInflater.setRemoteViewClickHandler(remoteViewClickHandler); } - public void setInflateExceptionHandler(InflationExceptionHandler inflateExceptionHandler) { - mNotificationInflater.setInflateExceptionHandler(inflateExceptionHandler); + public void setInflationCallback(InflationCallback callback) { + mNotificationInflater.setInflationCallback(callback); } public void setNeedsRedaction(boolean needsRedaction) { mNotificationInflater.setRedactAmbient(needsRedaction); } + @VisibleForTesting + public NotificationInflater getNotificationInflater() { + return mNotificationInflater; + } + public interface ExpansionLogger { public void logNotificationExpansion(String key, boolean userAction, boolean expanded); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java index 609856522e75..e7bf98336e8c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java @@ -1363,4 +1363,11 @@ public class NotificationContentView extends FrameLayout { public void setIsLowPriority(boolean isLowPriority) { mIsLowPriority = isLowPriority; } + + public boolean isDimmable() { + if (!mContractedWrapper.isDimmable()) { + return false; + } + return true; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java index 90e908b0a468..4d47e6b04aa9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java @@ -24,6 +24,7 @@ import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.Context; import android.graphics.drawable.Icon; +import android.os.AsyncTask; import android.os.RemoteException; import android.os.SystemClock; import android.service.notification.NotificationListenerService; @@ -32,6 +33,7 @@ import android.service.notification.NotificationListenerService.RankingMap; import android.service.notification.SnoozeCriterion; import android.service.notification.StatusBarNotification; import android.util.ArrayMap; +import android.util.ArraySet; import android.view.View; import android.widget.ImageView; import android.widget.RemoteViews; @@ -41,6 +43,7 @@ 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; +import com.android.systemui.statusbar.notification.NotificationInflater; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.HeadsUpManager; @@ -83,6 +86,7 @@ public class NotificationData { public List<SnoozeCriterion> snoozeCriteria; private int mCachedContrastColor = COLOR_INVALID; private int mCachedContrastColorIsFor = COLOR_INVALID; + private ArraySet<AsyncTask> mRunningTasks = new ArraySet(); public Entry(StatusBarNotification n) { this.key = n.getKey(); @@ -210,6 +214,29 @@ public class NotificationData { mCachedContrastColor = contrasted; return mCachedContrastColor; } + + /** + * Abort all existing inflation tasks + */ + public void abortInflation() { + for (AsyncTask task : mRunningTasks) { + task.cancel(true /* mayInterruptIfRunning */); + } + mRunningTasks.clear(); + } + + public void addInflationTask(AsyncTask asyncInflationTask) { + mRunningTasks.add(asyncInflationTask); + } + + public void onInflationTaskFinished(AsyncTask asyncInflationTask) { + mRunningTasks.remove(asyncInflationTask); + } + + @VisibleForTesting + public ArraySet<AsyncTask> getRunningTasks() { + return mRunningTasks; + } } private final ArrayMap<String, Entry> mEntries = new ArrayMap<>(); @@ -302,12 +329,12 @@ public class NotificationData { return mEntries.get(key); } - public void add(Entry entry, RankingMap ranking) { + public void add(Entry entry) { synchronized (mEntries) { mEntries.put(entry.notification.getKey(), entry); } mGroupManager.onEntryAdded(entry); - updateRankingAndSort(ranking); + filterAndSort(); } public Entry remove(String key, RankingMap ranking) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java new file mode 100644 index 000000000000..82910b8bf967 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.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.statusbar.notification; + +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Shader; +import android.graphics.Xfermode; +import android.graphics.drawable.Drawable; + +/** + * A utility class to colorize bitmaps with a color gradient and a special blending mode + */ +public class ImageGradientColorizer { + public Bitmap colorize(Drawable drawable, int backgroundColor) { + int width = drawable.getIntrinsicWidth(); + int height = drawable.getIntrinsicHeight(); + int size = Math.min(width, height); + int widthInset = (width - size) / 2; + int heightInset = (height - size) / 2; + drawable = drawable.mutate(); + drawable.setBounds(- widthInset, - heightInset, width - widthInset, height - heightInset); + Bitmap newBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(newBitmap); + + // Values to calculate the luminance of a color + float lr = 0.2126f; + float lg = 0.7152f; + float lb = 0.0722f; + + // Extract the red, green, blue components of the color extraction color in + // float and int form + int tri = Color.red(backgroundColor); + int tgi = Color.green(backgroundColor); + int tbi = Color.blue(backgroundColor); + + float tr = tri / 255f; + float tg = tgi / 255f; + float tb = tbi / 255f; + + // Calculate the luminance of the color extraction color + float cLum = (tr * lr + tg * lg + tb * lb) * 255; + + ColorMatrix m = new ColorMatrix(new float[] { + lr, lg, lb, 0, tri - cLum, + lr, lg, lb, 0, tgi - cLum, + lr, lg, lb, 0, tbi - cLum, + 0, 0, 0, 1, 0, + }); + + drawable.setColorFilter(new ColorMatrixColorFilter(m)); + drawable.draw(canvas); + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + LinearGradient linearGradient = new LinearGradient(0, 0, size, 0, + new int[] {0, Color.argb(0.5f, 1, 1, 1), Color.BLACK}, + new float[] {0.0f, 0.4f, 1.0f}, Shader.TileMode.CLAMP); + paint.setShader(linearGradient); + Bitmap fadeIn = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); + Canvas fadeInCanvas = new Canvas(fadeIn); + drawable.clearColorFilter(); + drawable.draw(fadeInCanvas); + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); + fadeInCanvas.drawPaint(paint); + canvas.drawBitmap(fadeIn, 0, 0, null); + + linearGradient = new LinearGradient(0, 0, size, 0, + new int[] {backgroundColor, Color.argb(0.5f, tr, tg, tb), 0}, + new float[] {0.0f, 0.6f, 1.0f}, Shader.TileMode.CLAMP); + paint.setShader(linearGradient); + paint.setXfermode(null); + canvas.drawPaint(paint); + return newBitmap; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java new file mode 100644 index 000000000000..cef225b0e80e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java @@ -0,0 +1,259 @@ +/* + * 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 android.app.Notification; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; +import android.support.v4.graphics.ColorUtils; +import android.support.v7.graphics.Palette; + +import com.android.systemui.R; + +import java.util.List; + +/** + * A class the processes media notifications and extracts the right text and background colors. + */ +public class MediaNotificationProcessor { + + /** + * The fraction below which we select the vibrant instead of the light/dark vibrant color + */ + private static final float POPULATION_FRACTION_FOR_MORE_VIBRANT = 0.75f; + private static final float POPULATION_FRACTION_FOR_WHITE_OR_BLACK = 2.5f; + private static final float BLACK_MAX_LIGHTNESS = 0.08f; + private static final float WHITE_MIN_LIGHTNESS = 0.92f; + private static final int RESIZE_BITMAP_AREA = 150 * 150; + private final ImageGradientColorizer mColorizer; + private final Context mContext; + private float[] mFilteredBackgroundHsl = null; + private Palette.Filter mBlackWhiteFilter = (rgb, hsl) -> !isWhiteOrBlack(hsl); + + /** + * The context of the notification. This is the app context of the package posting the + * notification. + */ + private final Context mPackageContext; + private boolean mIsLowPriority; + + public MediaNotificationProcessor(Context context, Context packageContext) { + mContext = context; + mPackageContext = packageContext; + mColorizer = new ImageGradientColorizer(); + } + + /** + * Processes a builder of a media notification and calculates the appropriate colors that should + * be used. + * + * @param notification the notification that is being processed + * @param builder the recovered builder for the notification. this will be modified + */ + public void processNotification(Notification notification, Notification.Builder builder) { + Icon largeIcon = notification.getLargeIcon(); + Bitmap bitmap = null; + Drawable drawable = null; + if (largeIcon != null) { + drawable = largeIcon.loadDrawable(mPackageContext); + int backgroundColor = 0; + if (notification.isColorizedMedia()) { + int width = drawable.getIntrinsicWidth(); + int height = drawable.getIntrinsicHeight(); + int area = width * height; + if (area > RESIZE_BITMAP_AREA) { + double factor = Math.sqrt((float) RESIZE_BITMAP_AREA / area); + width = (int) (factor * width); + height = (int) (factor * height); + } + bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, width, height); + drawable.draw(canvas); + + // for the background we only take the left side of the image to ensure + // a smooth transition + Palette.Builder paletteBuilder = Palette.from(bitmap) + .setRegion(0, 0, bitmap.getWidth() / 2, bitmap.getHeight()) + .clearFilters() // we want all colors, red / white / black ones too! + .resizeBitmapArea(RESIZE_BITMAP_AREA); + Palette palette = paletteBuilder.generate(); + backgroundColor = findBackgroundColorAndFilter(palette); + // we want the full region again + paletteBuilder.setRegion(0, 0, bitmap.getWidth(), bitmap.getHeight()); + if (mFilteredBackgroundHsl != null) { + paletteBuilder.addFilter((rgb, hsl) -> { + // at least 10 degrees hue difference + float diff = Math.abs(hsl[0] - mFilteredBackgroundHsl[0]); + return diff > 10 && diff < 350; + }); + } + paletteBuilder.addFilter(mBlackWhiteFilter); + palette = paletteBuilder.generate(); + int foregroundColor; + if (ColorUtils.calculateLuminance(backgroundColor) > 0.5) { + Palette.Swatch first = palette.getDarkVibrantSwatch(); + Palette.Swatch second = palette.getVibrantSwatch(); + if (first != null && second != null) { + int firstPopulation = first.getPopulation(); + int secondPopulation = second.getPopulation(); + if (firstPopulation / secondPopulation + < POPULATION_FRACTION_FOR_MORE_VIBRANT) { + foregroundColor = second.getRgb(); + } else { + foregroundColor = first.getRgb(); + } + } else if (first != null) { + foregroundColor = first.getRgb(); + } else if (second != null) { + foregroundColor = second.getRgb(); + } else { + first = palette.getMutedSwatch(); + second = palette.getDarkMutedSwatch(); + if (first != null && second != null) { + float firstSaturation = first.getHsl()[1]; + float secondSaturation = second.getHsl()[1]; + if (firstSaturation > secondSaturation) { + foregroundColor = first.getRgb(); + } else { + foregroundColor = second.getRgb(); + } + } else if (first != null) { + foregroundColor = first.getRgb(); + } else if (second != null) { + foregroundColor = second.getRgb(); + } else { + foregroundColor = Color.BLACK; + } + } + } else { + Palette.Swatch first = palette.getLightVibrantSwatch(); + Palette.Swatch second = palette.getVibrantSwatch(); + if (first != null && second != null) { + int firstPopulation = first.getPopulation(); + int secondPopulation = second.getPopulation(); + if (firstPopulation / secondPopulation + < POPULATION_FRACTION_FOR_MORE_VIBRANT) { + foregroundColor = second.getRgb(); + } else { + foregroundColor = first.getRgb(); + } + } else if (first != null) { + foregroundColor = first.getRgb(); + } else if (second != null) { + foregroundColor = second.getRgb(); + } else { + first = palette.getMutedSwatch(); + second = palette.getLightMutedSwatch(); + if (first != null && second != null) { + float firstSaturation = first.getHsl()[1]; + float secondSaturation = second.getHsl()[1]; + if (firstSaturation > secondSaturation) { + foregroundColor = first.getRgb(); + } else { + foregroundColor = second.getRgb(); + } + } else if (first != null) { + foregroundColor = first.getRgb(); + } else if (second != null) { + foregroundColor = second.getRgb(); + } else { + foregroundColor = Color.WHITE; + } + } + } + builder.setColorPalette(backgroundColor, foregroundColor); + } else { + int id = mIsLowPriority + ? R.color.notification_material_background_low_priority_color + : R.color.notification_material_background_color; + backgroundColor = mContext.getColor(id); + } + Bitmap colorized = mColorizer.colorize(drawable, backgroundColor); + builder.setLargeIcon(Icon.createWithBitmap(colorized)); + } + } + + private int findBackgroundColorAndFilter(Palette palette) { + // by default we use the dominant palette + Palette.Swatch dominantSwatch = palette.getDominantSwatch(); + if (dominantSwatch == null) { + // We're not filtering on white or black + mFilteredBackgroundHsl = null; + return Color.WHITE; + } + + if (!isWhiteOrBlack(dominantSwatch.getHsl())) { + mFilteredBackgroundHsl = dominantSwatch.getHsl(); + return dominantSwatch.getRgb(); + } + // Oh well, we selected black or white. Lets look at the second color! + List<Palette.Swatch> swatches = palette.getSwatches(); + float highestNonWhitePopulation = -1; + Palette.Swatch second = null; + for (Palette.Swatch swatch: swatches) { + if (swatch != dominantSwatch + && swatch.getPopulation() > highestNonWhitePopulation + && !isWhiteOrBlack(swatch.getHsl())) { + second = swatch; + highestNonWhitePopulation = swatch.getPopulation(); + } + } + if (second == null) { + // We're not filtering on white or black + mFilteredBackgroundHsl = null; + return dominantSwatch.getRgb(); + } + if (dominantSwatch.getPopulation() / highestNonWhitePopulation + > POPULATION_FRACTION_FOR_WHITE_OR_BLACK) { + // The dominant swatch is very dominant, lets take it! + // We're not filtering on white or black + mFilteredBackgroundHsl = null; + return dominantSwatch.getRgb(); + } else { + mFilteredBackgroundHsl = second.getHsl(); + return second.getRgb(); + } + } + + private boolean isWhiteOrBlack(float[] hsl) { + return isBlack(hsl) || isWhite(hsl); + } + + + /** + * @return true if the color represents a color which is close to black. + */ + private boolean isBlack(float[] hslColor) { + return hslColor[2] <= BLACK_MAX_LIGHTNESS; + } + + /** + * @return true if the color represents a color which is close to white. + */ + private boolean isWhite(float[] hslColor) { + return hslColor[2] >= WHITE_MIN_LIGHTNESS; + } + + public void setIsLowPriority(boolean isLowPriority) { + mIsLowPriority = isLowPriority; + } +} 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 2e34f2483a85..7cfc767f89b7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java @@ -18,11 +18,10 @@ package com.android.systemui.statusbar.notification; import android.app.Notification; import android.content.Context; +import android.os.AsyncTask; import android.service.notification.StatusBarNotification; import android.util.Log; import android.view.View; -import android.view.ViewGroup; -import android.view.ViewParent; import android.widget.RemoteViews; import com.android.internal.annotations.VisibleForTesting; @@ -39,7 +38,8 @@ public class NotificationInflater { @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; + @VisibleForTesting + static final int FLAG_REINFLATE_EXPANDED_VIEW = 1<<1; private static final int FLAG_REINFLATE_HEADS_UP_VIEW = 1<<2; private static final int FLAG_REINFLATE_PUBLIC_VIEW = 1<<3; private static final int FLAG_REINFLATE_AMBIENT_VIEW = 1<<4; @@ -50,7 +50,7 @@ public class NotificationInflater { private boolean mUsesIncreasedHeadsUpHeight; private RemoteViews.OnClickHandler mRemoteViewClickHandler; private boolean mIsChildInGroup; - private InflationExceptionHandler mInflateExceptionHandler; + private InflationCallback mCallback; private boolean mRedactAmbient; public NotificationInflater(ExpandableNotificationRow row) { @@ -66,21 +66,14 @@ public class NotificationInflater { * * @return whether the view was re-inflated */ - public boolean setIsChildInGroup(boolean childInGroup) { + public void setIsChildInGroup(boolean childInGroup) { if (childInGroup != mIsChildInGroup) { mIsChildInGroup = childInGroup; if (mIsLowPriority) { - try { - int flags = FLAG_REINFLATE_CONTENT_VIEW | FLAG_REINFLATE_EXPANDED_VIEW; - inflateNotificationViews(flags); - } catch (InflationException e) { - mInflateExceptionHandler.handleInflationException( - mRow.getStatusBarNotification(), e); - } + int flags = FLAG_REINFLATE_CONTENT_VIEW | FLAG_REINFLATE_EXPANDED_VIEW; + inflateNotificationViews(flags); } - return true; - } - return false; + } ; } public void setUsesIncreasedHeight(boolean usesIncreasedHeight) { @@ -101,39 +94,29 @@ public class NotificationInflater { if (mRow.getEntry() == null) { return; } - try { - inflateNotificationViews(FLAG_REINFLATE_AMBIENT_VIEW); - } catch (InflationException e) { - mInflateExceptionHandler.handleInflationException( - mRow.getStatusBarNotification(), e); - } + inflateNotificationViews(FLAG_REINFLATE_AMBIENT_VIEW); } } - public void inflateNotificationViews() throws InflationException { + /** + * Inflate all views of this notification on a background thread. This is asynchronous and will + * notify the callback once it's finished. + */ + public void inflateNotificationViews() { inflateNotificationViews(FLAG_REINFLATE_ALL); } /** - * reinflate all views for the specified flags + * Reinflate all views for the specified flags on a background thread. This is asynchronous and + * will notify the callback once it's finished. + * * @param reInflateFlags flags which views should be reinflated. Use {@link #FLAG_REINFLATE_ALL} * to reinflate all of views. - * @throws InflationException */ - private void inflateNotificationViews(int reInflateFlags) - throws InflationException { + @VisibleForTesting + void inflateNotificationViews(int reInflateFlags) { StatusBarNotification sbn = mRow.getEntry().notification; - try { - final Notification.Builder recoveredBuilder - = 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()); - Log.e(StatusBar.TAG, "couldn't inflate view for notification " + ident, e); - throw new InflationException("Couldn't inflate contentViews"); - } + new AsyncInflationTask(mRow.getContext(), sbn, reInflateFlags).execute(); } @VisibleForTesting @@ -284,12 +267,13 @@ public class NotificationInflater { && a.getLayoutId() == b.getLayoutId()); } - public void setInflateExceptionHandler(InflationExceptionHandler inflateExceptionHandler) { - mInflateExceptionHandler = inflateExceptionHandler; + public void setInflationCallback(InflationCallback callback) { + mCallback = callback; } - public interface InflationExceptionHandler { + public interface InflationCallback { void handleInflationException(StatusBarNotification notification, InflationException e); + void onAsyncInflationFinished(NotificationData.Entry entry); } public void onDensityOrFontScaleChanged() { @@ -299,12 +283,75 @@ public class NotificationInflater { entry.cachedContentView = null; entry.cachedHeadsUpContentView = null; entry.cachedPublicContentView = null; + inflateNotificationViews(); + } + + private class AsyncInflationTask extends AsyncTask<Void, Void, Notification.Builder> { + + private final StatusBarNotification mSbn; + private final Context mContext; + private final int mReInflateFlags; + private Context mPackageContext = null; + private Exception mError; + + private AsyncInflationTask(Context context, StatusBarNotification notification, + int reInflateFlags) { + mSbn = notification; + mContext = context; + mReInflateFlags = reInflateFlags; + mRow.getEntry().addInflationTask(this); + } + + @Override + protected Notification.Builder doInBackground(Void... params) { + try { + final Notification.Builder recoveredBuilder + = Notification.Builder.recoverBuilder(mContext, + mSbn.getNotification()); + mPackageContext = mSbn.getPackageContext(mContext); + Notification notification = mSbn.getNotification(); + if (notification.isMediaNotification()) { + MediaNotificationProcessor processor = new MediaNotificationProcessor(mContext, + mPackageContext); + processor.setIsLowPriority(mIsLowPriority); + processor.processNotification(notification, recoveredBuilder); + } + return recoveredBuilder; + } catch (Exception e) { + mError = e; + return null; + } + } + + @Override + protected void onPostExecute(Notification.Builder builder) { + mRow.getEntry().onInflationTaskFinished(this); + if (mError == null) { + finishInflation(mReInflateFlags, builder, mPackageContext); + } else { + handleError(mError); + } + } + } + + private void finishInflation(int reinflationFlags, Notification.Builder builder, + Context context) { try { - inflateNotificationViews(); - } catch (InflationException e) { - mInflateExceptionHandler.handleInflationException( - mRow.getStatusBarNotification(), e); + inflateNotificationViews(reinflationFlags, builder, context); + } catch (RuntimeException e){ + handleError(e); + return; } + mRow.onNotificationUpdated(); + mCallback.onAsyncInflationFinished(mRow.getEntry()); } + private void handleError(Exception e) { + StatusBarNotification sbn = mRow.getStatusBarNotification(); + final String ident = sbn.getPackageName() + "/0x" + + Integer.toHexString(sbn.getId()); + Log.e(StatusBar.TAG, "couldn't inflate view for notification " + ident, e); + mCallback.handleInflationException(sbn, + new InflationException("Couldn't inflate contentViews" + e)); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java index ef5a25ca5262..8596cb3e2e9a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java @@ -56,4 +56,9 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi mActions); } } + + @Override + public boolean isDimmable() { + return false; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java index f4db9a1977f3..5cc39cc27b26 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java @@ -178,4 +178,8 @@ public abstract class NotificationViewWrapper implements TransformableView { public void setIsChildInGroup(boolean isChildInGroup) { } + + public boolean isDimmable() { + return true; + } } 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 46d64153d04d..c1859fe43e01 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -22,7 +22,7 @@ import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN; import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; import static android.app.StatusBarManager.windowStateToString; -import static com.android.systemui.statusbar.notification.NotificationInflater.InflationExceptionHandler; +import static com.android.systemui.statusbar.notification.NotificationInflater.InflationCallback; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE; @@ -257,7 +257,7 @@ public class StatusBar extends SystemUI implements DemoMode, OnHeadsUpChangedListener, VisualStabilityManager.Callback, CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener, ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment, - ExpandableNotificationRow.OnExpandClickListener { + ExpandableNotificationRow.OnExpandClickListener, InflationCallback { public static final boolean MULTIUSER_DEBUG = false; public static final boolean ENABLE_REMOTE_INPUT = @@ -713,8 +713,8 @@ public class StatusBar extends SystemUI implements DemoMode, private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger(); private NotificationIconAreaController mNotificationIconAreaController; private ConfigurationListener mConfigurationListener; - private InflationExceptionHandler mInflationExceptionHandler = this::handleInflationException; private boolean mReinflateNotificationsOnUserSwitched; + private HashMap<String, Entry> mPendingNotifications = new HashMap<>(); private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) { final int N = array.size(); @@ -1544,29 +1544,24 @@ public class StatusBar extends SystemUI implements DemoMode, return new UserHandle(mCurrentUserId); } - public void addNotification(StatusBarNotification notification, RankingMap ranking, - Entry oldEntry) throws InflationException { - if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey()); + public void addNotification(StatusBarNotification notification, RankingMap ranking) + throws InflationException { + String key = notification.getKey(); + if (DEBUG) Log.d(TAG, "addNotification key=" + key); mNotificationData.updateRanking(ranking); Entry shadeEntry = createNotificationViews(notification); boolean isHeadsUped = shouldPeek(shadeEntry); - if (isHeadsUped) { - mHeadsUpManager.showNotification(shadeEntry); - // Mark as seen immediately - setNotificationShown(notification); - } - if (!isHeadsUped && notification.getNotification().fullScreenIntent != null) { - if (shouldSuppressFullScreenIntent(notification.getKey())) { + if (shouldSuppressFullScreenIntent(key)) { if (DEBUG) { - Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + notification.getKey()); + Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + key); } - } else if (mNotificationData.getImportance(notification.getKey()) + } else if (mNotificationData.getImportance(key) < NotificationManager.IMPORTANCE_HIGH) { if (DEBUG) { Log.d(TAG, "No Fullscreen intent: not important enough: " - + notification.getKey()); + + key); } } else { // Stop screensaver if the notification has a full-screen intent. @@ -1578,7 +1573,7 @@ public class StatusBar extends SystemUI implements DemoMode, Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent"); try { EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION, - notification.getKey()); + key); notification.getNotification().fullScreenIntent.send(); shadeEntry.notifyFullScreenIntentLaunched(); mMetricsLogger.count("note_fullscreen", 1); @@ -1586,15 +1581,47 @@ public class StatusBar extends SystemUI implements DemoMode, } } } - addNotificationViews(shadeEntry, ranking); + abortExistingInflation(key); + mPendingNotifications.put(key, shadeEntry); + } + + private void abortExistingInflation(String key) { + if (mPendingNotifications.containsKey(key)) { + Entry entry = mPendingNotifications.get(key); + entry.abortInflation(); + mPendingNotifications.remove(key); + } + Entry addedEntry = mNotificationData.get(key); + if (addedEntry != null) { + addedEntry.abortInflation(); + } + } + + private void addEntry(Entry shadeEntry) { + boolean isHeadsUped = shouldPeek(shadeEntry); + if (isHeadsUped) { + mHeadsUpManager.showNotification(shadeEntry); + // Mark as seen immediately + setNotificationShown(shadeEntry.notification); + } + addNotificationViews(shadeEntry); // Recalculate the position of the sliding windows and the titles. setAreThereNotifications(); } + @Override public void handleInflationException(StatusBarNotification notification, InflationException e) { handleNotificationError(notification, e.getMessage()); } + @Override + public void onAsyncInflationFinished(Entry entry) { + mPendingNotifications.remove(entry.key); + if (mNotificationData.get(entry.key) == null) { + addEntry(entry); + } + } + private boolean shouldSuppressFullScreenIntent(String key) { if (isDeviceInVrMode()) { return true; @@ -1614,6 +1641,7 @@ public class StatusBar extends SystemUI implements DemoMode, public void removeNotification(String key, RankingMap ranking) { boolean deferRemoval = false; + abortExistingInflation(key); if (mHeadsUpManager.isHeadsUp(key)) { // A cancel() in repsonse to a remote input shouldn't be delayed, as it makes the // sending look longer than it takes. @@ -3295,6 +3323,14 @@ public class StatusBar extends SystemUI implements DemoMode, + " scroll " + mStackScroller.getScrollX() + "," + mStackScroller.getScrollY()); } + pw.print(" mPendingNotifications="); + if (mPendingNotifications.size() == 0) { + pw.println("null"); + } else { + for (Entry entry : mPendingNotifications.values()) { + pw.println(entry.notification); + } + } pw.print(" mInteractingWindows="); pw.println(mInteractingWindows); pw.print(" mStatusBarWindowState="); @@ -5531,7 +5567,7 @@ public class StatusBar extends SystemUI implements DemoMode, public void run() { for (StatusBarNotification sbn : notifications) { try { - addNotification(sbn, currentRanking, null /* oldEntry */); + addNotification(sbn, currentRanking); } catch (InflationException e) { handleInflationException(sbn, e); } @@ -5574,7 +5610,7 @@ public class StatusBar extends SystemUI implements DemoMode, if (isUpdate) { updateNotification(sbn, rankingMap); } else { - addNotification(sbn, rankingMap, null /* oldEntry */); + addNotification(sbn, rankingMap); } } catch (InflationException e) { handleInflationException(sbn, e); @@ -6132,8 +6168,7 @@ public class StatusBar extends SystemUI implements DemoMode, } } - protected void inflateViews(Entry entry, ViewGroup parent) throws - InflationException { + protected void inflateViews(Entry entry, ViewGroup parent) { PackageManager pmUser = getPackageManagerForUser(mContext, entry.notification.getUser().getIdentifier()); @@ -6154,7 +6189,7 @@ public class StatusBar extends SystemUI implements DemoMode, row.setRemoteInputController(mRemoteInputController); row.setOnExpandClickListener(this); row.setRemoteViewClickHandler(mOnClickHandler); - row.setInflateExceptionHandler(mInflationExceptionHandler); + row.setInflationCallback(this); // Get the app name. // Note that Notification.Builder#bindHeaderAppName has similar logic @@ -6552,12 +6587,12 @@ public class StatusBar extends SystemUI implements DemoMode, return entry; } - protected void addNotificationViews(Entry entry, RankingMap ranking) { + protected void addNotificationViews(Entry entry) { if (entry == null) { return; } // Add the expanded view and icon. - mNotificationData.add(entry, ranking); + mNotificationData.add(entry); updateNotifications(); } @@ -6675,6 +6710,7 @@ public class StatusBar extends SystemUI implements DemoMode, if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")"); final String key = notification.getKey(); + abortExistingInflation(key); Entry entry = mNotificationData.get(key); if (entry == null) { return; diff --git a/packages/SystemUI/src/com/android/systemui/util/Assert.java b/packages/SystemUI/src/com/android/systemui/util/Assert.java index af447f3f74ec..0f7c9a462c0a 100644 --- a/packages/SystemUI/src/com/android/systemui/util/Assert.java +++ b/packages/SystemUI/src/com/android/systemui/util/Assert.java @@ -28,4 +28,10 @@ public class Assert { throw new IllegalStateException("should be called from the main thread."); } } + + public static void isNotMainThread() { + if (Looper.getMainLooper().isCurrentThread()) { + throw new IllegalStateException("should not be called from the main thread."); + } + } } diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk index 8eedf3145e61..5e8b3f905258 100644 --- a/packages/SystemUI/tests/Android.mk +++ b/packages/SystemUI/tests/Android.mk @@ -42,6 +42,7 @@ LOCAL_STATIC_ANDROID_LIBRARIES := \ android-support-v7-preference \ android-support-v7-appcompat \ android-support-v7-mediarouter \ + android-support-v7-palette \ android-support-v14-preference \ android-support-v17-leanback diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java new file mode 100644 index 000000000000..1c9f8133a15f --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.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.keyguard; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.text.TextUtils; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; +import android.widget.TextView; + +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + +public class KeyguardClockAccessibilityDelegateTest { + + private Context mContext; + private TextView mView; + + @Before + public void setUp() throws Exception { + mContext = InstrumentationRegistry.getContext(); + mView = new TextView(mContext); + mView.setText(R.string.keyguard_widget_12_hours_format); + mView.setContentDescription(mContext.getString(R.string.keyguard_widget_12_hours_format)); + mView.setAccessibilityDelegate(new KeyguardClockAccessibilityDelegate(mContext)); + } + + @Test + public void onInitializeAccessibilityEvent_producesNonEmptyAsciiContentDesc() throws Exception { + AccessibilityEvent ev = AccessibilityEvent.obtain(); + mView.onInitializeAccessibilityEvent(ev); + + assertFalse(TextUtils.isEmpty(ev.getContentDescription())); + assertTrue(isAscii(ev.getContentDescription())); + } + + @Test + public void onPopulateAccessibilityEvent_producesNonEmptyAsciiText() throws Exception { + AccessibilityEvent ev = AccessibilityEvent.obtain(); + mView.onPopulateAccessibilityEvent(ev); + + assertFalse(isEmpty(ev.getText())); + assertTrue(isAscii(ev.getText())); + } + + @Test + public void onInitializeAccessibilityNodeInfo_producesNonEmptyAsciiText() throws Exception { + AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(); + // Usually done in View.onInitializeAccessibilityNodeInfoInternal, but only when attached. + info.setContentDescription(mView.getContentDescription()); + mView.onInitializeAccessibilityNodeInfo(info); + + assertFalse(TextUtils.isEmpty(info.getText())); + assertTrue(isAscii(info.getText())); + + assertFalse(TextUtils.isEmpty(info.getContentDescription())); + assertTrue(isAscii(info.getContentDescription())); + } + + private boolean isAscii(CharSequence text) { + return text.chars().allMatch((i) -> i < 128); + } + + private boolean isAscii(List<CharSequence> texts) { + return texts.stream().allMatch(this::isAscii); + } + + private boolean isEmpty(List<CharSequence> texts) { + return texts.stream().allMatch(TextUtils::isEmpty); + } +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java index 1b5d4a4cb9cd..aa8409890336 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java @@ -43,12 +43,13 @@ public class ExpandHelperTest extends SysuiTestCase { private ExpandHelper.Callback mCallback; @Before - @UiThreadTest - public void setUp() { + public void setUp() throws Exception { Context context = getContext(); mRow = new NotificationTestHelper(context).createRow(); mCallback = mock(ExpandHelper.Callback.class); - mExpandHelper = new ExpandHelper(context, mCallback, 10, 100); + InstrumentationRegistry.getInstrumentation().runOnMainSync( + () -> mExpandHelper = new ExpandHelper(context, mCallback, 10, 100)); + } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java index 3db244048536..5cd092bc8b53 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java @@ -39,8 +39,7 @@ public class ExpandableNotificationRowTest { private NotificationTestHelper mNotificationTestHelper; @Before - @UiThreadTest - public void setUp() { + public void setUp() throws Exception { mContext = InstrumentationRegistry.getTargetContext(); mNotificationTestHelper = new NotificationTestHelper(mContext); mGroup = mNotificationTestHelper.createGroup(); 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 c91b269d6329..cb238ddbabaa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java @@ -17,15 +17,18 @@ package com.android.systemui.statusbar; import android.app.ActivityManager; +import android.app.Instrumentation; import android.app.Notification; import android.content.Context; import android.os.UserHandle; import android.service.notification.StatusBarNotification; +import android.support.test.InstrumentationRegistry; import android.view.LayoutInflater; import android.widget.RemoteViews; import com.android.systemui.R; import com.android.systemui.statusbar.notification.InflationException; +import com.android.systemui.statusbar.notification.NotificationInflaterTest; import com.android.systemui.statusbar.phone.NotificationGroupManager; /** @@ -34,14 +37,18 @@ import com.android.systemui.statusbar.phone.NotificationGroupManager; public class NotificationTestHelper { private final Context mContext; + private final Instrumentation mInstrumentation; private int mId; private final NotificationGroupManager mGroupManager = new NotificationGroupManager(); + private ExpandableNotificationRow mRow; + private InflationException mException; public NotificationTestHelper(Context context) { mContext = context; + mInstrumentation = InstrumentationRegistry.getInstrumentation(); } - public ExpandableNotificationRow createRow() { + public ExpandableNotificationRow createRow() throws Exception { Notification publicVersion = new Notification.Builder(mContext).setSmallIcon( R.drawable.ic_person) .setCustomContentView(new RemoteViews(mContext.getPackageName(), @@ -56,12 +63,15 @@ public class NotificationTestHelper { return createRow(notification); } - public ExpandableNotificationRow createRow(Notification notification) { + public ExpandableNotificationRow createRow(Notification notification) throws Exception { LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( mContext.LAYOUT_INFLATER_SERVICE); - ExpandableNotificationRow row = (ExpandableNotificationRow) inflater.inflate( - R.layout.status_bar_notification_row, - null, false); + mInstrumentation.runOnMainSync(() -> { + mRow = (ExpandableNotificationRow) inflater.inflate( + R.layout.status_bar_notification_row, + null, false); + }); + ExpandableNotificationRow row = mRow; row.setGroupManager(mGroupManager); UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser()); StatusBarNotification sbn = new StatusBarNotification("com.android.systemui", @@ -69,16 +79,13 @@ public class NotificationTestHelper { 2000, notification, mUser, null, System.currentTimeMillis()); NotificationData.Entry entry = new NotificationData.Entry(sbn); entry.row = row; - try { - entry.createIcons(mContext, sbn); - row.updateNotification(entry); - } catch (InflationException e) { - throw new RuntimeException(e.getMessage()); - } + entry.createIcons(mContext, sbn); + NotificationInflaterTest.runThenWaitForInflation(() -> row.updateNotification(entry), + row.getNotificationInflater()); return row; } - public ExpandableNotificationRow createGroup() { + public ExpandableNotificationRow createGroup() throws Exception { ExpandableNotificationRow row = createRow(); row.addChildNotification(createRow()); row.addChildNotification(createRow()); 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 000000000000..fbb25e5484ba --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java @@ -0,0 +1,176 @@ +/* + * 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.times; +import static org.mockito.Mockito.verify; + +import android.app.Notification; +import android.content.Context; +import android.service.notification.StatusBarNotification; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; +import android.widget.RemoteViews; + +import com.android.systemui.R; +import com.android.systemui.statusbar.ExpandableNotificationRow; +import com.android.systemui.statusbar.NotificationData; +import com.android.systemui.statusbar.NotificationTestHelper; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.concurrent.CountDownLatch; +import java.util.function.Function; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class NotificationInflaterTest { + + private Context mContext; + private NotificationInflater mNotificationInflater; + private Notification.Builder mBuilder; + private ExpandableNotificationRow mRow; + + @Before + public void setUp() throws Exception { + mContext = InstrumentationRegistry.getTargetContext(); + mBuilder = new Notification.Builder(mContext).setSmallIcon( + R.drawable.ic_person) + .setContentTitle("Title") + .setContentText("Text") + .setStyle(new Notification.BigTextStyle().bigText("big text")); + ExpandableNotificationRow row = new NotificationTestHelper(mContext).createRow( + mBuilder.build()); + mRow = spy(row); + mNotificationInflater = new NotificationInflater(mRow); + mNotificationInflater.setInflationCallback(new NotificationInflater.InflationCallback() { + @Override + public void handleInflationException(StatusBarNotification notification, + InflationException e) { + } + + @Override + public void onAsyncInflationFinished(NotificationData.Entry entry) { + } + }); + } + + @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); + } + + @Test + public void testInflationCallsUpdated() throws Exception { + runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(), + mNotificationInflater); + verify(mRow).onNotificationUpdated(); + } + + @Test + public void testInflationCallsOnlyRightMethod() throws Exception { + mRow.getPrivateLayout().removeAllViews(); + mRow.getEntry().cachedBigContentView = null; + runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews( + NotificationInflater.FLAG_REINFLATE_EXPANDED_VIEW), mNotificationInflater); + Assert.assertTrue(mRow.getPrivateLayout().getChildCount() == 1); + Assert.assertTrue(mRow.getPrivateLayout().getChildAt(0) + == mRow.getPrivateLayout().getExpandedChild()); + verify(mRow).onNotificationUpdated(); + } + + @Test + public void testInflationThrowsErrorDoesntCallUpdated() throws Exception { + mRow.getPrivateLayout().removeAllViews(); + mRow.getStatusBarNotification().getNotification().contentView + = new RemoteViews(mContext.getPackageName(), R.layout.status_bar); + runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(), + true /* expectingException */, mNotificationInflater); + Assert.assertTrue(mRow.getPrivateLayout().getChildCount() == 0); + verify(mRow, times(0)).onNotificationUpdated(); + } + + @Test + public void testAsyncTaskRemoved() throws Exception { + mRow.getEntry().abortInflation(); + runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(), + mNotificationInflater); + Assert.assertTrue(mRow.getEntry().getRunningTasks().size() == 0); + } + + public static void runThenWaitForInflation(Runnable block, + NotificationInflater inflater) throws Exception { + runThenWaitForInflation(block, false /* expectingException */, inflater); + } + + private static void runThenWaitForInflation(Runnable block, boolean expectingException, + NotificationInflater inflater) throws Exception { + com.android.systemui.util.Assert.isNotMainThread(); + CountDownLatch countDownLatch = new CountDownLatch(1); + final ExceptionHolder exceptionHolder = new ExceptionHolder(); + inflater.setInflationCallback(new NotificationInflater.InflationCallback() { + @Override + public void handleInflationException(StatusBarNotification notification, + InflationException e) { + if (!expectingException) { + exceptionHolder.setException(e); + } + countDownLatch.countDown(); + } + + @Override + public void onAsyncInflationFinished(NotificationData.Entry entry) { + if (expectingException) { + exceptionHolder.setException(new RuntimeException( + "Inflation finished even though there should be an error")); + } + countDownLatch.countDown(); + } + }); + block.run(); + countDownLatch.await(5, java.util.concurrent.TimeUnit.SECONDS); + if (exceptionHolder.mException != null) { + throw exceptionHolder.mException; + } + } + + private static class ExceptionHolder { + private Exception mException; + + public void setException(Exception exception) { + mException = exception; + } + } +} 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 deleted file mode 100644 index 0ec9c106a596..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationinflaterTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package 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/stack/NotificationChildrenContainerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java index dbe0de42fd0a..f051f3043224 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java @@ -42,8 +42,7 @@ public class NotificationChildrenContainerTest { private NotificationTestHelper mNotificationTestHelper; @Before - @UiThreadTest - public void setUp() { + public void setUp() throws Exception { mContext = InstrumentationRegistry.getTargetContext(); mNotificationTestHelper = new NotificationTestHelper(mContext); mGroup = mNotificationTestHelper.createGroup(); diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index dc082e137da8..cc6e43550710 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -3636,7 +3636,7 @@ message MetricsEvent { // OS: N ACTION_GET_CONTACT = 864; - // This values should never appear in log outputs - it is reserved for + // This value should never appear in log outputs - it is reserved for // internal platform metrics use. RESERVED_FOR_LOGBUILDER_PID = 865; @@ -3948,6 +3948,10 @@ message MetricsEvent { // OS: O NOTIFICATION_CHANNEL_LOCK_SCREEN_VIS = 942; + // This value should never appear in log outputs - it is reserved for + // internal platform metrics use. + RESERVED_FOR_LOGBUILDER_UID = 943; + // ---- End O Constants, all O constants go above this line ---- // Add new aosp constants above this line. diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index f61edc5e28ac..6b84c5fc9a49 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -19,14 +19,13 @@ package com.android.server.autofill; import static android.Manifest.permission.MANAGE_AUTO_FILL; import static android.content.Context.AUTOFILL_MANAGER_SERVICE; -import static com.android.server.autofill.Helper.DEBUG; -import static com.android.server.autofill.Helper.VERBOSE; +import static com.android.server.autofill.Helper.sDebug; +import static com.android.server.autofill.Helper.sVerbose; import static com.android.server.autofill.Helper.bundleToString; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; -import android.app.ActivityManagerInternal; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; @@ -39,6 +38,7 @@ import android.database.ContentObserver; import android.graphics.Rect; import android.net.Uri; import android.os.Binder; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -50,13 +50,12 @@ import android.os.UserManager; import android.os.UserManagerInternal; import android.provider.Settings; import android.service.autofill.FillEventHistory; -import android.text.TextUtils; import android.util.LocalLog; -import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; import android.view.autofill.AutofillId; +import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; import android.view.autofill.IAutoFillManager; import android.view.autofill.IAutoFillManagerClient; @@ -118,10 +117,6 @@ public final class AutofillManagerService extends SystemService { @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) { - final String reason = intent.getStringExtra("reason"); - if (VERBOSE) { - Slog.v(TAG, "close system dialogs: " + reason); - } mUi.hideAll(); } } @@ -132,6 +127,10 @@ public final class AutofillManagerService extends SystemService { mContext = context; mUi = new AutoFillUI(mContext); + final boolean debug = Build.IS_DEBUGGABLE; + Slog.i(TAG, "Setting debug to " + debug); + setDebugLocked(debug); + final IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); mContext.registerReceiver(mBroadcastReceiver, filter, null, FgThread.getHandler()); @@ -154,7 +153,7 @@ public final class AutofillManagerService extends SystemService { final boolean disabledBefore = mDisabledUsers.get(userId); if (disabledBefore == disabledNow) { // Nothing changed, do nothing. - if (DEBUG) { + if (sDebug) { Slog.d(TAG, "Restriction not changed for user " + userId + ": " + bundleToString(newRestrictions)); return; @@ -368,6 +367,42 @@ public final class AutofillManagerService extends SystemService { } } + // Called by Shell command. + void setLogLevel(int level) { + Slog.i(TAG, "setLogLevel(): " + level); + boolean debug = false; + boolean verbose = false; + if (level == AutofillManager.FLAG_ADD_CLIENT_VERBOSE) { + debug = verbose = true; + } else if (level == AutofillManager.FLAG_ADD_CLIENT_DEBUG) { + debug = true; + } + synchronized (mLock) { + setDebugLocked(debug); + setVerboseLocked(verbose); + } + } + + // Called by Shell command. + int getLogLevel() { + synchronized (mLock) { + if (sVerbose) return AutofillManager.FLAG_ADD_CLIENT_VERBOSE; + if (sDebug) return AutofillManager.FLAG_ADD_CLIENT_DEBUG; + return 0; + } + } + + private void setDebugLocked(boolean debug) { + com.android.server.autofill.Helper.sDebug = debug; + android.view.autofill.Helper.sDebug = debug; + } + + + private void setVerboseLocked(boolean verbose) { + com.android.server.autofill.Helper.sVerbose = verbose; + android.view.autofill.Helper.sVerbose = verbose; + } + /** * Removes a cached service for a given user. */ @@ -390,7 +425,7 @@ public final class AutofillManagerService extends SystemService { * Updates a cached service for a given user. */ private void updateCachedServiceLocked(int userId, boolean disabled) { - AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); + AutofillManagerServiceImpl service = getServiceForUserLocked(userId); if (service != null) { service.updateLocked(disabled); if (!service.isEnabled()) { @@ -399,24 +434,21 @@ public final class AutofillManagerService extends SystemService { } } - private IBinder getTopActivityForUser() { - final List<IBinder> topActivities = LocalServices - .getService(ActivityManagerInternal.class).getTopVisibleActivities(); - if (VERBOSE) { - Slog.v(TAG, "Top activities (" + topActivities.size() + "): " + topActivities); - } - if (topActivities.isEmpty()) { - Slog.w(TAG, "Could not get top activity"); - return null; - } - return topActivities.get(0); - } - final class AutoFillManagerServiceStub extends IAutoFillManager.Stub { @Override - public boolean addClient(IAutoFillManagerClient client, int userId) { + public int addClient(IAutoFillManagerClient client, int userId) { synchronized (mLock) { - return getServiceForUserLocked(userId).addClientLocked(client); + int flags = 0; + if (getServiceForUserLocked(userId).addClientLocked(client)) { + flags |= AutofillManager.FLAG_ADD_CLIENT_ENABLED; + } + if (sDebug) { + flags |= AutofillManager.FLAG_ADD_CLIENT_DEBUG; + } + if (sVerbose) { + flags |= AutofillManager.FLAG_ADD_CLIENT_VERBOSE; + } + return flags; } } @@ -509,12 +541,12 @@ public final class AutofillManagerService extends SystemService { @Override public void updateSession(int sessionId, AutofillId id, Rect bounds, - AutofillValue value, int flags, int userId) { + AutofillValue value, int action, int flags, int userId) { synchronized (mLock) { final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); if (service != null) { service.updateSessionLocked(sessionId, getCallingUid(), id, bounds, value, - flags); + action, flags); } } } @@ -568,24 +600,38 @@ public final class AutofillManagerService extends SystemService { @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; - synchronized (mLock) { - pw.print("Disabled users: "); pw.println(mDisabledUsers); - final int size = mServicesCache.size(); - pw.print("Cached services: "); - if (size == 0) { - pw.println("none"); - } else { - pw.println(size); - for (int i = 0; i < size; i++) { - pw.print("\nService at index "); pw.println(i); - final AutofillManagerServiceImpl impl = mServicesCache.valueAt(i); - impl.dumpLocked(" ", pw); + + boolean oldDebug = sDebug; + boolean oldVerbose = sVerbose; + try { + synchronized (mLock) { + oldDebug = sDebug; + oldVerbose = sVerbose; + setDebugLocked(true); + setVerboseLocked(true); + pw.print("Debug mode: "); pw.println(oldDebug); + pw.print("Verbose mode: "); pw.println(oldVerbose); + pw.print("Disabled users: "); pw.println(mDisabledUsers); + final int size = mServicesCache.size(); + pw.print("Cached services: "); + if (size == 0) { + pw.println("none"); + } else { + pw.println(size); + for (int i = 0; i < size; i++) { + pw.print("\nService at index "); pw.println(i); + final AutofillManagerServiceImpl impl = mServicesCache.valueAt(i); + impl.dumpLocked(" ", pw); + } } + mUi.dump(pw); } - mUi.dump(pw); + pw.println("Requests history:"); + mRequestsHistory.reverseDump(fd, pw, args); + } finally { + setDebugLocked(oldDebug); + setVerboseLocked(oldVerbose); } - pw.println("Requests history:"); - mRequestsHistory.reverseDump(fd, pw, args); } @Override diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 44a296e79b57..4507eae8d3d7 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -16,11 +16,10 @@ package com.android.server.autofill; -import static android.view.autofill.AutofillManager.FLAG_START_SESSION; +import static android.view.autofill.AutofillManager.ACTION_START_SESSION; import static android.view.autofill.AutofillManager.NO_SESSION; -import static com.android.server.autofill.Helper.DEBUG; -import static com.android.server.autofill.Helper.VERBOSE; +import static com.android.server.autofill.Helper.sVerbose; import android.annotation.NonNull; import android.annotation.Nullable; @@ -48,12 +47,9 @@ import android.service.autofill.FillResponse; import android.service.autofill.IAutoFillService; import android.text.TextUtils; import android.util.LocalLog; -import android.util.Log; -import android.util.PrintWriterPrinter; import android.util.Slog; import android.util.SparseArray; import android.view.autofill.AutofillId; -import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; import android.view.autofill.IAutoFillManagerClient; @@ -271,14 +267,14 @@ final class AutofillManagerServiceImpl { } final String historyItem = - "id=" + newSession.getId() + " uid=" + uid + " s=" + mInfo.getServiceInfo().packageName + "id=" + newSession.id + " uid=" + uid + " s=" + mInfo.getServiceInfo().packageName + " u=" + mUserId + " i=" + autofillId + " b=" + virtualBounds + " hc=" + hasCallback + " f=" + flags; mRequestsHistory.log(historyItem); - newSession.updateLocked(autofillId, virtualBounds, value, FLAG_START_SESSION); + newSession.updateLocked(autofillId, virtualBounds, value, ACTION_START_SESSION, flags); - return newSession.getId(); + return newSession.id; } void finishSessionLocked(int sessionId, int uid) { @@ -288,14 +284,15 @@ final class AutofillManagerServiceImpl { final Session session = mSessions.get(sessionId); if (session == null || uid != session.uid) { - Slog.w(TAG, "finishSessionLocked(): no session for " + sessionId + "(" + uid + ")"); + if (sVerbose) { + Slog.v(TAG, "finishSessionLocked(): no session for " + sessionId + "(" + uid + ")"); + } return; } final boolean finished = session.showSaveLocked(); - if (DEBUG) { - Log.d(TAG, "finishSessionLocked(): session finished on save? " + finished); - } + if (sVerbose) Slog.v(TAG, "finishSessionLocked(): session finished on save? " + finished); + if (finished) { session.removeSelfLocked(); } @@ -342,7 +339,7 @@ final class AutofillManagerServiceImpl { do { tries++; if (tries > MAX_SESSION_ID_CREATE_TRIES) { - Log.w(TAG, "Cannot create session in " + MAX_SESSION_ID_CREATE_TRIES + " tries"); + Slog.w(TAG, "Cannot create session in " + MAX_SESSION_ID_CREATE_TRIES + " tries"); return null; } @@ -350,9 +347,9 @@ final class AutofillManagerServiceImpl { } while (sessionId == NO_SESSION || mSessions.indexOfKey(sessionId) >= 0); final Session newSession = new Session(this, mUi, mContext, mHandlerCaller, mUserId, mLock, - sessionId, uid, activityToken, windowToken, appCallbackToken, hasCallback, flags, + sessionId, uid, activityToken, windowToken, appCallbackToken, hasCallback, mInfo.getServiceInfo().getComponentName(), packageName); - mSessions.put(newSession.getId(), newSession); + mSessions.put(newSession.id, newSession); return newSession; } @@ -396,17 +393,17 @@ final class AutofillManagerServiceImpl { } void updateSessionLocked(int sessionId, int uid, AutofillId autofillId, Rect virtualBounds, - AutofillValue value, int flags) { + AutofillValue value, int action, int flags) { final Session session = mSessions.get(sessionId); if (session == null || session.uid != uid) { - if (VERBOSE) { + if (sVerbose) { Slog.v(TAG, "updateSessionLocked(): session gone for " + sessionId + "(" + uid + ")"); } return; } - session.updateLocked(autofillId, virtualBounds, value, flags); + session.updateLocked(autofillId, virtualBounds, value, action, flags); } void removeSessionLocked(int sessionId) { @@ -426,9 +423,7 @@ final class AutofillManagerServiceImpl { } void destroyLocked() { - if (VERBOSE) { - Slog.v(TAG, "destroyLocked()"); - } + if (sVerbose) Slog.v(TAG, "destroyLocked()"); final int numSessions = mSessions.size(); for (int i = 0; i < numSessions; i++) { @@ -519,12 +514,6 @@ final class AutofillManagerServiceImpl { pw.println(mContext.getString(R.string.config_defaultAutofillService)); pw.print(prefix); pw.print("Disabled: "); pw.println(mDisabled); - if (VERBOSE && mInfo != null) { - // ServiceInfo dump is too noisy and redundant (it can be obtained through other dumps) - pw.print(prefix); pw.println("ServiceInfo:"); - mInfo.getServiceInfo().dump(new PrintWriterPrinter(pw), prefix + prefix); - } - final int size = mSessions.size(); if (size == 0) { pw.print(prefix); pw.println("No sessions"); diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java index 62226e3a6cfc..1b9c86ef59a9 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java @@ -18,10 +18,10 @@ package com.android.server.autofill; import static com.android.server.autofill.AutofillManagerService.RECEIVER_BUNDLE_EXTRA_SESSIONS; -import android.app.ActivityManager; import android.os.Bundle; import android.os.ShellCommand; import android.os.UserHandle; +import android.view.autofill.AutofillManager; import com.android.internal.os.IResultReceiver; @@ -51,6 +51,10 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand { return requestDestroy(pw); case "reset": return requestReset(); + case "get": + return requestGet(pw); + case "set": + return requestSet(pw); default: return handleDefaultCommands(cmd); } @@ -63,6 +67,12 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand { pw.println(" help"); pw.println(" Prints this help text."); pw.println(""); + pw.println(" get log_level "); + pw.println(" Gets the Autofill log level (off | debug | verbose)."); + pw.println(""); + pw.println(" set log_level [off | debug | verbose]"); + pw.println(" Sets the Autofill log level."); + pw.println(""); pw.println(" list sessions [--user USER_ID]"); pw.println(" List all pending sessions."); pw.println(""); @@ -75,6 +85,48 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand { } } + private int requestGet(PrintWriter pw) { + if (!isNextArgLogLevel(pw, "get")) { + return -1; + } + final int logLevel = mService.getLogLevel(); + switch (logLevel) { + case AutofillManager.FLAG_ADD_CLIENT_VERBOSE: + pw.println("verbose"); + return 0; + case AutofillManager.FLAG_ADD_CLIENT_DEBUG: + pw.println("debug"); + return 0; + case 0: + pw.println("off"); + return 0; + default: + pw.println("unknow (" + logLevel + ")"); + return 0; + } + } + + private int requestSet(PrintWriter pw) { + if (!isNextArgLogLevel(pw, "set")) { + return -1; + } + final String logLevel = getNextArg(); + switch (logLevel.toLowerCase()) { + case "verbose": + mService.setLogLevel(AutofillManager.FLAG_ADD_CLIENT_VERBOSE); + return 0; + case "debug": + mService.setLogLevel(AutofillManager.FLAG_ADD_CLIENT_DEBUG); + return 0; + case "off": + mService.setLogLevel(0); + return 0; + default: + pw.println("Invalid level: " + logLevel); + return -1; + } + } + private int requestDestroy(PrintWriter pw) { if (!isNextArgSessions(pw)) { return -1; @@ -121,6 +173,15 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand { return true; } + private boolean isNextArgLogLevel(PrintWriter pw, String cmd) { + final String type = getNextArgRequired(); + if (!type.equals("log_level")) { + pw.println("Error: invalid " + cmd + " type: " + type); + return false; + } + return true; + } + private int requestSessionCommon(PrintWriter pw, CountDownLatch latch, Runnable command) { command.run(); @@ -144,13 +205,6 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand { return 0; } - private int getUserIdFromArgsOrCurrentUser() { - if ("--user".equals(getNextArg())) { - return UserHandle.parseUserArg(getNextArgRequired()); - } - return ActivityManager.getCurrentUser(); - } - private int getUserIdFromArgsOrAllUsers() { if ("--user".equals(getNextArg())) { return UserHandle.parseUserArg(getNextArgRequired()); diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java index 5964172e138a..68ade63ac516 100644 --- a/services/autofill/java/com/android/server/autofill/Helper.java +++ b/services/autofill/java/com/android/server/autofill/Helper.java @@ -17,7 +17,6 @@ package com.android.server.autofill; import android.annotation.NonNull; -import android.annotation.Nullable; import android.app.assist.AssistStructure; import android.app.assist.AssistStructure.ViewNode; import android.os.Bundle; @@ -27,14 +26,22 @@ import java.util.Arrays; import java.util.Objects; import java.util.Set; -final class Helper { +public final class Helper { - // TODO(b/36141126): set to false and remove guard from places that should always be on - static final boolean DEBUG = true; - static final boolean VERBOSE = false; + /** + * Defines a logging flag that can be dynamically changed at runtime using + * {@code cmd autofill debug [on|off]}. + */ + public static boolean sDebug = false; + + /** + * Defines a logging flag that can be dynamically changed at runtime using + * {@code cmd autofill verbose [on|off]}. + */ + public static boolean sVerbose = false; static void append(StringBuilder builder, Bundle bundle) { - if (bundle == null || !DEBUG) { + if (bundle == null || !sVerbose) { builder.append("null"); return; } diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java index 2aeb07e1057b..a12ebb23ba5f 100644 --- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java +++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java @@ -18,7 +18,8 @@ package com.android.server.autofill; import static android.service.autofill.FillRequest.INVALID_REQUEST_ID; -import static com.android.server.autofill.Helper.DEBUG; +import static com.android.server.autofill.Helper.sDebug; +import static com.android.server.autofill.Helper.sVerbose; import android.annotation.NonNull; import android.annotation.Nullable; @@ -89,7 +90,7 @@ final class RemoteFillService implements DeathRecipient { private PendingRequest mPendingRequest; public interface FillServiceCallbacks { - void onFillRequestSuccess(@Nullable FillResponse response, int serviceUid, + void onFillRequestSuccess(int requestFlags, @Nullable FillResponse response, int serviceUid, @NonNull String servicePackageName); void onFillRequestFailure(@Nullable CharSequence message, @NonNull String servicePackageName); @@ -219,9 +220,7 @@ final class RemoteFillService implements DeathRecipient { mPendingRequest = pendingRequest; ensureBound(); } else { - if (DEBUG) { - Slog.d(LOG_TAG, "[user: " + mUserId + "] handlePendingRequest()"); - } + if (sVerbose) Slog.v(LOG_TAG, "[user: " + mUserId + "] handlePendingRequest()"); pendingRequest.run(); if (pendingRequest.isFinal()) { mCompleted = true; @@ -237,9 +236,7 @@ final class RemoteFillService implements DeathRecipient { if (isBound() || mBinding) { return; } - if (DEBUG) { - Slog.d(LOG_TAG, "[user: " + mUserId + "] ensureBound()"); - } + if (sVerbose) Slog.v(LOG_TAG, "[user: " + mUserId + "] ensureBound()"); mBinding = true; boolean willBind = mContext.bindServiceAsUser(mIntent, mServiceConnection, @@ -247,9 +244,7 @@ final class RemoteFillService implements DeathRecipient { new UserHandle(mUserId)); if (!willBind) { - if (DEBUG) { - Slog.d(LOG_TAG, "[user: " + mUserId + "] could not bind to " + mIntent); - } + if (sDebug) Slog.d(LOG_TAG, "[user: " + mUserId + "] could not bind to " + mIntent); mBinding = false; if (!mServiceDied) { @@ -262,9 +257,7 @@ final class RemoteFillService implements DeathRecipient { if (!isBound() && !mBinding) { return; } - if (DEBUG) { - Slog.d(LOG_TAG, "[user: " + mUserId + "] ensureUnbound()"); - } + if (sVerbose) Slog.v(LOG_TAG, "[user: " + mUserId + "] ensureUnbound()"); mBinding = false; if (isBound()) { try { @@ -281,10 +274,10 @@ final class RemoteFillService implements DeathRecipient { } private void dispatchOnFillRequestSuccess(PendingRequest pendingRequest, - int callingUid, FillResponse response) { + int callingUid, int requestFlags, FillResponse response) { mHandler.getHandler().post(() -> { if (handleResponseCallbackCommon(pendingRequest)) { - mCallbacks.onFillRequestSuccess(response, callingUid, + mCallbacks.onFillRequestSuccess(requestFlags, response, callingUid, mComponentName.getPackageName()); } }); @@ -452,8 +445,8 @@ final class RemoteFillService implements DeathRecipient { public void onSuccess(FillResponse response) { RemoteFillService remoteService = mWeakService.get(); if (remoteService != null) { - remoteService.dispatchOnFillRequestSuccess( - PendingFillRequest.this, getCallingUid(), response); + remoteService.dispatchOnFillRequestSuccess(PendingFillRequest.this, + getCallingUid(), request.getFlags(), response); } } diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 0687f6da022e..c85ce436375e 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -20,13 +20,13 @@ import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST; import static android.service.autofill.FillRequest.INVALID_REQUEST_ID; import static android.service.voice.VoiceInteractionSession.KEY_RECEIVER_EXTRAS; import static android.service.voice.VoiceInteractionSession.KEY_STRUCTURE; -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_VIEW_ENTERED; -import static android.view.autofill.AutofillManager.FLAG_VIEW_EXITED; +import static android.view.autofill.AutofillManager.ACTION_START_SESSION; +import static android.view.autofill.AutofillManager.ACTION_VALUE_CHANGED; +import static android.view.autofill.AutofillManager.ACTION_VIEW_ENTERED; +import static android.view.autofill.AutofillManager.ACTION_VIEW_EXITED; -import static com.android.server.autofill.Helper.DEBUG; -import static com.android.server.autofill.Helper.VERBOSE; +import static com.android.server.autofill.Helper.sDebug; +import static com.android.server.autofill.Helper.sVerbose; import static com.android.server.autofill.Helper.findViewNodeById; import android.annotation.NonNull; @@ -108,7 +108,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private static AtomicInteger sIdCounter = new AtomicInteger(); /** Id of the session */ - private final int mId; + public final int id; /** uid the session is for */ public final int uid; @@ -174,23 +174,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private boolean mDestroyed; /** - * Flags used to start the session. - */ - private final int mFlags; - - /** * Receiver of assist data from the app's {@link Activity}. */ private final IResultReceiver mAssistReceiver = new IResultReceiver.Stub() { @Override public void send(int resultCode, Bundle resultData) throws RemoteException { - if (VERBOSE) { - Slog.v(TAG, "resultCode on mAssistReceiver: " + resultCode); - } - final AssistStructure structure = resultData.getParcelable(KEY_STRUCTURE); if (structure == null) { - Slog.wtf(TAG, "no assist structure for id " + resultCode); + Slog.wtf(TAG, "no assist structure"); return; } @@ -202,8 +193,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final int requestId = receiverExtras.getInt(EXTRA_REQUEST_ID); - if (DEBUG) { - Slog.d(TAG, "New structure for requestId " + requestId + ": " + structure); + if (sVerbose) { + Slog.v(TAG, "New structure for requestId " + requestId + ": " + structure); } final FillRequest request; @@ -218,6 +209,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // Sanitize structure before it's sent to service. structure.sanitizeForParceling(true); + // Flags used to start the session. + final int flags = structure.getFlags(); + if (mContexts == null) { mContexts = new ArrayList<>(1); } @@ -230,7 +224,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState fillStructureWithAllowedValues(mContexts.get(i).getStructure()); } - request = new FillRequest(requestId, mContexts, mClientState, mFlags); + request = new FillRequest(requestId, mContexts, mClientState, flags); } mRemoteFillService.onFillRequest(request); @@ -251,9 +245,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final ViewNode node = findViewNodeById(structure, viewState.id); if (node == null) { - if (DEBUG) { - Slog.w(TAG, "fillStructureWithAllowedValues(): no node for " + viewState.id); - } + Slog.w(TAG, "fillStructureWithAllowedValues(): no node for " + viewState.id); continue; } @@ -295,15 +287,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState /** * Reads a new structure and then request a new fill response from the fill service. */ - private void requestNewFillResponseLocked() { + private void requestNewFillResponseLocked(int flags) { int requestId; do { requestId = sIdCounter.getAndIncrement(); } while (requestId == INVALID_REQUEST_ID); - if (DEBUG) { - Slog.d(TAG, "Requesting structure for requestId " + requestId); + if (sVerbose) { + Slog.v(TAG, "Requesting structure for requestId=" + requestId + ", flags=" + flags); } // If the focus changes very quickly before the first request is returned each focus change @@ -319,7 +311,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final long identity = Binder.clearCallingIdentity(); try { if (!ActivityManager.getService().requestAutofillData(mAssistReceiver, - receiverExtras, mActivityToken)) { + receiverExtras, mActivityToken, flags)) { Slog.w(TAG, "failed to request autofill data for " + mActivityToken); } } finally { @@ -334,8 +326,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @NonNull Context context, @NonNull HandlerCaller handlerCaller, int userId, @NonNull Object lock, int sessionId, int uid, @NonNull IBinder activityToken, @Nullable IBinder windowToken, @NonNull IBinder client, boolean hasCallback, - int flags, @NonNull ComponentName componentName, @NonNull String packageName) { - mId = sessionId; + @NonNull ComponentName componentName, @NonNull String packageName) { + id = sessionId; this.uid = uid; mService = service; mLock = lock; @@ -346,7 +338,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mWindowToken = windowToken; mHasCallback = hasCallback; mPackageName = packageName; - mFlags = flags; mClient = IAutoFillManagerClient.Stub.asInterface(client); mMetricsLogger.action(MetricsEvent.AUTOFILL_SESSION_STARTED, mPackageName); @@ -371,7 +362,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState synchronized (mLock) { if (mDestroyed) { Slog.w(TAG, "Call to Session#switchWindow() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } mWindowToken = newWindow; @@ -388,7 +379,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState synchronized (mLock) { if (mDestroyed) { Slog.w(TAG, "Call to Session#switchActivity() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } mActivityToken = newActivity; @@ -401,17 +392,17 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // FillServiceCallbacks @Override - public void onFillRequestSuccess(@Nullable FillResponse response, int serviceUid, - @NonNull String servicePackageName) { + public void onFillRequestSuccess(int requestFlags, @Nullable FillResponse response, + int serviceUid, @NonNull String servicePackageName) { synchronized (mLock) { if (mDestroyed) { Slog.w(TAG, "Call to Session#onFillRequestSuccess() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } } if (response == null) { - if ((mFlags & FLAG_MANUAL_REQUEST) != 0) { + if ((requestFlags & FLAG_MANUAL_REQUEST) != 0) { getUiForShowing().showError(R.string.autofill_error_cannot_autofill); } // Nothing to be done, but need to notify client. @@ -452,7 +443,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState synchronized (mLock) { if (mDestroyed) { Slog.w(TAG, "Call to Session#onFillRequestFailure() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } } @@ -472,7 +463,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState synchronized (mLock) { if (mDestroyed) { Slog.w(TAG, "Call to Session#onSaveRequestSuccess() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } } @@ -494,7 +485,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState synchronized (mLock) { if (mDestroyed) { Slog.w(TAG, "Call to Session#onSaveRequestFailure() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } } @@ -541,7 +532,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState synchronized (mLock) { if (mDestroyed) { Slog.w(TAG, "Call to Session#authenticate() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } } @@ -563,11 +554,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // AutoFillUiCallback @Override public void fill(int requestId, Dataset dataset) { - mHandlerCaller.getHandler().post(() -> autoFill(requestId, dataset)); synchronized (mLock) { if (mDestroyed) { Slog.w(TAG, "Call to Session#fill() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } } @@ -580,12 +570,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState synchronized (mLock) { if (mDestroyed) { Slog.w(TAG, "Call to Session#save() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } } mHandlerCaller.getHandler() - .obtainMessage(AutofillManagerServiceImpl.MSG_SERVICE_SAVE, mId, 0) + .obtainMessage(AutofillManagerServiceImpl.MSG_SERVICE_SAVE, id, 0) .sendToTarget(); } @@ -595,7 +585,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState synchronized (mLock) { if (mDestroyed) { Slog.w(TAG, "Call to Session#cancelSave() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } } @@ -609,19 +599,19 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState synchronized (mLock) { if (mDestroyed) { Slog.w(TAG, "Call to Session#requestShowFillUi() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } if (id.equals(mCurrentViewId)) { try { final ViewState view = mViewStates.get(id); - mClient.requestShowFillUi(mId, mWindowToken, id, width, height, + mClient.requestShowFillUi(this.id, mWindowToken, id, width, height, view.getVirtualBounds(), presenter); } catch (RemoteException e) { Slog.e(TAG, "Error requesting to show fill UI", e); } } else { - if (DEBUG) { + if (sDebug) { Slog.d(TAG, "Do not show full UI on " + id + " as it is not the current view (" + mCurrentViewId + ") anymore"); } @@ -636,7 +626,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // NOTE: We allow this call in a destroyed state as the UI is // asked to go away after we get destroyed, so let it do that. try { - mClient.requestHideFillUi(mId, mWindowToken, id); + mClient.requestHideFillUi(this.id, mWindowToken, id); } catch (RemoteException e) { Slog.e(TAG, "Error requesting to hide fill UI", e); } @@ -649,7 +639,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState synchronized (mLock) { if (mDestroyed) { Slog.w(TAG, "Call to Session#startIntentSender() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } removeSelfLocked(); @@ -668,7 +658,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState void setAuthenticationResultLocked(Bundle data) { if (mDestroyed) { Slog.w(TAG, "Call to Session#setAuthenticationResultLocked() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } if ((mResponseWaitingAuth == null && mDatasetWaitingAuth == null) || data == null) { @@ -708,7 +698,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState void setHasCallbackLocked(boolean hasIt) { if (mDestroyed) { Slog.w(TAG, "Call to Session#setHasCallbackLocked() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } mHasCallback = hasIt; @@ -722,7 +712,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState public boolean showSaveLocked() { if (mDestroyed) { Slog.w(TAG, "Call to Session#showSaveLocked() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return false; } if (mContexts == null) { @@ -732,23 +722,23 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (mResponses == null) { // Happens when the activity / session was finished before the service replied, or // when the service cannot autofill it (and returned a null response). - if (DEBUG) { - Slog.d(TAG, "showSaveLocked(): no responses on session"); + if (sVerbose) { + Slog.v(TAG, "showSaveLocked(): no responses on session"); } return true; } final int lastResponseIdx = getLastResponseIndex(); if (lastResponseIdx < 0) { - Slog.d(TAG, "showSaveLocked(): mResponses=" + mResponses + Slog.w(TAG, "showSaveLocked(): did not get last response. mResponses=" + mResponses + ", mViewStates=" + mViewStates); return true; } final FillResponse response = mResponses.valueAt(lastResponseIdx); final SaveInfo saveInfo = response.getSaveInfo(); - if (DEBUG) { - Slog.d(TAG, "showSaveLocked(): mResponses=" + mResponses + ", mContexts=" + mContexts + if (sVerbose) { + Slog.v(TAG, "showSaveLocked(): mResponses=" + mResponses + ", mContexts=" + mContexts + ", mViewStates=" + mViewStates); } @@ -783,7 +773,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final AutofillValue currentValue = viewState.getCurrentValue(); if (currentValue == null || currentValue.isEmpty()) { - if (DEBUG) { + if (sDebug) { Slog.d(TAG, "showSaveLocked(): empty value for required " + id ); } allRequiredAreNotEmpty = false; @@ -792,7 +782,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final AutofillValue filledValue = viewState.getAutofilledValue(); if (!currentValue.equals(filledValue)) { - if (DEBUG) { + if (sDebug) { Slog.d(TAG, "showSaveLocked(): found a change on required " + id + ": " + filledValue + " => " + currentValue); } @@ -815,7 +805,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final AutofillValue currentValue = viewState.getCurrentValue(); final AutofillValue filledValue = viewState.getAutofilledValue(); if (currentValue != null && !currentValue.equals(filledValue)) { - if (DEBUG) { + if (sDebug) { Slog.d(TAG, "finishSessionLocked(): found a change on optional " + id + ": " + filledValue + " => " + currentValue); } @@ -832,7 +822,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } // Nothing changed... - if (DEBUG) { + if (sDebug) { Slog.d(TAG, "showSaveLocked(): with no changes, comes no responsibilities." + "allRequiredAreNotNull=" + allRequiredAreNotEmpty + ", atLeastOneChanged=" + atLeastOneChanged); @@ -846,29 +836,23 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState void callSaveLocked() { if (mDestroyed) { Slog.w(TAG, "Call to Session#callSaveLocked() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } - if (DEBUG) { - Slog.d(TAG, "callSaveLocked(): mViewStates=" + mViewStates); - } + if (sVerbose) Slog.v(TAG, "callSaveLocked(): mViewStates=" + mViewStates); - int numContexts = mContexts.size(); + final int numContexts = mContexts.size(); for (int i = 0; i < numContexts; i++) { - FillContext context = mContexts.get(i); + final FillContext context = mContexts.get(i); - if (VERBOSE) { - Slog.v(TAG, "callSaveLocked(): updating " + context); - } + if (sVerbose) Slog.v(TAG, "callSaveLocked(): updating " + context); for (Entry<AutofillId, ViewState> entry : mViewStates.entrySet()) { final AutofillValue value = entry.getValue().getCurrentValue(); if (value == null) { - if (VERBOSE) { - Slog.v(TAG, "callSaveLocked(): skipping " + entry.getKey()); - } + if (sVerbose) Slog.v(TAG, "callSaveLocked(): skipping " + entry.getKey()); continue; } final AutofillId id = entry.getKey(); @@ -877,9 +861,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState Slog.w(TAG, "callSaveLocked(): did not find node with id " + id); continue; } - if (VERBOSE) { - Slog.v(TAG, "callSaveLocked(): updating " + id + " to " + value); - } + if (sVerbose) Slog.v(TAG, "callSaveLocked(): updating " + id + " to " + value); node.updateAutofillValue(value); } @@ -887,7 +869,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // Sanitize structure before it's sent to service. context.getStructure().sanitizeForParceling(false); - if (VERBOSE) { + if (sVerbose) { Slog.v(TAG, "Dumping structure of " + context + " before calling service.save()"); context.getStructure().dump(); } @@ -933,7 +915,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final int numDatasets = datasets.size(); for (int dataSetNum = 0; dataSetNum < numDatasets; dataSetNum++) { - final ArrayList fields = datasets.get(dataSetNum).getFieldIds(); + final ArrayList<AutofillId> fields = datasets.get(dataSetNum).getFieldIds(); if (fields != null && fields.contains(id)) { return false; @@ -945,96 +927,92 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return true; } - void updateLocked(AutofillId id, Rect virtualBounds, AutofillValue value, int flags) { + void updateLocked(AutofillId id, Rect virtualBounds, AutofillValue value, int action, + int flags) { if (mDestroyed) { Slog.w(TAG, "Call to Session#updateLocked() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } ViewState viewState = mViewStates.get(id); if (viewState == null) { - if ((flags & (FLAG_START_SESSION | FLAG_VALUE_CHANGED | FLAG_VIEW_ENTERED)) != 0) { - if (DEBUG) { - Slog.d(TAG, "Creating viewState for " + id + " on " + getFlagAsString(flags)); + if (action == ACTION_START_SESSION || action == ACTION_VALUE_CHANGED + || action == ACTION_VIEW_ENTERED) { + if (sVerbose) { + Slog.v(TAG, + "Creating viewState for " + id + " on " + getActionAsString(action)); } viewState = new ViewState(this, id, value, this, ViewState.STATE_INITIAL); mViewStates.put(id, viewState); } else { - if (VERBOSE) Slog.v(TAG, "Ignored " + getFlagAsString(flags) + " for " + id); + if (sVerbose) Slog.v(TAG, "Ignored " + getActionAsString(action) + " for " + id); return; } } - if ((flags & FLAG_START_SESSION) != 0) { - // View is triggering autofill. - mCurrentViewId = viewState.id; - viewState.update(value, virtualBounds); - viewState.setState(ViewState.STATE_STARTED_SESSION); - requestNewFillResponseLocked(); - return; - } - - if ((flags & FLAG_VALUE_CHANGED) != 0) { - if (value != null && !value.equals(viewState.getCurrentValue())) { - // Always update the internal state. - viewState.setCurrentValue(value); - - // Must check if this update was caused by autofilling the view, in which - // case we just update the value, but not the UI. - final AutofillValue filledValue = viewState.getAutofilledValue(); - if (value.equals(filledValue)) { - return; - } - // Update the internal state... - viewState.setState(ViewState.STATE_CHANGED); - - //..and the UI - if (value.isText()) { - getUiForShowing().filterFillUi(value.getTextValue().toString()); - } else { - getUiForShowing().filterFillUi(null); + switch(action) { + case ACTION_START_SESSION: + // View is triggering autofill. + mCurrentViewId = viewState.id; + viewState.update(value, virtualBounds); + viewState.setState(ViewState.STATE_STARTED_SESSION); + requestNewFillResponseLocked(flags); + break; + case ACTION_VALUE_CHANGED: + if (value != null && !value.equals(viewState.getCurrentValue())) { + // Always update the internal state. + viewState.setCurrentValue(value); + + // Must check if this update was caused by autofilling the view, in which + // case we just update the value, but not the UI. + final AutofillValue filledValue = viewState.getAutofilledValue(); + if (value.equals(filledValue)) { + return; + } + // Update the internal state... + viewState.setState(ViewState.STATE_CHANGED); + + //..and the UI + if (value.isText()) { + getUiForShowing().filterFillUi(value.getTextValue().toString()); + } else { + getUiForShowing().filterFillUi(null); + } } - } - - return; - } - - if ((flags & FLAG_VIEW_ENTERED) != 0) { - if (shouldStartNewPartitionLocked(id)) { - // TODO(b/37424539): proper implementation - if (mResponseWaitingAuth != null && ((flags & FLAG_START_SESSION) == 0)) { - viewState.setState(ViewState.STATE_WAITING_RESPONSE_AUTH); - } else if ((flags & FLAG_START_SESSION) == 0){ - if (DEBUG) { - Slog.d(TAG, "Starting partition for view id " + viewState.id); + break; + case ACTION_VIEW_ENTERED: + if (shouldStartNewPartitionLocked(id)) { + // TODO(b/37424539): proper implementation + if (mResponseWaitingAuth != null) { + viewState.setState(ViewState.STATE_WAITING_RESPONSE_AUTH); + } else { + if (sDebug) { + Slog.d(TAG, "Starting partition for view id " + viewState.id); + } + viewState.setState(ViewState.STATE_STARTED_PARTITION); + requestNewFillResponseLocked(flags); } - viewState.setState(ViewState.STATE_STARTED_PARTITION); - requestNewFillResponseLocked(); } - } - // Remove the UI if the ViewState has changed. - if (mCurrentViewId != viewState.id) { - mUi.hideFillUi(mCurrentViewId != null ? mCurrentViewId : null); - mCurrentViewId = viewState.id; - } - - // If the ViewState is ready to be displayed, onReady() will be called. - viewState.update(value, virtualBounds); - - return; - } + // Remove the UI if the ViewState has changed. + if (mCurrentViewId != viewState.id) { + mUi.hideFillUi(mCurrentViewId != null ? mCurrentViewId : null); + mCurrentViewId = viewState.id; + } - if ((flags & FLAG_VIEW_EXITED) != 0) { - if (mCurrentViewId == viewState.id) { - mUi.hideFillUi(viewState.id); - mCurrentViewId = null; - } - return; + // If the ViewState is ready to be displayed, onReady() will be called. + viewState.update(value, virtualBounds); + break; + case ACTION_VIEW_EXITED: + if (mCurrentViewId == viewState.id) { + mUi.hideFillUi(viewState.id); + mCurrentViewId = null; + } + break; + default: + Slog.w(TAG, "updateLocked(): unknown action: " + action); } - - Slog.w(TAG, "updateLocked(): unknown flags " + flags + ": " + getFlagAsString(flags)); } @Override @@ -1043,7 +1021,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState synchronized (mLock) { if (mDestroyed) { Slog.w(TAG, "Call to Session#onFillReady() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } } @@ -1056,12 +1034,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState getUiForShowing().showFillUi(filledId, response, filterText, mPackageName); } - static String getFlagAsString(int flag) { - return DebugUtils.flagsToString(AutofillManager.class, "FLAG_", flag); - } - - int getId() { - return mId; + String getActionAsString(int flag) { + return DebugUtils.flagsToString(AutofillManager.class, "ACTION_", flag); } boolean isDestroyed() { @@ -1080,7 +1054,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState synchronized (mLock) { if (!mHasCallback) return; try { - mClient.notifyNoFillUi(mId, mWindowToken, mCurrentViewId); + mClient.notifyNoFillUi(id, mWindowToken, mCurrentViewId); } catch (RemoteException e) { Slog.e(TAG, "Error notifying client no fill UI: windowToken=" + mWindowToken + " id=" + mCurrentViewId, e); @@ -1115,21 +1089,22 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } try { - mClient.setTrackedViews(mId, trackedViews, saveOnAllViewsInvisible); + mClient.setTrackedViews(id, trackedViews, saveOnAllViewsInvisible); } catch (RemoteException e) { Slog.w(TAG, "Cannot set tracked ids", e); } } private void processResponseLocked(@NonNull FillResponse response) { - if (DEBUG) { - Slog.d(TAG, "processResponseLocked(mCurrentViewId=" + mCurrentViewId + "):" + response); + if (sVerbose) { + Slog.v(TAG, "processResponseLocked(mCurrentViewId=" + mCurrentViewId + "):" + response); } if (mResponses == null) { mResponses = new SparseArray<>(4); } - mResponses.put(response.getRequestId(), response); + final int requestId = response.getRequestId(); + mResponses.put(requestId, response); mClientState = response.getClientState(); setViewStatesLocked(response, ViewState.STATE_FILLABLE); @@ -1139,13 +1114,18 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return; } - if ((mFlags & FLAG_MANUAL_REQUEST) != 0 && response.getDatasets() != null - && response.getDatasets().size() == 1) { - Slog.d(TAG, "autofilling manual request directly"); - autoFill(response.getRequestId(), response.getDatasets().get(0)); - return; - } + final ArrayList<Dataset> datasets = response.getDatasets(); + if (datasets != null && datasets.size() == 1) { + // Check if it its a single response for a manual request, in which case it should + // be automatically filled + final FillContext context = getFillContextByRequestIdLocked(requestId); + if (context != null && (context.getStructure().getFlags() & FLAG_MANUAL_REQUEST) != 0) { + Slog.d(TAG, "autofilling manual request directly"); + autoFill(requestId, datasets.get(0)); + return; + } + } // Updates the UI, if necessary. final ViewState currentView = mViewStates.get(mCurrentViewId); currentView.maybeCallOnFillReady(); @@ -1200,14 +1180,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } - private ViewState createOrUpdateViewStateLocked(AutofillId id, int state,AutofillValue value) { + private ViewState createOrUpdateViewStateLocked(AutofillId id, int state, AutofillValue value) { ViewState viewState = mViewStates.get(id); if (viewState != null) { viewState.setState(state); } else { viewState = new ViewState(this, id, null, this, state); - if (DEBUG) { // TODO(b/33197203): change to VERBOSE once stable - Slog.d(TAG, "Adding autofillable view with id " + id + " and state " + state); + if (sVerbose) { + Slog.v(TAG, "Adding autofillable view with id " + id + " and state " + state); } mViewStates.put(id, viewState); } @@ -1235,7 +1215,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState synchronized (mLock) { if (mDestroyed) { Slog.w(TAG, "Call to Session#autoFill() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } // Autofill it directly... @@ -1273,7 +1253,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final Intent fillInIntent = new Intent(); fillInIntent.putExtra(AutofillManager.EXTRA_ASSIST_STRUCTURE, structure); if (extras != null) { - fillInIntent.putExtra(AutofillManager.EXTRA_DATA_EXTRAS, extras); + fillInIntent.putExtra(AutofillManager.EXTRA_CLIENT_STATE, extras); } return fillInIntent; } @@ -1281,7 +1261,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private void startAuthentication(IntentSender intent, Intent fillInIntent) { try { synchronized (mLock) { - mClient.authenticate(mId, intent, fillInIntent); + mClient.authenticate(id, intent, fillInIntent); } } catch (RemoteException e) { Slog.e(TAG, "Error launching auth intent", e); @@ -1289,10 +1269,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } void dumpLocked(String prefix, PrintWriter pw) { - pw.print(prefix); pw.print("id: "); pw.println(mId); + pw.print(prefix); pw.print("id: "); pw.println(id); pw.print(prefix); pw.print("uid: "); pw.println(uid); pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken); - pw.print(prefix); pw.print("mFlags: "); pw.println(mFlags); pw.print(prefix); pw.print("mResponses: "); pw.println(mResponses); pw.print(prefix); pw.print("mResponseWaitingAuth: "); pw.println(mResponseWaitingAuth); pw.print(prefix); pw.print("mDatasetWaitingAuth: "); pw.println(mDatasetWaitingAuth); @@ -1312,7 +1291,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState FillContext context = mContexts.get(i); pw.print(prefix2); pw.print(context); - if (VERBOSE) { + if (sVerbose) { pw.println(context.getStructure() + " (look at logcat)"); // TODO: add method on AssistStructure to dump on pw @@ -1333,14 +1312,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState synchronized (mLock) { if (mDestroyed) { Slog.w(TAG, "Call to Session#autoFillApp() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } try { - if (DEBUG) { - Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset); - } - mClient.autofill(mId, mWindowToken, dataset.getFieldIds(), + if (sDebug) Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset); + mClient.autofill(id, mWindowToken, dataset.getFieldIds(), dataset.getFieldValues()); setViewStatesLocked(null, dataset, ViewState.STATE_AUTOFILLED); } catch (RemoteException e) { @@ -1374,16 +1351,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } void removeSelfLocked() { - if (VERBOSE) { - Slog.v(TAG, "removeSelfLocked()"); - } + if (sVerbose) Slog.v(TAG, "removeSelfLocked()"); if (mDestroyed) { Slog.w(TAG, "Call to Session#removeSelfLocked() rejected - session: " - + mId + " destroyed"); + + id + " destroyed"); return; } destroyLocked(); - mService.removeSessionLocked(mId); + mService.removeSessionLocked(id); } private int getLastResponseIndex() { diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java index 3967f59355c4..7ca943511dc0 100644 --- a/services/autofill/java/com/android/server/autofill/ViewState.java +++ b/services/autofill/java/com/android/server/autofill/ViewState.java @@ -16,7 +16,7 @@ package com.android.server.autofill; -import static com.android.server.autofill.Helper.DEBUG; +import static com.android.server.autofill.Helper.sDebug; import android.annotation.Nullable; import android.graphics.Rect; @@ -65,15 +65,15 @@ final class ViewState { public static final int STATE_WAITING_RESPONSE_AUTH = 0x80; public final AutofillId id; + private final Listener mListener; private final Session mSession; - private FillResponse mResponse; + private FillResponse mResponse; private AutofillValue mInitialValue; private AutofillValue mCurrentValue; private AutofillValue mAutofilledValue; private Rect mVirtualBounds; - private int mState; ViewState(Session session, AutofillId id, AutofillValue value, Listener listener, int state) { @@ -172,9 +172,7 @@ final class ViewState { */ void maybeCallOnFillReady() { if ((mState & (STATE_AUTOFILLED | STATE_WAITING_DATASET_AUTH)) != 0) { - if (DEBUG) { - Slog.d(TAG, "Ignoring UI for " + id + " on " + getStateAsString()); - } + if (sDebug) Slog.d(TAG, "Ignoring UI for " + id + " on " + getStateAsString()); return; } // First try the current response associated with this View. 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 0556c6711888..086742eac6d5 100644 --- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java +++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java @@ -15,7 +15,7 @@ */ package com.android.server.autofill.ui; -import static com.android.server.autofill.ui.Helper.DEBUG; +import static com.android.server.autofill.Helper.sDebug; import android.annotation.NonNull; import android.annotation.Nullable; @@ -47,7 +47,7 @@ import java.io.PrintWriter; * managing saving of user edits. */ public final class AutoFillUI { - private static final String TAG = "AutoFillUI"; + private static final String TAG = "AutofillUI"; private final Handler mHandler = UiThread.getHandler(); private final @NonNull Context mContext; @@ -139,7 +139,7 @@ public final class AutoFillUI { */ public void showFillUi(@NonNull AutofillId focusedId, @NonNull FillResponse response, @Nullable String filterText, @NonNull String packageName) { - if (DEBUG) { + if (sDebug) { Slog.d(TAG, "showFillUi(): id=" + focusedId + ", filter=" + filterText); } final LogMaker log = (new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_FILL_UI)) 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 bb47e5b54863..fa95e036eae5 100644 --- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java @@ -15,6 +15,8 @@ */ package com.android.server.autofill.ui; +import static com.android.server.autofill.Helper.sDebug; + import android.annotation.NonNull; import android.annotation.Nullable; import android.app.PendingIntent; @@ -341,7 +343,7 @@ final class FillUi { mWm.updateViewLayout(mContentView, params); } } catch (WindowManager.BadTokenException e) { - Slog.i(TAG, "Filed with with token " + params.token + " gone."); + if (sDebug) Slog.d(TAG, "Filed with with token " + params.token + " gone."); mCallback.onDestroy(); } } diff --git a/services/autofill/java/com/android/server/autofill/ui/Helper.java b/services/autofill/java/com/android/server/autofill/ui/Helper.java deleted file mode 100644 index 996e4213ac44..000000000000 --- a/services/autofill/java/com/android/server/autofill/ui/Helper.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.autofill.ui; - -final class Helper { - - static final boolean DEBUG = true; // TODO(b/33197203): set to false when stable - static final boolean VERBOSE = false; - private Helper() { - throw new UnsupportedOperationException("contains static members only"); - } -} diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java index cbaaef707bec..63420fd27072 100644 --- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java @@ -16,7 +16,7 @@ package com.android.server.autofill.ui; -import static com.android.server.autofill.ui.Helper.DEBUG; +import static com.android.server.autofill.Helper.sDebug; import android.annotation.NonNull; import android.app.Dialog; @@ -42,7 +42,7 @@ import com.android.server.UiThread; */ final class SaveUi { - private static final String TAG = "SaveUi"; + private static final String TAG = "AutofillSaveUi"; public interface OnSaveListener { void onSave(); @@ -61,7 +61,7 @@ final class SaveUi { @Override public void onSave() { - if (DEBUG) Slog.d(TAG, "onSave(): " + mDone); + if (sDebug) Slog.d(TAG, "onSave(): " + mDone); if (mDone) { return; } @@ -71,7 +71,7 @@ final class SaveUi { @Override public void onCancel(IntentSender listener) { - if (DEBUG) Slog.d(TAG, "onCancel(): " + mDone); + if (sDebug) Slog.d(TAG, "onCancel(): " + mDone); if (mDone) { return; } @@ -81,7 +81,7 @@ final class SaveUi { @Override public void onDestroy() { - if (DEBUG) Slog.d(TAG, "onDestroy(): " + mDone); + if (sDebug) Slog.d(TAG, "onDestroy(): " + mDone); if (mDone) { return; } @@ -154,8 +154,9 @@ final class SaveUi { subTitleView.setVisibility(View.VISIBLE); } - if (DEBUG) { - Slog.d(TAG, "Title: " + title + " SubTitle: " + subTitle); + Slog.i(TAG, "Showing save dialog: " + title); + if (sDebug) { + Slog.d(TAG, "SubTitle: " + subTitle); } final TextView noButton = view.findViewById(R.id.autofill_save_no); diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 6c18b260e18d..18b4571ca3ea 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -18,6 +18,7 @@ package com.android.server; import android.Manifest; import android.app.ActivityManager; +import android.app.AppGlobals; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothProfile; import android.bluetooth.IBluetooth; @@ -37,11 +38,11 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; +import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.database.ContentObserver; import android.os.Binder; -import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -50,7 +51,6 @@ import android.os.Message; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; -import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; @@ -61,15 +61,15 @@ import android.provider.Settings.SettingNotFoundException; import android.util.Slog; import com.android.internal.util.DumpUtils; -import com.android.server.pm.PackageManagerService; +import com.android.server.pm.UserRestrictionsUtils; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReentrantReadWriteLock; class BluetoothManagerService extends IBluetoothManager.Stub { @@ -120,7 +120,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int MESSAGE_ADD_PROXY_DELAYED = 400; private static final int MESSAGE_BIND_PROFILE_SERVICE = 401; - private static final int MAX_SAVE_RETRIES = 3; private static final int MAX_ERROR_RESTART_RETRIES = 6; // Bluetooth persisted setting is off @@ -223,22 +222,25 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public void onUserRestrictionsChanged(int userId, Bundle newRestrictions, Bundle prevRestrictions) { - if (!newRestrictions.containsKey(UserManager.DISALLOW_BLUETOOTH) - && !prevRestrictions.containsKey(UserManager.DISALLOW_BLUETOOTH)) { - // The relevant restriction has not changed - do nothing. - return; + if (!UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions, + UserManager.DISALLOW_BLUETOOTH, UserManager.DISALLOW_BLUETOOTH_SHARING)) { + return; // No relevant changes, nothing to do. } - final boolean bluetoothDisallowed = - newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH); - if ((mEnable || mEnableExternal) && bluetoothDisallowed) { + + final boolean disallowed = newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH); + + // DISALLOW_BLUETOOTH is a global restriction that can only be set by DO or PO on the + // system user, so we only look at the system user. + if (userId == UserHandle.USER_SYSTEM && disallowed && (mEnable || mEnableExternal)) { try { - disable(null, true); + disable(null /* packageName */, true /* persist */); } catch (RemoteException e) { - Slog.w(TAG, "Exception when disabling Bluetooth from UserRestrictionsListener", - e); + Slog.w(TAG, "Exception when disabling Bluetooth", e); } } - updateOppLauncherComponentState(bluetoothDisallowed); + final boolean sharingDisallowed = disallowed + || newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH_SHARING); + updateOppLauncherComponentState(userId, sharingDisallowed); } }; @@ -994,11 +996,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { LocalServices.getService(UserManagerInternal.class); userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener); final boolean isBluetoothDisallowed = isBluetoothDisallowed(); - PackageManagerService packageManagerService = - (PackageManagerService) ServiceManager.getService("package"); - if (packageManagerService != null && !packageManagerService.isOnlyCoreApps()) { - updateOppLauncherComponentState(isBluetoothDisallowed); - } if (isBluetoothDisallowed) { return; } @@ -2074,21 +2071,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub { /** * Disables BluetoothOppLauncherActivity component, so the Bluetooth sharing option is not - * offered to the user if Bluetooth is disallowed. Puts the component to its default state if - * Bluetooth is not disallowed. + * offered to the user if Bluetooth or sharing is disallowed. Puts the component to its default + * state if Bluetooth is not disallowed. * - * @param bluetoothDisallowed whether the {@link UserManager.DISALLOW_BLUETOOTH} user - * restriction was set. + * @param userId user to disable bluetooth sharing for. + * @param bluetoothSharingDisallowed whether bluetooth sharing is disallowed. */ - private void updateOppLauncherComponentState(boolean bluetoothDisallowed) { + private void updateOppLauncherComponentState(int userId, boolean bluetoothSharingDisallowed) { final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth", "com.android.bluetooth.opp.BluetoothOppLauncherActivity"); - final int newState = bluetoothDisallowed + final int newState = bluetoothSharingDisallowed ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; try { - mContext.getPackageManager() - .setComponentEnabledSetting(oppLauncherComponent, newState, 0); + final IPackageManager imp = AppGlobals.getPackageManager(); + imp.setComponentEnabledSetting(oppLauncherComponent, newState, 0 /* flags */, userId); } catch (Exception e) { // The component was not found, do nothing. } diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 018e41b7bef1..03da5b21fef8 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -576,6 +576,22 @@ public class AccountManagerService long identityToken = clearCallingIdentity(); try { UserAccounts accounts = getUserAccounts(userId); + if (AccountManager.PACKAGE_NAME_KEY_LEGACY_VISIBLE.equals(packageName)) { + int visibility = getAccountVisibilityFromCache(account, packageName, accounts); + if (AccountManager.VISIBILITY_UNDEFINED != visibility) { + return visibility; + } else { + return AccountManager.VISIBILITY_USER_MANAGED_VISIBLE; + } + } + if (AccountManager.PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE.equals(packageName)) { + int visibility = getAccountVisibilityFromCache(account, packageName, accounts); + if (AccountManager.VISIBILITY_UNDEFINED != visibility) { + return visibility; + } else { + return AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE; + } + } return resolveAccountVisibility(account, packageName, accounts); } finally { restoreCallingIdentity(identityToken); @@ -641,11 +657,6 @@ public class AccountManagerService return AccountManager.VISIBILITY_VISIBLE; // Authenticator can always see the account } - if (isSpecialPackageKey(packageName)) { - Log.d(TAG, "Package name is forbidden: " + packageName); - return AccountManager.VISIBILITY_NOT_VISIBLE; - } - // Return stored value if it was set. int visibility = getAccountVisibilityFromCache(account, packageName, accounts); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 8d1435b29e4b..71ef23028651 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -12836,7 +12836,7 @@ public class ActivityManagerService extends IActivityManager.Stub public Bundle getAssistContextExtras(int requestType) { PendingAssistExtras pae = enqueueAssistContext(requestType, null, null, null, null, null, true /* focused */, true /* newSessionId */, - UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_TIMEOUT); + UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_TIMEOUT, 0); if (pae == null) { return null; } @@ -12906,25 +12906,21 @@ public class ActivityManagerService extends IActivityManager.Stub Bundle receiverExtras, IBinder activityToken, boolean focused, boolean newSessionId) { return enqueueAssistContext(requestType, null, null, receiver, receiverExtras, activityToken, focused, newSessionId, UserHandle.getCallingUserId(), null, - PENDING_ASSIST_EXTRAS_LONG_TIMEOUT) != null; + PENDING_ASSIST_EXTRAS_LONG_TIMEOUT, 0) != null; } @Override 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 - // 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 - // autofill flag values). + IBinder activityToken, int flags) { return enqueueAssistContext(ActivityManager.ASSIST_CONTEXT_AUTOFILL, null, null, receiver, receiverExtras, activityToken, true, true, UserHandle.getCallingUserId(), - null, PENDING_AUTOFILL_ASSIST_STRUCTURE_TIMEOUT) != null; + null, PENDING_AUTOFILL_ASSIST_STRUCTURE_TIMEOUT, flags) != null; } private PendingAssistExtras enqueueAssistContext(int requestType, Intent intent, String hint, IResultReceiver receiver, Bundle receiverExtras, IBinder activityToken, - boolean focused, boolean newSessionId, int userHandle, Bundle args, long timeout) { + boolean focused, boolean newSessionId, int userHandle, Bundle args, long timeout, + int flags) { enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO, "enqueueAssistContext()"); @@ -12974,7 +12970,7 @@ public class ActivityManagerService extends IActivityManager.Stub } try { activity.app.thread.requestAssistContextExtras(activity.appToken, pae, requestType, - mViSessionId); + mViSessionId, flags); mPendingAssistExtras.add(pae); mUiHandler.postDelayed(pae, timeout); } catch (RemoteException e) { @@ -13086,7 +13082,7 @@ public class ActivityManagerService extends IActivityManager.Stub Bundle args) { return enqueueAssistContext(requestType, intent, hint, null, null, null, true /* focused */, true /* newSessionId */, userHandle, args, - PENDING_ASSIST_EXTRAS_TIMEOUT) != null; + PENDING_ASSIST_EXTRAS_TIMEOUT, 0) != null; } public void registerProcessObserver(IProcessObserver observer) { @@ -14644,8 +14640,10 @@ public class ActivityManagerService extends IActivityManager.Stub } static int procStateToImportance(int procState, int memAdj, - ActivityManager.RunningAppProcessInfo currApp) { - int imp = ActivityManager.RunningAppProcessInfo.procStateToImportance(procState); + ActivityManager.RunningAppProcessInfo currApp, + int clientTargetSdk) { + int imp = ActivityManager.RunningAppProcessInfo.procStateToImportanceForTargetSdk( + procState, clientTargetSdk); if (imp == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) { currApp.lru = memAdj; } else { @@ -14655,7 +14653,8 @@ public class ActivityManagerService extends IActivityManager.Stub } private void fillInProcMemInfo(ProcessRecord app, - ActivityManager.RunningAppProcessInfo outInfo) { + ActivityManager.RunningAppProcessInfo outInfo, + int clientTargetSdk) { outInfo.pid = app.pid; outInfo.uid = app.info.uid; if (mHeavyWeightProcess == app) { @@ -14670,7 +14669,7 @@ public class ActivityManagerService extends IActivityManager.Stub outInfo.lastTrimLevel = app.trimMemoryLevel; int adj = app.curAdj; int procState = app.curProcState; - outInfo.importance = procStateToImportance(procState, adj, outInfo); + outInfo.importance = procStateToImportance(procState, adj, outInfo, clientTargetSdk); outInfo.importanceReasonCode = app.adjTypeCode; outInfo.processState = app.curProcState; } @@ -14680,6 +14679,7 @@ public class ActivityManagerService extends IActivityManager.Stub enforceNotIsolatedCaller("getRunningAppProcesses"); final int callingUid = Binder.getCallingUid(); + final int clientTargetSdk = mPackageManagerInt.getUidTargetSdkVersion(callingUid); // Lazy instantiation of list List<ActivityManager.RunningAppProcessInfo> runList = null; @@ -14702,7 +14702,7 @@ public class ActivityManagerService extends IActivityManager.Stub ActivityManager.RunningAppProcessInfo currApp = new ActivityManager.RunningAppProcessInfo(app.processName, app.pid, app.getPackageList()); - fillInProcMemInfo(app, currApp); + fillInProcMemInfo(app, currApp, clientTargetSdk); if (app.adjSource instanceof ProcessRecord) { currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid; currApp.importanceReasonImportance = @@ -14758,12 +14758,16 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void getMyMemoryState(ActivityManager.RunningAppProcessInfo outInfo) { enforceNotIsolatedCaller("getMyMemoryState"); + + final int callingUid = Binder.getCallingUid(); + final int clientTargetSdk = mPackageManagerInt.getUidTargetSdkVersion(callingUid); + synchronized (this) { ProcessRecord proc; synchronized (mPidsSelfLocked) { proc = mPidsSelfLocked.get(Binder.getCallingPid()); } - fillInProcMemInfo(proc, outInfo); + fillInProcMemInfo(proc, outInfo, clientTargetSdk); } } @@ -19715,12 +19719,12 @@ public class ActivityManagerService extends IActivityManager.Stub ActiveInstrumentation activeInstr = new ActiveInstrumentation(this); activeInstr.mClass = className; String defProcess = ai.processName;; - if (ii.targetProcess == null) { + if (ii.targetProcesses == null) { activeInstr.mTargetProcesses = new String[]{ai.processName}; - } else if (ii.targetProcess.equals("*")) { + } else if (ii.targetProcesses.equals("*")) { activeInstr.mTargetProcesses = new String[0]; } else { - activeInstr.mTargetProcesses = ii.targetProcess.split(","); + activeInstr.mTargetProcesses = ii.targetProcesses.split(","); defProcess = activeInstr.mTargetProcesses[0]; } activeInstr.mTargetInfo = ai; @@ -21722,9 +21726,11 @@ public class ActivityManagerService extends IActivityManager.Stub } } } catch (Exception e) { - Slog.w(TAG, "Failed setting process group of " + app.pid - + " to " + app.curSchedGroup); - e.printStackTrace(); + if (false) { + Slog.w(TAG, "Failed setting process group of " + app.pid + + " to " + app.curSchedGroup); + Slog.w(TAG, "at location", e); + } } finally { Binder.restoreCallingIdentity(oldId); } diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 728a3b98e638..82e2a3deadf1 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -3301,13 +3301,21 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai final ActivityRecord next = topRunningActivityLocked(); final String myReason = reason + " adjustFocus"; + if (next != r) { if (next != null && StackId.keepFocusInStackIfPossible(mStackId) && isFocusable()) { // For freeform, docked, and pinned stacks we always keep the focus within the // stack as long as there is a running activity. return; } else { + // Task is not guaranteed to be non-null. For example, destroying the + // {@link ActivityRecord} will disassociate the task from the activity. final TaskRecord task = r.getTask(); + + if (task == null) { + throw new IllegalStateException("activity no longer associated with task:" + r); + } + final boolean isAssistantOrOverAssistant = task.getStack().isAssistantStack() || task.isOverAssistantStack(); if (r.frontOfTask && isATopFinishingTask(task) @@ -3373,8 +3381,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + r); if (requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, "stop-no-history", false)) { - // Activity was finished, no need to continue trying to schedule stop. - adjustFocusedActivityStackLocked(r, "stopActivityFinished"); + // If {@link requestFinishActivityLocked} returns {@code true}, + // {@link adjustFocusedActivityStackLocked} would have been already called. r.resumeKeyDispatchingLocked(); return; } diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 1f4b21b14ed5..ca842d5574d3 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -245,6 +245,9 @@ class ActivityStarter { ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container, TaskRecord inTask) { int err = ActivityManager.START_SUCCESS; + // Pull the optional Ephemeral Installer-only bundle out of the options early. + final Bundle verificationBundle + = options != null ? options.popAppVerificationBundle() : null; ProcessRecord callerApp = null; if (caller != null) { @@ -466,7 +469,7 @@ class ActivityStarter { // app [on install success]. if (rInfo != null && rInfo.auxiliaryInfo != null) { intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent, - callingPackage, resolvedType, userId); + callingPackage, verificationBundle, resolvedType, userId); resolvedType = null; callingUid = realCallingUid; callingPid = realCallingPid; @@ -522,14 +525,16 @@ class ActivityStarter { * Creates a launch intent for the given auxiliary resolution data. */ private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse, - Intent originalIntent, String callingPackage, String resolvedType, int userId) { + Intent originalIntent, String callingPackage, Bundle verificationBundle, + String resolvedType, int userId) { if (auxiliaryResponse.needsPhaseTwo) { // request phase two resolution mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo( - auxiliaryResponse, originalIntent, resolvedType, callingPackage, userId); + auxiliaryResponse, originalIntent, resolvedType, callingPackage, + verificationBundle, userId); } return InstantAppResolver.buildEphemeralInstallerIntent(originalIntent, - callingPackage, resolvedType, userId, auxiliaryResponse.packageName, + callingPackage, verificationBundle, resolvedType, userId, auxiliaryResponse.packageName, auxiliaryResponse.splitName, auxiliaryResponse.versionCode, auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo); } diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index ba72dcf23c98..d6bfb35b1935 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -751,6 +751,26 @@ class AppErrors { mAppsNotReportingCrashes.add(proc.info.packageName); } + static boolean isInterestingForBackgroundTraces(ProcessRecord app) { + // The system_server is always considered interesting. + if (app.pid == MY_PID) { + return true; + } + + // A package is considered interesting if any of the following is true : + // + // - It's displaying an activity. + // - It's the SystemUI. + // - It has an overlay or a top UI visible. + // + // NOTE: The check whether a given ProcessRecord belongs to the systemui + // process is a bit of a kludge, but the same pattern seems repeated at + // several places in the system server. + return app.isInterestingToUserLocked() || + (app.info != null && "com.android.systemui".equals(app.info.packageName)) || + (app.hasTopUi || app.hasOverlayUi); + } + final void appNotResponding(ProcessRecord app, ActivityRecord activity, ActivityRecord parent, boolean aboveSystem, final String annotation) { ArrayList<Integer> firstPids = new ArrayList<Integer>(5); @@ -812,7 +832,7 @@ class AppErrors { firstPids.add(app.pid); // Don't dump other PIDs if it's a background ANR - isSilentANR = !showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID; + isSilentANR = !showBackground && !isInterestingForBackgroundTraces(app); if (!isSilentANR) { int parentPid = app.pid; if (parent != null && parent.app != null && parent.app.pid > 0) { diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java index dd16e228cbe3..144eb11cbf85 100644 --- a/services/core/java/com/android/server/am/KeyguardController.java +++ b/services/core/java/com/android/server/am/KeyguardController.java @@ -95,6 +95,7 @@ class KeyguardController { return; } mKeyguardShowing = showing; + dismissDockedStackIfNeeded(); if (showing) { mKeyguardGoingAway = false; mDismissalRequested = false; diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 3c5c5fd0cfe4..b025385413ea 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -520,6 +520,14 @@ final class ProcessRecord { return true; } } + + final int servicesSize = services.size(); + for (int i = 0; i < servicesSize; i++) { + ServiceRecord r = services.valueAt(i); + if (r.isForeground) { + return true; + } + } return false; } diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index 42c405febae7..027dc0862e9d 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -495,8 +495,9 @@ final class ServiceRecord extends Binder { Settings.ACTION_APPLICATION_DETAILS_SETTINGS); runningIntent.setData(Uri.fromParts("package", appInfo.packageName, null)); - PendingIntent pi = PendingIntent.getActivity(ams.mContext, 0, - runningIntent, PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent pi = PendingIntent.getActivityAsUser(ams.mContext, 0, + runningIntent, PendingIntent.FLAG_UPDATE_CURRENT, null, + UserHandle.of(userId)); notiBuilder.setColor(ams.mContext.getColor( com.android.internal .R.color.system_notification_accent_color)); diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 742ee3553896..e2b838f74699 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -232,6 +232,7 @@ public class AudioService extends IAudioService.Stub private static final int MSG_UNMUTE_STREAM = 24; private static final int MSG_DYN_POLICY_MIX_STATE_UPDATE = 25; private static final int MSG_INDICATE_SYSTEM_READY = 26; + private static final int MSG_ACCESSORY_PLUG_MEDIA_UNMUTE = 27; // start of messages handled under wakelock // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(), // and not with sendMsg(..., ..., SENDMSG_QUEUE, ...) @@ -3964,6 +3965,33 @@ public class AudioService extends IAudioService.Stub } } + private static final int DEVICE_MEDIA_UNMUTED_ON_PLUG = + AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE | + AudioSystem.DEVICE_OUT_LINE | + AudioSystem.DEVICE_OUT_ALL_A2DP | + AudioSystem.DEVICE_OUT_ALL_USB | + AudioSystem.DEVICE_OUT_HDMI; + + private void onAccessoryPlugMediaUnmute(int newDevice) { + if (DEBUG_VOL) { + Log.i(TAG, String.format("onAccessoryPlugMediaUnmute newDevice=%d [%s]", + newDevice, AudioSystem.getOutputDeviceName(newDevice))); + } + synchronized (mConnectedDevices) { + if ((newDevice & DEVICE_MEDIA_UNMUTED_ON_PLUG) != 0 + && mStreamStates[AudioSystem.STREAM_MUSIC].mIsMuted + && mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(newDevice) != 0 + && (newDevice & AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC)) != 0) + { + if (DEBUG_VOL) { + Log.i(TAG, String.format(" onAccessoryPlugMediaUnmute unmuting device=%d [%s]", + newDevice, AudioSystem.getOutputDeviceName(newDevice))); + } + mStreamStates[AudioSystem.STREAM_MUSIC].mute(false); + } + } + } + /////////////////////////////////////////////////////////////////////////// // Inner classes /////////////////////////////////////////////////////////////////////////// @@ -4854,6 +4882,10 @@ public class AudioService extends IAudioService.Stub onIndicateSystemReady(); break; + case MSG_ACCESSORY_PLUG_MEDIA_UNMUTE: + onAccessoryPlugMediaUnmute(msg.arg1); + break; + case MSG_PERSIST_MUSIC_ACTIVE_MS: final int musicActiveMs = msg.arg1; Settings.Secure.putIntForUser(mContentResolver, @@ -4942,7 +4974,7 @@ public class AudioService extends IAudioService.Stub // must be called synchronized on mConnectedDevices private void makeA2dpDeviceAvailable(String address, String name) { - // enable A2DP before notifying A2DP connection to avoid unecessary processing in + // enable A2DP before notifying A2DP connection to avoid unnecessary processing in // audio policy manager VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, @@ -4956,6 +4988,8 @@ public class AudioService extends IAudioService.Stub makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address), new DeviceListSpec(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, name, address)); + sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE, + AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, null, 0); } private void onSendBecomingNoisyIntent() { @@ -5115,7 +5149,7 @@ public class AudioService extends IAudioService.Stub private void onBluetoothA2dpDeviceConfigChange(BluetoothDevice btDevice) { - if (DEBUG_VOL) { + if (DEBUG_DEVICES) { Log.d(TAG, "onBluetoothA2dpDeviceConfigChange btDevice=" + btDevice); } if (btDevice == null) { @@ -5132,8 +5166,13 @@ public class AudioService extends IAudioService.Stub final DeviceListSpec deviceSpec = mConnectedDevices.get(key); if (deviceSpec != null) { // Device is connected - AudioSystem.handleDeviceConfigChange(device, address, - btDevice.getName()); + if (AudioSystem.handleDeviceConfigChange(device, address, + btDevice.getName()) != AudioSystem.AUDIO_STATUS_OK) { + // force A2DP device disconnection in case of error so that AudioService state is + // consistent with audio policy manager state + setBluetoothA2dpDeviceConnectionState( + btDevice, BluetoothA2dp.STATE_DISCONNECTED, BluetoothProfile.A2DP_SINK); + } } } } @@ -5176,6 +5215,8 @@ public class AudioService extends IAudioService.Stub return false; } mConnectedDevices.put(deviceKey, new DeviceListSpec(device, deviceName, address)); + sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE, + device, 0, null, 0); return true; } else if (!connect && isConnected) { AudioSystem.setDeviceConnectionState(device, @@ -6182,6 +6223,7 @@ public class AudioService extends IAudioService.Stub pw.print(" mCameraSoundForced="); pw.println(mCameraSoundForced); pw.print(" mHasVibrator="); pw.println(mHasVibrator); pw.print(" mVolumePolicy="); pw.println(mVolumePolicy); + pw.print(" mAvrcpAbsVolSupported="); pw.println(mAvrcpAbsVolSupported); dumpAudioPolicies(pw); diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java index ac5fb43f9344..b42242eb4423 100644 --- a/services/core/java/com/android/server/connectivity/Tethering.java +++ b/services/core/java/com/android/server/connectivity/Tethering.java @@ -218,6 +218,10 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering return (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); } + private WifiManager getWifiManager() { + return (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); + } + private void updateConfiguration() { mConfig = new TetheringConfiguration(mContext); } @@ -396,9 +400,9 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering private int setWifiTethering(final boolean enable) { synchronized (mPublicSync) { mWifiTetherRequested = enable; - final WifiManager wifiManager = - (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); - if (wifiManager.setWifiApEnabled(null /* use existing wifi config */, enable)) { + final WifiManager wifiManager = getWifiManager(); + if ((enable && wifiManager.startSoftAp(null /* use existing wifi config */)) || + (!enable && wifiManager.stopSoftAp())) { return ConnectivityManager.TETHER_ERROR_NO_ERROR; } return ConnectivityManager.TETHER_ERROR_MASTER_ERROR; @@ -1420,12 +1424,37 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering } else { mForwardedDownstreams.remove(who); } + + // If this is a Wi-Fi interface, notify WifiManager of the active serving state. + if (who.interfaceType() == ConnectivityManager.TETHERING_WIFI) { + final WifiManager mgr = getWifiManager(); + final String iface = who.interfaceName(); + switch (mode) { + case IControlsTethering.STATE_TETHERED: + mgr.updateInterfaceIpState(iface, WifiManager.IFACE_IP_MODE_TETHERED); + break; + case IControlsTethering.STATE_LOCAL_ONLY: + mgr.updateInterfaceIpState(iface, WifiManager.IFACE_IP_MODE_LOCAL_ONLY); + break; + default: + Log.wtf(TAG, "Unknown active serving mode: " + mode); + break; + } + } } private void handleInterfaceServingStateInactive(TetherInterfaceStateMachine who) { mNotifyList.remove(who); mIPv6TetheringCoordinator.removeActiveDownstream(who); mForwardedDownstreams.remove(who); + + // If this is a Wi-Fi interface, tell WifiManager of any errors. + if (who.interfaceType() == ConnectivityManager.TETHERING_WIFI) { + if (who.lastError() != ConnectivityManager.TETHER_ERROR_NO_ERROR) { + getWifiManager().updateInterfaceIpState( + who.interfaceName(), WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR); + } + } } class InitialState extends State { @@ -1742,7 +1771,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering public void notifyInterfaceStateChange(String iface, TetherInterfaceStateMachine who, int state, int error) { synchronized (mPublicSync) { - TetherState tetherState = mTetherStates.get(iface); + final TetherState tetherState = mTetherStates.get(iface); if (tetherState != null && tetherState.stateMachine.equals(who)) { tetherState.lastState = state; tetherState.lastError = error; diff --git a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java index e21349af8649..d3cfd875faae 100644 --- a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java +++ b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java @@ -117,9 +117,11 @@ public class TetherInterfaceStateMachine extends StateMachine { setInitialState(mInitialState); } - public int interfaceType() { - return mInterfaceType; - } + public String interfaceName() { return mIfaceName; } + + public int interfaceType() { return mInterfaceType; } + + public int lastError() { return mLastError; } // configured when we start tethering and unconfig'd on error or conclusion private boolean configureIfaceIp(boolean enabled) { diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java index 313abab7a750..dbccc0765b73 100644 --- a/services/core/java/com/android/server/dreams/DreamManagerService.java +++ b/services/core/java/com/android/server/dreams/DreamManagerService.java @@ -353,6 +353,7 @@ public final class DreamManagerService extends SystemService { && mCurrentDreamIsTest == isTest && mCurrentDreamCanDoze == canDoze && mCurrentDreamUserId == userId) { + Slog.i(TAG, "Already in target dream."); return; } @@ -388,6 +389,7 @@ public final class DreamManagerService extends SystemService { mHandler.post(new Runnable() { @Override public void run() { + Slog.i(TAG, "Performing gentle wake from dream."); mController.stopDream(immediate); } }); diff --git a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java index 848704ec58c4..1c31c3e6af96 100644 --- a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java +++ b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java @@ -109,44 +109,49 @@ public class JobSchedulerShellCommand extends ShellCommand { final String pkgName = getNextArgRequired(); final int jobId = Integer.parseInt(getNextArgRequired()); - int ret = mInternal.executeRunCommand(pkgName, userId, jobId, force); - switch (ret) { - case CMD_ERR_NO_PACKAGE: - pw.print("Package not found: "); - pw.print(pkgName); - pw.print(" / user "); - pw.println(userId); - break; - - case CMD_ERR_NO_JOB: - pw.print("Could not find job "); - pw.print(jobId); - pw.print(" in package "); - pw.print(pkgName); - pw.print(" / user "); - pw.println(userId); - break; - - case CMD_ERR_CONSTRAINTS: - pw.print("Job "); - pw.print(jobId); - pw.print(" in package "); - pw.print(pkgName); - pw.print(" / user "); - pw.print(userId); - pw.println(" has functional constraints but --force not specified"); - break; - - default: - // success! - pw.print("Running job"); - if (force) { - pw.print(" [FORCED]"); - } - pw.println(); - break; + final long ident = Binder.clearCallingIdentity(); + try { + int ret = mInternal.executeRunCommand(pkgName, userId, jobId, force); + switch (ret) { + case CMD_ERR_NO_PACKAGE: + pw.print("Package not found: "); + pw.print(pkgName); + pw.print(" / user "); + pw.println(userId); + break; + + case CMD_ERR_NO_JOB: + pw.print("Could not find job "); + pw.print(jobId); + pw.print(" in package "); + pw.print(pkgName); + pw.print(" / user "); + pw.println(userId); + break; + + case CMD_ERR_CONSTRAINTS: + pw.print("Job "); + pw.print(jobId); + pw.print(" in package "); + pw.print(pkgName); + pw.print(" / user "); + pw.print(userId); + pw.println(" has functional constraints but --force not specified"); + break; + + default: + // success! + pw.print("Running job"); + if (force) { + pw.print(" [FORCED]"); + } + pw.println(); + break; + } + return ret; + } finally { + Binder.restoreCallingIdentity(ident); } - return ret; } private int runMonitorBattery(PrintWriter pw) throws Exception { diff --git a/services/core/java/com/android/server/location/GeofenceManager.java b/services/core/java/com/android/server/location/GeofenceManager.java index e24bf7620fe3..2493dfb42a60 100644 --- a/services/core/java/com/android/server/location/GeofenceManager.java +++ b/services/core/java/com/android/server/location/GeofenceManager.java @@ -23,8 +23,10 @@ import java.util.List; import android.app.AppOpsManager; import android.app.PendingIntent; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.database.ContentObserver; import android.location.Geofence; import android.location.Location; import android.location.LocationListener; @@ -35,6 +37,8 @@ import android.os.Handler; import android.os.Message; import android.os.PowerManager; import android.os.SystemClock; +import android.os.UserHandle; +import android.provider.Settings; import android.util.Slog; import com.android.server.LocationManagerService; @@ -58,9 +62,9 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish private static final long MAX_AGE_NANOS = 5 * 60 * 1000000000L; // five minutes /** - * Most frequent update interval allowed. + * The default value of most frequent update interval allowed. */ - private static final long MIN_INTERVAL_MS = 1 * 60 * 1000; // one minute + private static final long DEFAULT_MIN_INTERVAL_MS = 30 * 60 * 1000; // 30 minutes /** * Least frequent update interval allowed. @@ -106,6 +110,12 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish */ private boolean mPendingUpdate; + /** + * The actual value of most frequent update interval allowed. + */ + private long mEffectiveMinIntervalMs; + private ContentResolver mResolver; + public GeofenceManager(Context context, LocationBlacklist blacklist) { mContext = context; mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); @@ -114,6 +124,28 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); mHandler = new GeofenceHandler(); mBlacklist = blacklist; + mResolver = mContext.getContentResolver(); + updateMinInterval(); + mResolver.registerContentObserver( + Settings.Global.getUriFor( + Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS), + true, + new ContentObserver(mHandler) { + @Override + public void onChange(boolean selfChange) { + synchronized (mLock) { + updateMinInterval(); + } + } + }, UserHandle.USER_ALL); + } + + /** + * Updates the minimal location request frequency. + */ + private void updateMinInterval() { + mEffectiveMinIntervalMs = Settings.Global.getLong(mResolver, + Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS, DEFAULT_MIN_INTERVAL_MS); } public void addFence(LocationRequest request, Geofence geofence, PendingIntent intent, @@ -301,10 +333,10 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish // Compute a location update interval based on the distance to the nearest fence. long intervalMs; if (location != null && Double.compare(minFenceDistance, Double.MAX_VALUE) != 0) { - intervalMs = (long)Math.min(MAX_INTERVAL_MS, Math.max(MIN_INTERVAL_MS, + intervalMs = (long)Math.min(MAX_INTERVAL_MS, Math.max(mEffectiveMinIntervalMs, minFenceDistance * 1000 / MAX_SPEED_M_S)); } else { - intervalMs = MIN_INTERVAL_MS; + intervalMs = mEffectiveMinIntervalMs; } if (!mReceivingLocationUpdates || mLocationUpdateInterval != intervalMs) { mReceivingLocationUpdates = true; diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index c802179ba3a4..d9ca00c1cb77 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -2879,17 +2879,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final List<UserInfo> users = mUserManager.getUsers(); for (int ui = users.size() - 1; ui >= 0; ui--) { UserInfo user = users.get(ui); - for (int i = mPowerSaveTempWhitelistAppIds.size() - 1; i >= 0; i--) { - if (mPowerSaveTempWhitelistAppIds.valueAt(i)) { - int appId = mPowerSaveTempWhitelistAppIds.keyAt(i); - int uid = UserHandle.getUid(user.id, appId); - uidRules.put(uid, FIREWALL_RULE_ALLOW); - } - } - for (int i = mPowerSaveWhitelistAppIds.size() - 1; i >= 0; i--) { - int appId = mPowerSaveWhitelistAppIds.keyAt(i); - int uid = UserHandle.getUid(user.id, appId); - uidRules.put(uid, FIREWALL_RULE_ALLOW); + updateRulesForWhitelistedAppIds(uidRules, mPowerSaveTempWhitelistAppIds, user.id); + updateRulesForWhitelistedAppIds(uidRules, mPowerSaveWhitelistAppIds, user.id); + if (chain == FIREWALL_CHAIN_POWERSAVE) { + updateRulesForWhitelistedAppIds(uidRules, + mPowerSaveWhitelistExceptIdleAppIds, user.id); } } for (int i = mUidState.size() - 1; i >= 0; i--) { @@ -2903,16 +2897,39 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } - private boolean isWhitelistedBatterySaverUL(int uid) { + private void updateRulesForWhitelistedAppIds(final SparseIntArray uidRules, + final SparseBooleanArray whitelistedAppIds, int userId) { + for (int i = whitelistedAppIds.size() - 1; i >= 0; --i) { + if (whitelistedAppIds.valueAt(i)) { + final int appId = whitelistedAppIds.keyAt(i); + final int uid = UserHandle.getUid(userId, appId); + uidRules.put(uid, FIREWALL_RULE_ALLOW); + } + } + } + + /** + * @param deviceIdleMode if true then we don't consider + * {@link #mPowerSaveWhitelistExceptIdleAppIds} for checking if the {@param uid} is + * whitelisted. + */ + private boolean isWhitelistedBatterySaverUL(int uid, boolean deviceIdleMode) { final int appId = UserHandle.getAppId(uid); - return mPowerSaveTempWhitelistAppIds.get(appId) || mPowerSaveWhitelistAppIds.get(appId); + boolean isWhitelisted = mPowerSaveTempWhitelistAppIds.get(appId) + || mPowerSaveWhitelistAppIds.get(appId); + if (!deviceIdleMode) { + isWhitelisted = isWhitelisted || mPowerSaveWhitelistExceptIdleAppIds.get(appId); + } + return isWhitelisted; } // NOTE: since both fw_dozable and fw_powersave uses the same map // (mPowerSaveTempWhitelistAppIds) for whitelisting, we can reuse their logic in this method. private void updateRulesForWhitelistedPowerSaveUL(int uid, boolean enabled, int chain) { if (enabled) { - if (isWhitelistedBatterySaverUL(uid) || isUidForegroundOnRestrictPowerUL(uid)) { + final boolean isWhitelisted = isWhitelistedBatterySaverUL(uid, + chain == FIREWALL_CHAIN_DOZABLE); + if (isWhitelisted || isUidForegroundOnRestrictPowerUL(uid)) { setUidFirewallRule(chain, uid, FIREWALL_RULE_ALLOW); } else { setUidFirewallRule(chain, uid, FIREWALL_RULE_DEFAULT); @@ -3430,7 +3447,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final boolean restrictMode = isIdle || mRestrictPower || mDeviceIdleMode; final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid); - final boolean isWhitelisted = isWhitelistedBatterySaverUL(uid); + final boolean isWhitelisted = isWhitelistedBatterySaverUL(uid, mDeviceIdleMode); final int oldRule = oldUidRules & MASK_ALL_NETWORKS; int newRule = RULE_NONE; diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 51cc39174f0d..b8ca2bb6d3c7 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -56,6 +56,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_TOAST; import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; import android.Manifest; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManagerInternal; @@ -980,6 +981,14 @@ public class NotificationManagerService extends SystemService { void addNotification(NotificationRecord r) { mNotificationList.add(r); mNotificationsByKey.put(r.sbn.getKey(), r); + if (r.sbn.isGroup()) { + mSummaryByGroupKey.put(r.getGroupKey(), r); + } + } + + @VisibleForTesting + void addEnqueuedNotification(NotificationRecord r) { + mEnqueuedNotifications.add(r); } @VisibleForTesting @@ -1016,7 +1025,7 @@ public class NotificationManagerService extends SystemService { @VisibleForTesting void init(Looper looper, IPackageManager packageManager, PackageManager packageManagerClient, LightsManager lightsManager, NotificationListeners notificationListeners, - ICompanionDeviceManager companionManager) { + ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper) { Resources resources = getContext().getResources(); mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(), Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE, @@ -1071,21 +1080,7 @@ public class NotificationManagerService extends SystemService { sendRegisteredOnlyBroadcast(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED); } }); - mSnoozeHelper = new SnoozeHelper(getContext(), new SnoozeHelper.Callback() { - @Override - public void repost(int userId, NotificationRecord r) { - try { - if (DBG) { - Slog.d(TAG, "Reposting " + r.getKey()); - } - enqueueNotificationInternal(r.sbn.getPackageName(), r.sbn.getOpPkg(), - r.sbn.getUid(), r.sbn.getInitialPid(), r.sbn.getTag(), r.sbn.getId(), - r.sbn.getNotification(), userId); - } catch (Exception e) { - Slog.e(TAG, "Cannot un-snooze notification", e); - } - } - }, mUserProfiles); + mSnoozeHelper = snoozeHelper; mGroupHelper = new GroupHelper(new GroupHelper.Callback() { @Override public void addAutoGroup(String key) { @@ -1204,9 +1199,25 @@ public class NotificationManagerService extends SystemService { @Override public void onStart() { + SnoozeHelper snoozeHelper = new SnoozeHelper(getContext(), new SnoozeHelper.Callback() { + @Override + public void repost(int userId, NotificationRecord r) { + try { + if (DBG) { + Slog.d(TAG, "Reposting " + r.getKey()); + } + enqueueNotificationInternal(r.sbn.getPackageName(), r.sbn.getOpPkg(), + r.sbn.getUid(), r.sbn.getInitialPid(), r.sbn.getTag(), r.sbn.getId(), + r.sbn.getNotification(), userId); + } catch (Exception e) { + Slog.e(TAG, "Cannot un-snooze notification", e); + } + } + }, mUserProfiles); + init(Looper.myLooper(), AppGlobals.getPackageManager(), getContext().getPackageManager(), getLocalService(LightsManager.class), new NotificationListeners(), - null); + null, snoozeHelper); publishBinderService(Context.NOTIFICATION_SERVICE, mService); publishLocalService(NotificationManagerInternal.class, mInternalService); } @@ -3304,7 +3315,7 @@ public class NotificationManagerService extends SystemService { return false; } } else if (isCallerInstantApp(pkg)) { - // Ephemeral apps have some special contraints for notifications. + // Ephemeral apps have some special constraints for notifications. // They are not allowed to create new notifications however they are allowed to // update notifications created by the system (e.g. a foreground service // notification). @@ -3378,6 +3389,76 @@ public class NotificationManagerService extends SystemService { return isBlocked; } + protected class SnoozeNotificationRunnable implements Runnable { + private final String mKey; + private final long mDuration; + private final String mSnoozeCriterionId; + + SnoozeNotificationRunnable(String key, long duration, String snoozeCriterionId) { + mKey = key; + mDuration = duration; + mSnoozeCriterionId = snoozeCriterionId; + } + + @Override + public void run() { + synchronized (mNotificationLock) { + final NotificationRecord r = findNotificationByKeyLocked(mKey); + if (r != null) { + snoozeLocked(r); + } + } + } + + void snoozeLocked(NotificationRecord r) { + if (r.sbn.isGroup()) { + final List<NotificationRecord> groupNotifications = findGroupNotificationsLocked( + r.sbn.getPackageName(), r.sbn.getGroupKey(), r.sbn.getUserId()); + if (r.getNotification().isGroupSummary()) { + // snooze summary and all children + for (int i = 0; i < groupNotifications.size(); i++) { + snoozeNotificationLocked(groupNotifications.get(i)); + } + } else { + // if there is a valid summary for this group, and we are snoozing the only + // child, also snooze the summary + if (mSummaryByGroupKey.containsKey(r.sbn.getGroupKey())) { + if (groupNotifications.size() != 2) { + snoozeNotificationLocked(r); + } else { + // snooze summary and the one child + for (int i = 0; i < groupNotifications.size(); i++) { + snoozeNotificationLocked(groupNotifications.get(i)); + } + } + } else { + snoozeNotificationLocked(r); + } + } + } else { + // just snooze the one notification + snoozeNotificationLocked(r); + } + } + + void snoozeNotificationLocked(NotificationRecord r) { + MetricsLogger.action(r.getLogMaker() + .setCategory(MetricsEvent.NOTIFICATION_SNOOZED) + .setType(MetricsEvent.TYPE_CLOSE) + .addTaggedData(MetricsEvent.NOTIFICATION_SNOOZED_CRITERIA, + mSnoozeCriterionId == null ? 0 : 1)); + cancelNotificationLocked(r, false, REASON_SNOOZED); + updateLightsLocked(); + if (mSnoozeCriterionId != null) { + mNotificationAssistants.notifyAssistantSnoozedLocked(r.sbn, mSnoozeCriterionId); + mSnoozeHelper.snooze(r); + } else { + mSnoozeHelper.snooze(r, mDuration); + } + savePolicyFile(); + } + } + protected class EnqueueNotificationRunnable implements Runnable { private final NotificationRecord r; private final int userId; @@ -3412,6 +3493,11 @@ public class NotificationManagerService extends SystemService { // can to avoid extracting signals. handleGroupedNotificationLocked(r, old, callingUid, callingPid); + // if this is a group child, unsnooze parent summary + if (n.isGroup() && notification.isGroupChild()) { + mSnoozeHelper.repostGroupSummary(pkg, r.getUserId(), n.getGroupKey()); + } + // This conditional is a dirty hack to limit the logging done on // behalf of the download manager without affecting other apps. if (!pkg.equals("com.android.providers.downloads") @@ -4394,31 +4480,7 @@ public class NotificationManagerService extends SystemService { snoozeCriterionId, listenerName)); } // Needs to post so that it can cancel notifications not yet enqueued. - mHandler.post(new Runnable() { - @Override - public void run() { - synchronized (mNotificationLock) { - final NotificationRecord r = findNotificationByKeyLocked(key); - if (r != null) { - MetricsLogger.action(r.getLogMaker() - .setCategory(MetricsEvent.NOTIFICATION_SNOOZED) - .setType(MetricsEvent.TYPE_CLOSE) - .addTaggedData(MetricsEvent.NOTIFICATION_SNOOZED_CRITERIA, - snoozeCriterionId == null ? 0 : 1)); - cancelNotificationLocked(r, false, REASON_SNOOZED); - updateLightsLocked(); - if (snoozeCriterionId != null) { - mNotificationAssistants.notifyAssistantSnoozedLocked(r.sbn, - snoozeCriterionId); - mSnoozeHelper.snooze(r); - } else { - mSnoozeHelper.snooze(r, duration); - } - savePolicyFile(); - } - } - } - }); + mHandler.post(new SnoozeNotificationRunnable(key, duration, snoozeCriterionId)); } void unsnoozeNotificationInt(String key, ManagedServiceInfo listener) { @@ -4531,6 +4593,30 @@ public class NotificationManagerService extends SystemService { } } + @NonNull List<NotificationRecord> findGroupNotificationsLocked(String pkg, + String groupKey, int userId) { + List<NotificationRecord> records = new ArrayList<>(); + records.addAll(findGroupNotificationByListLocked(mNotificationList, pkg, groupKey, userId)); + records.addAll( + findGroupNotificationByListLocked(mEnqueuedNotifications, pkg, groupKey, userId)); + return records; + } + + + private @NonNull List<NotificationRecord> findGroupNotificationByListLocked( + ArrayList<NotificationRecord> list, String pkg, String groupKey, int userId) { + List<NotificationRecord> records = new ArrayList<>(); + final int len = list.size(); + for (int i = 0; i < len; i++) { + NotificationRecord r = list.get(i); + if (notificationMatchesUserId(r, userId) && r.getGroupKey().equals(groupKey) + && r.sbn.getPackageName().equals(pkg)) { + records.add(r); + } + } + return records; + } + // Searches both enqueued and posted notifications by key. // TODO: need to combine a bunch of these getters with slightly different behavior. // TODO: Should enqueuing just add to mNotificationsByKey instead? @@ -4545,7 +4631,7 @@ public class NotificationManagerService extends SystemService { return null; } - private NotificationRecord findNotificationLocked(String pkg, String tag, int id, int userId) { + NotificationRecord findNotificationLocked(String pkg, String tag, int id, int userId) { NotificationRecord r; if ((r = findNotificationByListLocked(mNotificationList, pkg, tag, id, userId)) != null) { return r; diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java index 913f636edfba..42b4f573dfcc 100644 --- a/services/core/java/com/android/server/notification/SnoozeHelper.java +++ b/services/core/java/com/android/server/notification/SnoozeHelper.java @@ -25,6 +25,7 @@ import org.xmlpull.v1.XmlSerializer; import android.annotation.NonNull; import android.app.AlarmManager; +import android.app.Notification; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; @@ -61,7 +62,6 @@ public class SnoozeHelper { private static final String REPOST_ACTION = SnoozeHelper.class.getSimpleName() + ".EVALUATE"; private static final int REQUEST_CODE_REPOST = 1; private static final String REPOST_SCHEME = "repost"; - private static final String EXTRA_PKG = "pkg"; private static final String EXTRA_KEY = "key"; private static final String EXTRA_USER_ID = "userId"; @@ -98,7 +98,7 @@ public class SnoozeHelper { protected Collection<NotificationRecord> getSnoozed(int userId, String pkg) { if (mSnoozedNotifications.containsKey(userId) && mSnoozedNotifications.get(userId).containsKey(pkg)) { - mSnoozedNotifications.get(userId).get(pkg).values(); + return mSnoozedNotifications.get(userId).get(pkg).values(); } return Collections.EMPTY_LIST; } @@ -106,16 +106,18 @@ public class SnoozeHelper { protected @NonNull List<NotificationRecord> getSnoozed() { List<NotificationRecord> snoozedForUser = new ArrayList<>(); int[] userIds = mUserProfiles.getCurrentProfileIds(); - final int N = userIds.length; - for (int i = 0; i < N; i++) { - final ArrayMap<String, ArrayMap<String, NotificationRecord>> snoozedPkgs = - mSnoozedNotifications.get(userIds[i]); - if (snoozedPkgs != null) { - final int M = snoozedPkgs.size(); - for (int j = 0; j < M; j++) { - final ArrayMap<String, NotificationRecord> records = snoozedPkgs.valueAt(j); - if (records != null) { - snoozedForUser.addAll(records.values()); + if (userIds != null) { + final int N = userIds.length; + for (int i = 0; i < N; i++) { + final ArrayMap<String, ArrayMap<String, NotificationRecord>> snoozedPkgs = + mSnoozedNotifications.get(userIds[i]); + if (snoozedPkgs != null) { + final int M = snoozedPkgs.size(); + for (int j = 0; j < M; j++) { + final ArrayMap<String, NotificationRecord> records = snoozedPkgs.valueAt(j); + if (records != null) { + snoozedForUser.addAll(records.values()); + } } } } @@ -281,6 +283,42 @@ public class SnoozeHelper { } } + protected void repostGroupSummary(String pkg, int userId, String groupKey) { + if (mSnoozedNotifications.containsKey(userId)) { + ArrayMap<String, ArrayMap<String, NotificationRecord>> keysByPackage + = mSnoozedNotifications.get(userId); + + if (keysByPackage != null && keysByPackage.containsKey(pkg)) { + ArrayMap<String, NotificationRecord> recordsByKey = keysByPackage.get(pkg); + + if (recordsByKey != null) { + String groupSummaryKey = null; + int N = recordsByKey.size(); + for (int i = 0; i < N; i++) { + final NotificationRecord potentialGroupSummary = recordsByKey.valueAt(i); + if (potentialGroupSummary.sbn.isGroup() + && potentialGroupSummary.getNotification().isGroupSummary() + && groupKey.equals(potentialGroupSummary.getGroupKey())) { + groupSummaryKey = potentialGroupSummary.getKey(); + break; + } + } + + if (groupSummaryKey != null) { + NotificationRecord record = recordsByKey.remove(groupSummaryKey); + mPackages.remove(groupSummaryKey); + mUsers.remove(groupSummaryKey); + + MetricsLogger.action(record.getLogMaker() + .setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED) + .setType(MetricsProto.MetricsEvent.TYPE_OPEN)); + mCallback.repost(userId, record); + } + } + } + } + } + private PendingIntent createPendingIntent(String pkg, String key, int userId) { return PendingIntent.getBroadcast(mContext, REQUEST_CODE_REPOST, diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java index fc9e0a3edd51..b1659841d5ac 100644 --- a/services/core/java/com/android/server/pm/InstantAppRegistry.java +++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java @@ -218,6 +218,11 @@ class InstantAppRegistry { byte[] randomBytes = new byte[8]; new SecureRandom().nextBytes(randomBytes); String id = ByteStringUtils.toHexString(randomBytes).toLowerCase(Locale.US); + File appDir = getInstantApplicationDir(packageName, userId); + if (!appDir.exists() && !appDir.mkdirs()) { + Slog.e(LOG_TAG, "Cannot create instant app cookie directory"); + return id; + } File idFile = new File(getInstantApplicationDir(packageName, userId), INSTANT_APP_ANDROID_ID_FILE); try (FileOutputStream fos = new FileOutputStream(idFile)) { diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java index b56db047fd30..624d8c9ef13e 100644 --- a/services/core/java/com/android/server/pm/InstantAppResolver.java +++ b/services/core/java/com/android/server/pm/InstantAppResolver.java @@ -41,6 +41,7 @@ import android.content.pm.InstantAppResolveInfo.InstantAppDigest; import android.metrics.LogMaker; import android.os.Binder; import android.os.Build; +import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; import android.util.Log; @@ -147,6 +148,7 @@ public abstract class InstantAppResolver { final Intent installerIntent = buildEphemeralInstallerIntent( requestObj.origIntent, requestObj.callingPackage, + requestObj.verificationBundle, requestObj.resolvedType, requestObj.userId, packageName, @@ -172,6 +174,7 @@ public abstract class InstantAppResolver { */ public static Intent buildEphemeralInstallerIntent(@NonNull Intent origIntent, @NonNull String callingPackage, + @Nullable Bundle verificationBundle, @NonNull String resolvedType, int userId, @NonNull String instantAppPackageName, @@ -234,6 +237,10 @@ public abstract class InstantAppResolver { intent.putExtra(Intent.EXTRA_PACKAGE_NAME, instantAppPackageName); intent.putExtra(Intent.EXTRA_SPLIT_NAME, instantAppSplitName); intent.putExtra(Intent.EXTRA_VERSION_CODE, versionCode); + intent.putExtra(Intent.EXTRA_CALLING_PACKAGE, callingPackage); + if (verificationBundle != null) { + intent.putExtra(Intent.EXTRA_VERIFICATION_BUNDLE, verificationBundle); + } } return intent; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 7bbb1feeb09c..a56590e3f00b 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -739,12 +739,123 @@ public class PackageManagerService extends IPackageManager.Stub @GuardedBy("mPackages") final SparseArray<Map<String, Integer>> mChangedPackagesSequenceNumbers = new SparseArray<>(); - final PackageParser.Callback mPackageParserCallback = new PackageParser.Callback() { - @Override public boolean hasFeature(String feature) { + class PackageParserCallback implements PackageParser.Callback { + @Override public final boolean hasFeature(String feature) { return PackageManagerService.this.hasSystemFeature(feature, 0); } + + final List<PackageParser.Package> getStaticOverlayPackagesLocked( + Collection<PackageParser.Package> allPackages, String targetPackageName) { + List<PackageParser.Package> overlayPackages = null; + for (PackageParser.Package p : allPackages) { + if (targetPackageName.equals(p.mOverlayTarget) && p.mIsStaticOverlay) { + if (overlayPackages == null) { + overlayPackages = new ArrayList<PackageParser.Package>(); + } + overlayPackages.add(p); + } + } + if (overlayPackages != null) { + Comparator<PackageParser.Package> cmp = new Comparator<PackageParser.Package>() { + public int compare(PackageParser.Package p1, PackageParser.Package p2) { + return p1.mOverlayPriority - p2.mOverlayPriority; + } + }; + Collections.sort(overlayPackages, cmp); + } + return overlayPackages; + } + + final String[] getStaticOverlayPathsLocked(Collection<PackageParser.Package> allPackages, + String targetPackageName, String targetPath) { + if ("android".equals(targetPackageName)) { + // Static RROs targeting to "android", ie framework-res.apk, are already applied by + // native AssetManager. + return null; + } + List<PackageParser.Package> overlayPackages = + getStaticOverlayPackagesLocked(allPackages, targetPackageName); + if (overlayPackages == null || overlayPackages.isEmpty()) { + return null; + } + List<String> overlayPathList = null; + for (PackageParser.Package overlayPackage : overlayPackages) { + if (targetPath == null) { + if (overlayPathList == null) { + overlayPathList = new ArrayList<String>(); + } + overlayPathList.add(overlayPackage.baseCodePath); + continue; + } + + try { + // Creates idmaps for system to parse correctly the Android manifest of the + // target package. + // + // OverlayManagerService will update each of them with a correct gid from its + // target package app id. + mInstaller.idmap(targetPath, overlayPackage.baseCodePath, + UserHandle.getSharedAppGid( + UserHandle.getUserGid(UserHandle.USER_SYSTEM))); + if (overlayPathList == null) { + overlayPathList = new ArrayList<String>(); + } + overlayPathList.add(overlayPackage.baseCodePath); + } catch (InstallerException e) { + Slog.e(TAG, "Failed to generate idmap for " + targetPath + " and " + + overlayPackage.baseCodePath); + } + } + return overlayPathList == null ? null : overlayPathList.toArray(new String[0]); + } + + String[] getStaticOverlayPaths(String targetPackageName, String targetPath) { + synchronized (mPackages) { + return getStaticOverlayPathsLocked( + mPackages.values(), targetPackageName, targetPath); + } + } + + @Override public final String[] getOverlayApks(String targetPackageName) { + return getStaticOverlayPaths(targetPackageName, null); + } + + @Override public final String[] getOverlayPaths(String targetPackageName, + String targetPath) { + return getStaticOverlayPaths(targetPackageName, targetPath); + } }; + class ParallelPackageParserCallback extends PackageParserCallback { + List<PackageParser.Package> mOverlayPackages = null; + + void findStaticOverlayPackages() { + synchronized (mPackages) { + for (PackageParser.Package p : mPackages.values()) { + if (p.mIsStaticOverlay) { + if (mOverlayPackages == null) { + mOverlayPackages = new ArrayList<PackageParser.Package>(); + } + mOverlayPackages.add(p); + } + } + } + } + + @Override + synchronized String[] getStaticOverlayPaths(String targetPackageName, String targetPath) { + // We can trust mOverlayPackages without holding mPackages because package uninstall + // can't happen while running parallel parsing. + // Moreover holding mPackages on each parsing thread causes dead-lock. + return mOverlayPackages == null ? null : + getStaticOverlayPathsLocked(mOverlayPackages, targetPackageName, targetPath); + } + } + + final PackageParser.Callback mPackageParserCallback = new PackageParserCallback(); + final ParallelPackageParserCallback mParallelPackageParserCallback = + new ParallelPackageParserCallback(); + public static final class SharedLibraryEntry { public final String path; public final String apk; @@ -2453,6 +2564,8 @@ public class PackageManagerService extends IPackageManager.Stub | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0); + mParallelPackageParserCallback.findStaticOverlayPackages(); + // Find base frameworks (resource packages without code). scanDirTracedLI(frameworkDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM @@ -5820,10 +5933,10 @@ public class PackageManagerService extends IPackageManager.Stub private void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj, Intent origIntent, String resolvedType, String callingPackage, - int userId) { + Bundle verificationBundle, int userId) { final Message msg = mHandler.obtainMessage(INSTANT_APP_RESOLUTION_PHASE_TWO, new InstantAppRequest(responseObj, origIntent, resolvedType, - callingPackage, userId)); + callingPackage, userId, verificationBundle)); mHandler.sendMessage(msg); } @@ -6372,7 +6485,7 @@ public class PackageManagerService extends IPackageManager.Stub Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveEphemeral"); final InstantAppRequest requestObject = new InstantAppRequest( null /*responseObj*/, intent /*origIntent*/, resolvedType, - null /*callingPackage*/, userId); + null /*callingPackage*/, userId, null /*verificationBundle*/); final AuxiliaryResolveInfo auxiliaryResponse = InstantAppResolver.doInstantAppResolutionPhaseOne( mContext, mInstantAppResolverConnection, requestObject); @@ -7856,7 +7969,8 @@ public class PackageManagerService extends IPackageManager.Stub + " flags=0x" + Integer.toHexString(parseFlags)); } ParallelPackageParser parallelPackageParser = new ParallelPackageParser( - mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir, mPackageParserCallback); + mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir, + mParallelPackageParserCallback); // Submit files for parsing in parallel int fileCount = 0; @@ -17075,10 +17189,10 @@ public class PackageManagerService extends IPackageManager.Stub PackageParser.Permission perm = pkg.permissions.get(i); BasePermission bp = mSettings.mPermissions.get(perm.info.name); - // Don't allow anyone but the platform to define ephemeral permissions. + // Don't allow anyone but the system to define ephemeral permissions. if ((perm.info.protectionLevel & PermissionInfo.PROTECTION_FLAG_EPHEMERAL) != 0 - && !PLATFORM_PACKAGE_NAME.equals(pkg.packageName)) { - Slog.w(TAG, "Package " + pkg.packageName + && !systemApp) { + Slog.w(TAG, "Non-System package " + pkg.packageName + " attempting to delcare ephemeral permission " + perm.info.name + "; Removing ephemeral."); perm.info.protectionLevel &= ~PermissionInfo.PROTECTION_FLAG_EPHEMERAL; @@ -20570,6 +20684,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); public static final int DUMP_DEXOPT = 1 << 20; public static final int DUMP_COMPILER_STATS = 1 << 21; public static final int DUMP_ENABLED_OVERLAYS = 1 << 22; + public static final int DUMP_CHANGES = 1 << 23; public static final int OPTION_SHOW_FILTERS = 1 << 0; @@ -20815,6 +20930,8 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); dumpState.setDump(DumpState.DUMP_COMPILER_STATS); } else if ("enabled-overlays".equals(cmd)) { dumpState.setDump(DumpState.DUMP_ENABLED_OVERLAYS); + } else if ("changes".equals(cmd)) { + dumpState.setDump(DumpState.DUMP_CHANGES); } else if ("write".equals(cmd)) { synchronized (mPackages) { mSettings.writeLPr(); @@ -21145,6 +21262,31 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); mSettings.dumpSharedUsersLPr(pw, packageName, permissionNames, dumpState, checkin); } + if (dumpState.isDumping(DumpState.DUMP_CHANGES)) { + if (dumpState.onTitlePrinted()) pw.println(); + pw.println("Package Changes:"); + pw.print(" Sequence number="); pw.println(mChangedPackagesSequenceNumber); + final int K = mChangedPackages.size(); + for (int i = 0; i < K; i++) { + final SparseArray<String> changes = mChangedPackages.valueAt(i); + pw.print(" User "); pw.print(mChangedPackages.keyAt(i)); pw.println(":"); + final int N = changes.size(); + if (N == 0) { + pw.print(" "); pw.println("No packages changed"); + } else { + for (int j = 0; j < N; j++) { + final String pkgName = changes.valueAt(j); + final int sequenceNumber = changes.keyAt(j); + pw.print(" "); + pw.print("seq="); + pw.print(sequenceNumber); + pw.print(", package="); + pw.println(pkgName); + } + } + } + } + if (!checkin && dumpState.isDumping(DumpState.DUMP_PERMISSIONS) && packageName == null) { mSettings.dumpRestoredPermissionGrantsLPr(pw, dumpState); } @@ -23423,9 +23565,11 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); @Override public void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj, - Intent origIntent, String resolvedType, String callingPackage, int userId) { + Intent origIntent, String resolvedType, String callingPackage, + Bundle verificationBundle, int userId) { PackageManagerService.this.requestInstantAppResolutionPhaseTwo( - responseObj, origIntent, resolvedType, callingPackage, userId); + responseObj, origIntent, resolvedType, callingPackage, verificationBundle, + userId); } @Override @@ -23570,6 +23714,13 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); mIsolatedOwners.delete(isolatedUid); } } + + @Override + public int getUidTargetSdkVersion(int uid) { + synchronized (mPackages) { + return getUidTargetSdkVersionLockedLPr(uid); + } + } } @Override diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java index 84381fe20acc..c6667a702f67 100644 --- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java +++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java @@ -74,6 +74,7 @@ public class UserRestrictionsUtils { UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, UserManager.DISALLOW_CONFIG_BLUETOOTH, UserManager.DISALLOW_BLUETOOTH, + UserManager.DISALLOW_BLUETOOTH_SHARING, UserManager.DISALLOW_USB_FILE_TRANSFER, UserManager.DISALLOW_CONFIG_CREDENTIALS, UserManager.DISALLOW_REMOVE_USER, @@ -155,6 +156,7 @@ public class UserRestrictionsUtils { */ private static final Set<String> GLOBAL_RESTRICTIONS = Sets.newArraySet( UserManager.DISALLOW_ADJUST_VOLUME, + UserManager.DISALLOW_BLUETOOTH_SHARING, UserManager.DISALLOW_RUN_IN_BACKGROUND, UserManager.DISALLOW_UNMUTE_MICROPHONE, UserManager.DISALLOW_UNMUTE_DEVICE @@ -167,6 +169,17 @@ public class UserRestrictionsUtils { UserManager.DISALLOW_ADD_MANAGED_PROFILE ); + /** + * User restrictions that default to {@code true} for managed profile owners. + * + * NB: {@link UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES} is also set by default but it is + * not set to existing profile owners unless they used to have INSTALL_NON_MARKET_APPS disabled + * in settings. So it is handled separately. + */ + private static final Set<String> DEFAULT_ENABLED_FOR_MANAGED_PROFILES = Sets.newArraySet( + UserManager.DISALLOW_BLUETOOTH_SHARING + ); + /* * Special user restrictions that are always applied to all users no matter who sets them. */ @@ -308,6 +321,13 @@ public class UserRestrictionsUtils { } /** + * Returns the user restrictions that default to {@code true} for managed profile owners. + */ + public static @NonNull Set<String> getDefaultEnabledForManagedProfiles() { + return DEFAULT_ENABLED_FOR_MANAGED_PROFILES; + } + + /** * Takes restrictions that can be set by device owner, and sort them into what should be applied * globally and what should be applied only on the current user. */ @@ -544,8 +564,8 @@ public class UserRestrictionsUtils { public static void moveRestriction(String restrictionKey, SparseArray<Bundle> srcRestrictions, SparseArray<Bundle> destRestrictions) { for (int i = 0; i < srcRestrictions.size(); i++) { - int key = srcRestrictions.keyAt(i); - Bundle from = srcRestrictions.valueAt(i); + final int key = srcRestrictions.keyAt(i); + final Bundle from = srcRestrictions.valueAt(i); if (contains(from, restrictionKey)) { from.remove(restrictionKey); Bundle to = destRestrictions.get(key); @@ -562,4 +582,24 @@ public class UserRestrictionsUtils { } } } + + /** + * Returns whether restrictions differ between two bundles. + * @param oldRestrictions old bundle of restrictions. + * @param newRestrictions new bundle of restrictions + * @param restrictions restrictions of interest, if empty, all restrictions are checked. + */ + public static boolean restrictionsChanged(Bundle oldRestrictions, Bundle newRestrictions, + String... restrictions) { + if (restrictions.length == 0) { + return areEqual(oldRestrictions, newRestrictions); + } + for (final String restriction : restrictions) { + if (oldRestrictions.getBoolean(restriction, false) != + newRestrictions.getBoolean(restriction, false)) { + return true; + } + } + return false; + } } diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 3c2dfa51d8f6..36418bea1940 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -893,6 +893,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree if (mPendingRelaunchCount > 0) { mPendingRelaunchCount--; } + updateAllDrawn(); } void clearRelaunching() { @@ -1301,16 +1302,20 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } } - void updateAllDrawn(DisplayContent dc) { + void updateAllDrawn() { if (!allDrawn) { + // Number of drawn windows can be less when a window is being relaunched, wait for + // all windows to be launched and drawn for this token be considered all drawn final int numInteresting = mNumInterestingWindows; - if (numInteresting > 0 && mNumDrawnWindows >= numInteresting) { + if (numInteresting > 0 && mNumDrawnWindows >= numInteresting && !isRelaunching()) { if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows); allDrawn = true; // Force an additional layout pass where // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked(). - dc.setLayoutNeeded(); + if (mDisplayContent != null) { + mDisplayContent.setLayoutNeeded(); + } mService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget(); final TaskStack s = getStack(); @@ -1327,7 +1332,9 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindowsExcludingSaved); allDrawnExcludingSaved = true; - dc.setLayoutNeeded(); + if (mDisplayContent != null) { + mDisplayContent.setLayoutNeeded(); + } if (isAnimatingInvisibleWithSavedSurface() && !mService.mFinishedEarlyAnim.contains(this)) { mService.mFinishedEarlyAnim.add(this); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index d85552a4d140..05b95e2659b2 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -2730,7 +2730,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo final AppWindowToken atoken = mTmpUpdateAllDrawn.removeLast(); // See if any windows have been drawn, so they (and others associated with them) // can now be shown. - atoken.updateAllDrawn(this); + atoken.updateAllDrawn(); } return mTmpApplySurfaceChangesTransactionState.focusDisplayed; diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 2f26f43b78a7..6584672c0948 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -1903,7 +1903,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { setDeviceOwnerSystemPropertyLocked(); findOwnerComponentIfNecessaryLocked(); migrateUserRestrictionsIfNecessaryLocked(); - setDefaultEnabledUserRestrictionsIfNecessaryLocked(); + maybeSetDefaultDeviceOwnerUserRestrictionsLocked(); // TODO PO may not have a class name either due to b/17652534. Address that too. @@ -1911,33 +1911,77 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - private void setDefaultEnabledUserRestrictionsIfNecessaryLocked() { + /** Apply default restrictions that haven't been applied to device owners yet. */ + private void maybeSetDefaultDeviceOwnerUserRestrictionsLocked() { final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); - if (deviceOwner != null - && !UserRestrictionsUtils.getDefaultEnabledForDeviceOwner().equals( - deviceOwner.defaultEnabledRestrictionsAlreadySet)) { - Slog.i(LOG_TAG,"New user restrictions need to be set by default for the device owner"); + if (deviceOwner != null) { + maybeSetDefaultRestrictionsForAdminLocked(mOwners.getDeviceOwnerUserId(), + deviceOwner, UserRestrictionsUtils.getDefaultEnabledForDeviceOwner()); + } + } - if (VERBOSE_LOG) { - Slog.d(LOG_TAG,"Default enabled restrictions for DO: " - + UserRestrictionsUtils.getDefaultEnabledForDeviceOwner() - + ". Restrictions already enabled: " - + deviceOwner.defaultEnabledRestrictionsAlreadySet); + /** Apply default restrictions that haven't been applied to profile owners yet. */ + private void maybeSetDefaultProfileOwnerUserRestrictions() { + synchronized (this) { + for (final int userId : mOwners.getProfileOwnerKeys()) { + final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId); + // The following restrictions used to be applied to managed profiles by different + // means (via Settings or by disabling components). Now they are proper user + // restrictions so we apply them to managed profile owners. Non-managed secondary + // users didn't have those restrictions so we skip them to keep existing behavior. + if (profileOwner == null || !mUserManager.isManagedProfile(userId)) { + continue; + } + maybeSetDefaultRestrictionsForAdminLocked(userId, profileOwner, + UserRestrictionsUtils.getDefaultEnabledForManagedProfiles()); + ensureUnknownSourcesRestrictionForProfileOwnerLocked( + userId, profileOwner, false /* newOwner */); } + } + } - Set<String> restrictionsToSet = new ArraySet<>( - UserRestrictionsUtils.getDefaultEnabledForDeviceOwner()); - restrictionsToSet.removeAll(deviceOwner.defaultEnabledRestrictionsAlreadySet); - if (!restrictionsToSet.isEmpty()) { - for (String restriction : restrictionsToSet) { - deviceOwner.ensureUserRestrictions().putBoolean(restriction, true); - } - deviceOwner.defaultEnabledRestrictionsAlreadySet.addAll(restrictionsToSet); - Slog.i(LOG_TAG, - "Enabled the following restrictions by default: " + restrictionsToSet); + /** + * Checks whether {@link UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES} should be added to the + * set of restrictions for this profile owner. + */ + private void ensureUnknownSourcesRestrictionForProfileOwnerLocked(int userId, + ActiveAdmin profileOwner, boolean newOwner) { + if (newOwner || mInjector.settingsSecureGetIntForUser( + Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, 0, userId) != 0) { + profileOwner.ensureUserRestrictions().putBoolean( + UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true); + saveUserRestrictionsLocked(userId); + mInjector.settingsSecurePutIntForUser( + Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, 0, userId); + } + } + + /** + * Apply default restrictions that haven't been applied to a given admin yet. + */ + private void maybeSetDefaultRestrictionsForAdminLocked( + int userId, ActiveAdmin admin, Set<String> defaultRestrictions) { + if (defaultRestrictions.equals(admin.defaultEnabledRestrictionsAlreadySet)) { + return; // The same set of default restrictions has been already applied. + } + Slog.i(LOG_TAG, "New user restrictions need to be set by default for user " + userId); - saveUserRestrictionsLocked(mOwners.getDeviceOwnerUserId()); + if (VERBOSE_LOG) { + Slog.d(LOG_TAG,"Default enabled restrictions: " + + defaultRestrictions + + ". Restrictions already enabled: " + + admin.defaultEnabledRestrictionsAlreadySet); + } + + final Set<String> restrictionsToSet = new ArraySet<>(defaultRestrictions); + restrictionsToSet.removeAll(admin.defaultEnabledRestrictionsAlreadySet); + if (!restrictionsToSet.isEmpty()) { + for (final String restriction : restrictionsToSet) { + admin.ensureUserRestrictions().putBoolean(restriction, true); } + admin.defaultEnabledRestrictionsAlreadySet.addAll(restrictionsToSet); + Slog.i(LOG_TAG, "Enabled the following restrictions by default: " + restrictionsToSet); + saveUserRestrictionsLocked(userId); } } @@ -2927,41 +2971,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - private void ensureUnknownSourcesRestrictionForProfileOwners() { - synchronized (this) { - for (int userId : mOwners.getProfileOwnerKeys()) { - if (!mUserManager.isManagedProfile(userId) || - mInjector.settingsSecureGetIntForUser( - Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, 0, userId) == 0) { - continue; - } - setUserRestrictionOnBehalfOfProfileOwnerLocked( - UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, userId); - mInjector.settingsSecurePutIntForUser( - Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, 0, userId); - } - } - } - - private void setUserRestrictionOnBehalfOfProfileOwnerLocked(String userRestrictionKey, - int userId) { - if (UserRestrictionsUtils.isValidRestriction(userRestrictionKey) && - UserRestrictionsUtils.canProfileOwnerChange(userRestrictionKey, userId)) { - ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId); - if (profileOwner == null) { - return; - } - Bundle restrictions = profileOwner.ensureUserRestrictions(); - restrictions.putBoolean(userRestrictionKey, true); - saveUserRestrictionsLocked(userId); - } - } - private void onLockSettingsReady() { getUserData(UserHandle.USER_SYSTEM); loadOwners(); cleanUpOldUsers(); - ensureUnknownSourcesRestrictionForProfileOwners(); + maybeSetDefaultProfileOwnerUserRestrictions(); handleStartUser(UserHandle.USER_SYSTEM); // Register an observer for watching for user setup complete and settings changes. @@ -4637,19 +4651,20 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { final long ident = mInjector.binderClearCallingIdentity(); try { // Evict key - if ((flags & DevicePolicyManager.FLAG_EVICT_CE_KEY) != 0) { - enforceManagedProfile(callingUserId, "set FLAG_EVICT_CE_KEY"); + if ((flags & DevicePolicyManager.FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY) != 0) { + enforceManagedProfile( + callingUserId, "set FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY"); if (!isProfileOwner(admin.info.getComponent(), callingUserId)) { - throw new SecurityException( - "Only profile owner admins can set FLAG_EVICT_CE_KEY"); + throw new SecurityException("Only profile owner admins can set " + + "FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY"); } if (parent) { throw new IllegalArgumentException( - "Cannot set FLAG_EVICT_CE_KEY for the parent"); + "Cannot set FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY for the parent"); } if (!mInjector.storageManagerIsFileBasedEncryptionEnabled()) { throw new UnsupportedOperationException( - "FLAG_EVICT_CE_KEY only applies to FBE devices"); + "FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY only applies to FBE devices"); } mUserManager.evictCredentialEncryptionKey(callingUserId); } @@ -6713,8 +6728,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { synchronized (this) { enforceCanSetProfileOwnerLocked(who, userHandle, hasIncompatibleAccountsOrNonAdb); - if (getActiveAdminUncheckedLocked(who, userHandle) == null - || getUserData(userHandle).mRemovingAdmins.contains(who)) { + final ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); + if (admin == null || getUserData(userHandle).mRemovingAdmins.contains(who)) { throw new IllegalArgumentException("Not active admin: " + who); } @@ -6730,10 +6745,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { final long id = mInjector.binderClearCallingIdentity(); try { if (mUserManager.isManagedProfile(userHandle)) { - setUserRestrictionOnBehalfOfProfileOwnerLocked( - UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, userHandle); - mInjector.settingsSecurePutIntForUser( - Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, 0, userHandle); + maybeSetDefaultRestrictionsForAdminLocked(userHandle, admin, + UserRestrictionsUtils.getDefaultEnabledForManagedProfiles()); + ensureUnknownSourcesRestrictionForProfileOwnerLocked(userHandle, admin, + true /* newOwner */); } } finally { mInjector.binderRestoreCallingIdentity(id); diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java index d402d10bc2e1..f41a99f91d3b 100644 --- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -24,6 +24,7 @@ import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.fail; import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.any; @@ -96,6 +97,7 @@ public class NotificationManagerServiceTest { private NotificationManagerService.NotificationListeners mNotificationListeners; private ManagedServices.ManagedServiceInfo mListener; @Mock private ICompanionDeviceManager mCompanionMgr; + @Mock SnoozeHelper mSnoozeHelper; // Use a Testable subclass so we can simulate calls from the system without failing. private static class TestableNotificationManagerService extends NotificationManagerService { @@ -133,7 +135,8 @@ public class NotificationManagerServiceTest { null, new ComponentName(PKG, "test_class"), uid, true, null, 0); when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener); mNotificationManagerService.init(mTestableLooper.getLooper(), mPackageManager, - mPackageManagerClient, mockLightsManager, mNotificationListeners, mCompanionMgr); + mPackageManagerClient, mockLightsManager, mNotificationListeners, mCompanionMgr, + mSnoozeHelper); // Tests call directly into the Binder. mBinderService = mNotificationManagerService.getBinderService(); @@ -147,6 +150,18 @@ public class NotificationManagerServiceTest { mTestableLooper.processAllMessages(); } + private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id, + String groupKey, boolean isSummary) { + Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) + .setContentTitle("foo") + .setSmallIcon(android.R.drawable.sym_def_app_icon) + .setGroup(groupKey) + .setGroupSummary(isSummary); + + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", uid, 0, + nb.build(), new UserHandle(uid), null, 0); + return new NotificationRecord(mContext, sbn, channel); + } private NotificationRecord generateNotificationRecord(NotificationChannel channel) { return generateNotificationRecord(channel, null); } @@ -396,6 +411,46 @@ public class NotificationManagerServiceTest { } @Test + public void testFindGroupNotificationsLocked() throws Exception { + // make sure the same notification can be found in both lists and returned + final NotificationRecord group1 = generateNotificationRecord( + mTestNotificationChannel, 1, "group1", true); + mNotificationManagerService.addEnqueuedNotification(group1); + mNotificationManagerService.addNotification(group1); + + // should not be returned + final NotificationRecord group2 = generateNotificationRecord( + mTestNotificationChannel, 2, "group2", true); + mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null, + group2.sbn.getId(), group2.sbn.getNotification(), group2.sbn.getUserId()); + waitForIdle(); + + // should not be returned + final NotificationRecord nonGroup = generateNotificationRecord( + mTestNotificationChannel, 3, null, false); + mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null, + nonGroup.sbn.getId(), nonGroup.sbn.getNotification(), nonGroup.sbn.getUserId()); + waitForIdle(); + + // same group, child, should be returned + final NotificationRecord group1Child = generateNotificationRecord( + mTestNotificationChannel, 4, "group1", false); + mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null, group1Child.sbn.getId(), + group1Child.sbn.getNotification(), group1Child.sbn.getUserId()); + waitForIdle(); + + List<NotificationRecord> inGroup1 = + mNotificationManagerService.findGroupNotificationsLocked(PKG, group1.getGroupKey(), + group1.sbn.getUserId()); + assertEquals(3, inGroup1.size()); + for (NotificationRecord record : inGroup1) { + assertTrue(record.getGroupKey().equals(group1.getGroupKey())); + assertTrue(record.sbn.getId() == 1 || record.sbn.getId() == 4); + } + } + + + @Test public void testTvExtenderChannelOverride_onTv() throws Exception { mNotificationManagerService.setIsTelevision(true); mNotificationManagerService.setRankingHelper(mRankingHelper); @@ -701,4 +756,134 @@ public class NotificationManagerServiceTest { assertFalse(mNotificationManagerService.hasCompanionDevice(mListener)); } + @Test + public void testSnoozeRunnable_snoozeNonGrouped() throws Exception { + final NotificationRecord nonGrouped = generateNotificationRecord( + mTestNotificationChannel, 1, null, false); + final NotificationRecord grouped = generateNotificationRecord( + mTestNotificationChannel, 2, "group", false); + mNotificationManagerService.addNotification(grouped); + mNotificationManagerService.addNotification(nonGrouped); + + NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = + mNotificationManagerService.new SnoozeNotificationRunnable( + nonGrouped.getKey(), 100, null); + snoozeNotificationRunnable.run(); + + // only snooze the one notification + verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); + } + + @Test + public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception { + final NotificationRecord parent = generateNotificationRecord( + mTestNotificationChannel, 1, "group", true); + final NotificationRecord child = generateNotificationRecord( + mTestNotificationChannel, 2, "group", false); + final NotificationRecord child2 = generateNotificationRecord( + mTestNotificationChannel, 3, "group", false); + mNotificationManagerService.addNotification(parent); + mNotificationManagerService.addNotification(child); + mNotificationManagerService.addNotification(child2); + + NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = + mNotificationManagerService.new SnoozeNotificationRunnable( + parent.getKey(), 100, null); + snoozeNotificationRunnable.run(); + + // snooze parent and children + verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong()); + } + + @Test + public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception { + final NotificationRecord parent = generateNotificationRecord( + mTestNotificationChannel, 1, "group", true); + final NotificationRecord child = generateNotificationRecord( + mTestNotificationChannel, 2, "group", false); + final NotificationRecord child2 = generateNotificationRecord( + mTestNotificationChannel, 3, "group", false); + mNotificationManagerService.addNotification(parent); + mNotificationManagerService.addNotification(child); + mNotificationManagerService.addNotification(child2); + + NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = + mNotificationManagerService.new SnoozeNotificationRunnable( + child2.getKey(), 100, null); + snoozeNotificationRunnable.run(); + + // only snooze the one child + verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); + } + + @Test + public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception { + final NotificationRecord parent = generateNotificationRecord( + mTestNotificationChannel, 1, "group", true); + assertTrue(parent.sbn.getNotification().isGroupSummary()); + final NotificationRecord child = generateNotificationRecord( + mTestNotificationChannel, 2, "group", false); + mNotificationManagerService.addNotification(parent); + mNotificationManagerService.addNotification(child); + + NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = + mNotificationManagerService.new SnoozeNotificationRunnable( + child.getKey(), 100, null); + snoozeNotificationRunnable.run(); + + // snooze child and summary + verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong()); + } + + @Test + public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception { + final NotificationRecord child = generateNotificationRecord( + mTestNotificationChannel, 2, "group", false); + mNotificationManagerService.addNotification(child); + + NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable = + mNotificationManagerService.new SnoozeNotificationRunnable( + child.getKey(), 100, null); + snoozeNotificationRunnable.run(); + + // snooze child only + verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong()); + } + + @Test + public void testPostGroupChild_unsnoozeParent() throws Exception { + final NotificationRecord child = generateNotificationRecord( + mTestNotificationChannel, 2, "group", false); + + mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null, + child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId()); + waitForIdle(); + + verify(mSnoozeHelper, times(1)).repostGroupSummary( + anyString(), anyInt(), eq(child.getGroupKey())); + } + + @Test + public void testPostNonGroup_noUnsnoozing() throws Exception { + final NotificationRecord record = generateNotificationRecord( + mTestNotificationChannel, 2, null, false); + + mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null, + record.sbn.getId(), record.sbn.getNotification(), record.sbn.getUserId()); + waitForIdle(); + + verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString()); + } + + @Test + public void testPostGroupSummary_noUnsnoozing() throws Exception { + final NotificationRecord parent = generateNotificationRecord( + mTestNotificationChannel, 2, "group", true); + + mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null, + parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId()); + waitForIdle(); + + verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString()); + } } diff --git a/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java index 9575d3253b28..51ec05c51b07 100644 --- a/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java +++ b/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java @@ -34,6 +34,7 @@ import android.service.notification.StatusBarNotification; import android.support.test.InstrumentationRegistry; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.SmallTest; +import android.util.Slog; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; @@ -232,13 +233,50 @@ public class SnoozeHelperTest { assertEquals(4, mSnoozeHelper.getSnoozed().size()); } + @Test + public void repostGroupSummary_onlyFellowGroupChildren() throws Exception { + NotificationRecord r = getNotificationRecord( + "pkg", 1, "one", UserHandle.SYSTEM, "group1", false); + NotificationRecord r2 = getNotificationRecord( + "pkg", 2, "two", UserHandle.SYSTEM, "group1", false); + mSnoozeHelper.snooze(r, 1000); + mSnoozeHelper.snooze(r2, 1000); + mSnoozeHelper.repostGroupSummary("pkg", UserHandle.USER_SYSTEM, "group1"); + + verify(mCallback, never()).repost(UserHandle.USER_SYSTEM, r); + } + + @Test + public void repostGroupSummary_repostsSummary() throws Exception { + when(mUserProfiles.getCurrentProfileIds()).thenReturn( + new int[] {UserHandle.USER_SYSTEM}); + NotificationRecord r = getNotificationRecord( + "pkg", 1, "one", UserHandle.SYSTEM, "group1", true); + NotificationRecord r2 = getNotificationRecord( + "pkg", 2, "two", UserHandle.SYSTEM, "group1", false); + mSnoozeHelper.snooze(r, 1000); + mSnoozeHelper.snooze(r2, 1000); + assertEquals(2, mSnoozeHelper.getSnoozed().size()); + assertEquals(2, mSnoozeHelper.getSnoozed(UserHandle.USER_SYSTEM, "pkg").size()); + + mSnoozeHelper.repostGroupSummary("pkg", UserHandle.USER_SYSTEM, r.getGroupKey()); + + verify(mCallback, times(1)).repost(UserHandle.USER_SYSTEM, r); + verify(mCallback, never()).repost(UserHandle.USER_SYSTEM, r2); + + assertEquals(1, mSnoozeHelper.getSnoozed().size()); + assertEquals(1, mSnoozeHelper.getSnoozed(UserHandle.USER_SYSTEM, "pkg").size()); + } + private NotificationRecord getNotificationRecord(String pkg, int id, String tag, - UserHandle user) { + UserHandle user, String groupKey, boolean groupSummary) { Notification n = new Notification.Builder(getContext(), TEST_CHANNEL_ID) .setContentTitle("A") .setGroup("G") .setSortKey("A") .setWhen(1205) + .setGroup(groupKey) + .setGroupSummary(groupSummary) .build(); final NotificationChannel notificationChannel = new NotificationChannel( TEST_CHANNEL_ID, "name", NotificationManager.IMPORTANCE_LOW); @@ -246,4 +284,9 @@ public class SnoozeHelperTest { pkg, pkg, id, tag, 0, 0, n, user, null, System.currentTimeMillis()), notificationChannel); } + + private NotificationRecord getNotificationRecord(String pkg, int id, String tag, + UserHandle user) { + return getNotificationRecord(pkg, id, tag, user, null, false); + } } diff --git a/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/profile_device_policies.xml b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/profile_device_policies.xml new file mode 100644 index 000000000000..b162785aefef --- /dev/null +++ b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/profile_device_policies.xml @@ -0,0 +1,8 @@ +<?xml version='1.0' encoding='utf-8' standalone='yes' ?> +<policies setup-complete="true" provisioning-state="3"> +<admin name="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin1"> + <policies flags="991" /> + <strong-auth-unlock-timeout value="0" /> + <organization-color value="-16738680" /> +</admin> +</policies> diff --git a/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/profile_owner.xml b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/profile_owner.xml new file mode 100644 index 000000000000..744042413e08 --- /dev/null +++ b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/profile_owner.xml @@ -0,0 +1,8 @@ +<?xml version='1.0' encoding='utf-8' standalone='yes' ?> +<root> + <profile-owner + package="com.android.frameworks.servicestests" + name="com.android.frameworks.servicestests" + component="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin1" + userRestrictionsMigrated="true" /> +</root> diff --git a/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/system_device_policies.xml b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/system_device_policies.xml new file mode 100644 index 000000000000..5f9a87194bf7 --- /dev/null +++ b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/system_device_policies.xml @@ -0,0 +1,3 @@ +<?xml version='1.0' encoding='utf-8' standalone='yes' ?> +<policies setup-complete="true" provisioning-state="3"> +</policies> diff --git a/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java index cf477f2b32ef..f8dfee40698f 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java @@ -131,7 +131,7 @@ public class FingerprintGestureControllerTest { mFingerprintGestureController.registerFingerprintGestureCallback( mMockFingerprintGestureCallback, null); mFingerprintGestureController.onGesture(FINGERPRINT_GESTURE_SWIPE_DOWN); - verify(mMockFingerprintGestureCallback, times(1)).onGesture(FINGERPRINT_GESTURE_SWIPE_DOWN); + verify(mMockFingerprintGestureCallback, times(1)).onGestureDetected(FINGERPRINT_GESTURE_SWIPE_DOWN); reset(mMockFingerprintGestureCallback); mFingerprintGestureController.unregisterFingerprintGestureCallback( @@ -150,9 +150,9 @@ public class FingerprintGestureControllerTest { mFingerprintGestureController.registerFingerprintGestureCallback( mMockFingerprintGestureCallback, messageCapturingHandler); mFingerprintGestureController.onGesture(FINGERPRINT_GESTURE_SWIPE_DOWN); - verify(mMockFingerprintGestureCallback, times(0)).onGesture(FINGERPRINT_GESTURE_SWIPE_DOWN); + verify(mMockFingerprintGestureCallback, times(0)).onGestureDetected(FINGERPRINT_GESTURE_SWIPE_DOWN); messageCapturingHandler.sendLastMessage(); - verify(mMockFingerprintGestureCallback, times(1)).onGesture(FINGERPRINT_GESTURE_SWIPE_DOWN); + verify(mMockFingerprintGestureCallback, times(1)).onGestureDetected(FINGERPRINT_GESTURE_SWIPE_DOWN); reset(mMockFingerprintGestureCallback); mFingerprintGestureController.unregisterFingerprintGestureCallback( diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java index 58166b6c1ac5..c87eaed5c954 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import android.content.ComponentName; +import android.content.pm.ActivityInfo; import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -84,4 +85,16 @@ public class ActivityStackTests extends ActivityTestsBase { // Make sure the resumed activity is untouched. assertEquals(testStack.mResumedActivity, activityRecord); } + + @Test + public void testStopActivityWhenActivityDestroyed() throws Exception { + final ActivityManagerService service = createActivityManagerService(); + final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID); + final ActivityRecord activityRecord = createActivity(service, testActivityComponent, task); + activityRecord.info.flags |= ActivityInfo.FLAG_NO_HISTORY; + final ActivityStack testStack = service.mStackSupervisor.getStack(TEST_STACK_ID); + service.mStackSupervisor.setFocusStackUnchecked("testStopActivityWithDestroy", testStack); + + testStack.stopActivityLocked(activityRecord); + } } diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java index 082708442032..3fc2c1246c59 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java @@ -161,6 +161,11 @@ public class ActivityTestsBase { void moveHomeStackToFront(String reason) { } + @Override + boolean moveHomeStackTaskToTop(String reason) { + return true; + } + // Invoked during {@link ActivityStack} creation. @Override void updateUIDsPresentOnDisplay() { diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java index b440095e60cc..be1d07bbec0b 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java @@ -15,31 +15,28 @@ */ package com.android.server.devicepolicy; -import com.android.server.LocalServices; -import com.android.server.SystemService; -import com.android.server.devicepolicy.DevicePolicyManagerServiceTestable.OwnersTestable; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.when; -import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.os.Bundle; import android.os.UserHandle; import android.os.UserManager; -import android.util.Pair; +import android.provider.Settings; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; +import com.android.server.LocalServices; +import com.android.server.SystemService; +import com.android.server.devicepolicy.DevicePolicyManagerServiceTestable.OwnersTestable; import java.io.File; import java.util.HashMap; import java.util.Map; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.when; +import java.util.Set; public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { private DpmMockContext mContext; @@ -57,7 +54,7 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { public void testMigration() throws Exception { final File user10dir = mMockContext.addUser(10, 0); final File user11dir = mMockContext.addUser(11, UserInfo.FLAG_MANAGED_PROFILE); - final File user12dir = mMockContext.addUser(12, 0); + mMockContext.addUser(12, 0); setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID); setUpPackageManagerForAdmin(admin2, UserHandle.getUid(10, 123)); @@ -109,16 +106,13 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { final Map<Integer, Bundle> newBaseRestrictions = new HashMap<>(); - doAnswer(new Answer<Void>() { - @Override - public Void answer(InvocationOnMock invocation) throws Throwable { - Integer userId = (Integer) invocation.getArguments()[0]; - Bundle bundle = (Bundle) invocation.getArguments()[1]; + doAnswer(invocation -> { + Integer userId = (Integer) invocation.getArguments()[0]; + Bundle bundle = (Bundle) invocation.getArguments()[1]; - newBaseRestrictions.put(userId, bundle); + newBaseRestrictions.put(userId, bundle); - return null; - } + return null; }).when(mContext.userManagerInternal).setBaseUserRestrictionsByDpmsForMigration( anyInt(), any(Bundle.class)); @@ -225,16 +219,13 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { final Map<Integer, Bundle> newBaseRestrictions = new HashMap<>(); - doAnswer(new Answer<Void>() { - @Override - public Void answer(InvocationOnMock invocation) throws Throwable { - Integer userId = (Integer) invocation.getArguments()[0]; - Bundle bundle = (Bundle) invocation.getArguments()[1]; + doAnswer(invocation -> { + Integer userId = (Integer) invocation.getArguments()[0]; + Bundle bundle = (Bundle) invocation.getArguments()[1]; - newBaseRestrictions.put(userId, bundle); + newBaseRestrictions.put(userId, bundle); - return null; - } + return null; }).when(mContext.userManagerInternal).setBaseUserRestrictionsByDpmsForMigration( anyInt(), any(Bundle.class)); @@ -278,4 +269,63 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { ), dpms.getProfileOwnerAdminLocked(UserHandle.USER_SYSTEM).ensureUserRestrictions()); } + + // Test setting default restrictions for managed profile. + public void testMigration3_managedProfileOwner() throws Exception { + // Create a managed profile user. + final File user10dir = mMockContext.addUser(10, UserInfo.FLAG_MANAGED_PROFILE); + // Profile owner package for managed profile user. + setUpPackageManagerForAdmin(admin1, UserHandle.getUid(10, 123)); + // Set up fake UserManager to make it look like a managed profile. + when(mMockContext.userManager.isManagedProfile(eq(10))).thenReturn(true); + // Set up fake Settings to make it look like INSTALL_NON_MARKET_APPS was reversed. + when(mMockContext.settings.settingsSecureGetIntForUser( + eq(Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED), + eq(0), eq(10))).thenReturn(1); + // Write policy and owners files. + DpmTestUtils.writeToFile( + (new File(mContext.systemUserDataDir, "device_policies.xml")).getAbsoluteFile(), + DpmTestUtils.readAsset(mRealTestContext, + "DevicePolicyManagerServiceMigrationTest3/system_device_policies.xml")); + DpmTestUtils.writeToFile( + (new File(user10dir, "device_policies.xml")).getAbsoluteFile(), + DpmTestUtils.readAsset(mRealTestContext, + "DevicePolicyManagerServiceMigrationTest3/profile_device_policies.xml")); + DpmTestUtils.writeToFile( + (new File(user10dir, "profile_owner.xml")).getAbsoluteFile(), + DpmTestUtils.readAsset(mRealTestContext, + "DevicePolicyManagerServiceMigrationTest3/profile_owner.xml")); + + final DevicePolicyManagerServiceTestable dpms; + + // Initialize DPM/DPMS and let it migrate the persisted information. + // (Need clearCallingIdentity() to pass permission checks.) + final long ident = mContext.binder.clearCallingIdentity(); + try { + LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); + + dpms = new DevicePolicyManagerServiceTestable(mContext, dataDir); + + dpms.systemReady(SystemService.PHASE_LOCK_SETTINGS_READY); + dpms.systemReady(SystemService.PHASE_BOOT_COMPLETED); + } finally { + mContext.binder.restoreCallingIdentity(ident); + } + + assertFalse(dpms.mOwners.hasDeviceOwner()); + assertTrue(dpms.mOwners.hasProfileOwner(10)); + + // Check that default restrictions were applied. + DpmTestUtils.assertRestrictions( + DpmTestUtils.newRestrictions( + UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, + UserManager.DISALLOW_BLUETOOTH_SHARING + ), + dpms.getProfileOwnerAdminLocked(10).ensureUserRestrictions()); + + final Set<String> alreadySet = + dpms.getProfileOwnerAdminLocked(10).defaultEnabledRestrictionsAlreadySet; + assertEquals(alreadySet.size(), 1); + assertTrue(alreadySet.contains(UserManager.DISALLOW_BLUETOOTH_SHARING)); + } } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java index a6ce1d51f80e..46da3dedc77e 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java @@ -21,7 +21,6 @@ import android.app.PendingIntent; import android.app.backup.IBackupManager; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.pm.IPackageManager; import android.content.pm.PackageManagerInternal; import android.database.ContentObserver; @@ -56,17 +55,17 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi public static class OwnersTestable extends Owners { public static final String LEGACY_FILE = "legacy.xml"; public static final String DEVICE_OWNER_FILE = "device_owner2.xml"; - public static final String PROFILE_OWNER_FILE_BASE = "profile_owner.xml"; + public static final String PROFILE_OWNER_FILE = "profile_owner.xml"; private final File mLegacyFile; private final File mDeviceOwnerFile; - private final File mProfileOwnerBase; + private final File mUsersDataDir; public OwnersTestable(DpmMockContext context) { super(context.userManager, context.userManagerInternal, context.packageManagerInternal); mLegacyFile = new File(context.dataDir, LEGACY_FILE); mDeviceOwnerFile = new File(context.dataDir, DEVICE_OWNER_FILE); - mProfileOwnerBase = new File(context.dataDir, PROFILE_OWNER_FILE_BASE); + mUsersDataDir = new File(context.dataDir, "users"); } @Override @@ -81,7 +80,8 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi @Override File getProfileOwnerFileWithTestOverride(int userId) { - return new File(mDeviceOwnerFile.getAbsoluteFile() + "-" + userId); + final File userDir = new File(mUsersDataDir, String.valueOf(userId)); + return new File(userDir, PROFILE_OWNER_FILE); } } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java index 1ea12d853556..23fada46d16e 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java @@ -468,7 +468,7 @@ public class DpmMockContext extends MockContext { when(accountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]); // Create a data directory. - final File dir = new File(dataDir, "user" + userId); + final File dir = new File(dataDir, "users/" + userId); DpmTestUtils.clearDir(dir); when(environment.getUserSystemDirectory(eq(userId))).thenReturn(dir); diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java index 315d37cbd662..db317a0e4cca 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java @@ -35,7 +35,7 @@ public class NetworkEventTest extends DpmTestBase { p.setDataPosition(0); ConnectEvent unparceledEvent = p.readParcelable(NetworkEventTest.class.getClassLoader()); p.recycle(); - assertEquals(event.getIpAddress(), unparceledEvent.getIpAddress()); + assertEquals(event.getInetAddress(), unparceledEvent.getInetAddress()); assertEquals(event.getPort(), unparceledEvent.getPort()); assertEquals(event.getPackageName(), unparceledEvent.getPackageName()); assertEquals(event.getTimestamp(), unparceledEvent.getTimestamp()); @@ -53,9 +53,10 @@ public class NetworkEventTest extends DpmTestBase { DnsEvent unparceledEvent = p.readParcelable(NetworkEventTest.class.getClassLoader()); p.recycle(); assertEquals(event.getHostname(), unparceledEvent.getHostname()); - assertEquals(event.getIpAddresses()[0], unparceledEvent.getIpAddresses()[0]); - assertEquals(event.getIpAddresses()[1], unparceledEvent.getIpAddresses()[1]); - assertEquals(event.getIpAddressesCount(), unparceledEvent.getIpAddressesCount()); + assertEquals(event.getInetAddresses().get(0), unparceledEvent.getInetAddresses().get(0)); + assertEquals(event.getInetAddresses().get(1), unparceledEvent.getInetAddresses().get(1)); + assertEquals(event.getTotalResolvedAddressCount(), + unparceledEvent.getTotalResolvedAddressCount()); assertEquals(event.getPackageName(), unparceledEvent.getPackageName()); assertEquals(event.getTimestamp(), unparceledEvent.getTimestamp()); } diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java index d8db3315d423..1284b1b5bf24 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java @@ -15,7 +15,6 @@ */ package com.android.server.pm; -import android.annotation.TestApi; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ConfigurationInfo; @@ -338,7 +337,7 @@ public class PackageParserTest { // Sanity check for InstrumentationInfo. assertEquals(a.info.targetPackage, b.info.targetPackage); - assertEquals(a.info.targetProcess, b.info.targetProcess); + assertEquals(a.info.targetProcesses, b.info.targetProcesses); assertEquals(a.info.sourceDir, b.info.sourceDir); assertEquals(a.info.publicSourceDir, b.info.publicSourceDir); } diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java index 2ebf5fc1c533..e13665bed275 100644 --- a/services/usage/java/com/android/server/usage/StorageStatsService.java +++ b/services/usage/java/com/android/server/usage/StorageStatsService.java @@ -157,7 +157,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub { @Override public long getTotalBytes(String volumeUuid, String callingPackage) { - enforcePermission(Binder.getCallingUid(), callingPackage); + // NOTE: No permissions required if (volumeUuid == StorageManager.UUID_PRIVATE_INTERNAL) { return FileUtils.roundStorageSize(mStorage.getPrimaryStorageSize()); @@ -173,7 +173,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub { @Override public long getFreeBytes(String volumeUuid, String callingPackage) { - enforcePermission(Binder.getCallingUid(), callingPackage); + // NOTE: No permissions required long cacheBytes = 0; final long token = Binder.clearCallingIdentity(); @@ -187,14 +187,14 @@ public class StorageStatsService extends IStorageStatsManager.Stub { } if (volumeUuid == StorageManager.UUID_PRIVATE_INTERNAL) { - return Environment.getDataDirectory().getUsableSpace() + cacheBytes; + return Environment.getDataDirectory().getFreeSpace() + cacheBytes; } else { final VolumeInfo vol = mStorage.findVolumeByUuid(volumeUuid); if (vol == null) { throw new ParcelableException( new IOException("Failed to find storage device for UUID " + volumeUuid)); } - return vol.getPath().getUsableSpace() + cacheBytes; + return vol.getPath().getFreeSpace() + cacheBytes; } } @@ -213,7 +213,6 @@ public class StorageStatsService extends IStorageStatsManager.Stub { @Override public StorageStats queryStatsForPackage(String volumeUuid, String packageName, int userId, String callingPackage) { - enforcePermission(Binder.getCallingUid(), callingPackage); if (userId != UserHandle.getCallingUserId()) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS, TAG); @@ -227,6 +226,12 @@ public class StorageStatsService extends IStorageStatsManager.Stub { throw new ParcelableException(e); } + if (Binder.getCallingUid() == appInfo.uid) { + // No permissions required when asking about themselves + } else { + enforcePermission(Binder.getCallingUid(), callingPackage); + } + if (mPackage.getPackagesForUid(appInfo.uid).length == 1) { // Only one package inside UID means we can fast-path return queryStatsForUid(volumeUuid, appInfo.uid, callingPackage); @@ -257,14 +262,19 @@ public class StorageStatsService extends IStorageStatsManager.Stub { @Override public StorageStats queryStatsForUid(String volumeUuid, int uid, String callingPackage) { - enforcePermission(Binder.getCallingUid(), callingPackage); - if (UserHandle.getUserId(uid) != UserHandle.getCallingUserId()) { + final int userId = UserHandle.getUserId(uid); + final int appId = UserHandle.getAppId(uid); + + if (userId != UserHandle.getCallingUserId()) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS, TAG); } - final int userId = UserHandle.getUserId(uid); - final int appId = UserHandle.getAppId(uid); + if (Binder.getCallingUid() == uid) { + // No permissions required when asking about themselves + } else { + enforcePermission(Binder.getCallingUid(), callingPackage); + } final String[] packageNames = mPackage.getPackagesForUid(uid); final long[] ceDataInodes = new long[packageNames.length]; @@ -304,12 +314,14 @@ public class StorageStatsService extends IStorageStatsManager.Stub { @Override public StorageStats queryStatsForUser(String volumeUuid, int userId, String callingPackage) { - enforcePermission(Binder.getCallingUid(), callingPackage); if (userId != UserHandle.getCallingUserId()) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS, TAG); } + // Always require permission to see user-level stats + enforcePermission(Binder.getCallingUid(), callingPackage); + final int[] appIds = getAppIds(userId); final PackageStats stats = new PackageStats(TAG); try { @@ -329,12 +341,14 @@ public class StorageStatsService extends IStorageStatsManager.Stub { @Override public ExternalStorageStats queryExternalStatsForUser(String volumeUuid, int userId, String callingPackage) { - enforcePermission(Binder.getCallingUid(), callingPackage); if (userId != UserHandle.getCallingUserId()) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS, TAG); } + // Always require permission to see user-level stats + enforcePermission(Binder.getCallingUid(), callingPackage); + final int[] appIds = getAppIds(userId); final long[] stats; try { diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index 6c4ced4326a2..4ffacfd7056a 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -1203,6 +1203,50 @@ public class VoiceInteractionManagerService extends SystemService { } @Override + public void onPackageModified(String pkgName) { + // If the package modified is not in the current user, then don't bother making + // any changes as we are going to do any initialization needed when we switch users. + if (mCurUser != getChangingUserId()) { + return; + } + // Package getting updated will be handled by {@link #onSomePackagesChanged}. + if (isPackageAppearing(pkgName) != PACKAGE_UNCHANGED) { + return; + } + final ComponentName curInteractor = getCurInteractor(mCurUser); + if (curInteractor == null) { + final VoiceInteractionServiceInfo availInteractorInfo + = findAvailInteractor(mCurUser, pkgName); + if (availInteractorInfo != null) { + final ComponentName availInteractor = new ComponentName( + availInteractorInfo.getServiceInfo().packageName, + availInteractorInfo.getServiceInfo().name); + setCurInteractor(availInteractor, mCurUser); + if (getCurRecognizer(mCurUser) == null && + availInteractorInfo.getRecognitionService() != null) { + setCurRecognizer(new ComponentName( + availInteractorInfo.getServiceInfo().packageName, + availInteractorInfo.getRecognitionService()), mCurUser); + } + } + } else { + if (didSomePackagesChange()) { + // Package is changed + if (curInteractor != null && pkgName.equals( + curInteractor.getPackageName())) { + switchImplementationIfNeeded(true); + } + } else { + // Only some components are changed + if (curInteractor != null + && isComponentModified(curInteractor.getClassName())) { + switchImplementationIfNeeded(true); + } + } + } + } + + @Override public void onSomePackagesChanged() { int userHandle = getChangingUserId(); if (DEBUG) Slog.d(TAG, "onSomePackagesChanged user=" + userHandle); diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 0b4a3e8cac90..7174a70dd01b 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -993,6 +993,20 @@ public class CarrierConfigManager { "carrier_default_actions_on_dcfailure_string_array"; /** + * Defines carrier-specific actions which act upon + * com.android.internal.telephony.CARRIER_SIGNAL_RESET, used for customization of the + * default carrier app + * Format: "CARRIER_ACTION_IDX, ..." + * Where {@code CARRIER_ACTION_IDX} is an integer defined in + * {@link com.android.carrierdefaultapp.CarrierActionUtils CarrierActionUtils} + * Example: + * {@link com.android.carrierdefaultapp.CarrierActionUtils + * #CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS clear all notifications on reset} + * @hide + */ + public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_RESET = + "carrier_default_actions_on_reset_string_array"; + /** * Defines a list of acceptable redirection url for default carrier app * @hides */ @@ -1594,7 +1608,8 @@ public class CarrierConfigManager { sDefaults.putStringArray(KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY, new String[]{ "com.android.carrierdefaultapp/.CarrierDefaultBroadcastReceiver:" + - "com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED" + "com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED," + + "com.android.internal.telephony.CARRIER_SIGNAL_RESET" }); sDefaults.putStringArray(KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY, null); @@ -1606,6 +1621,9 @@ public class CarrierConfigManager { //4: CARRIER_ACTION_DISABLE_METERED_APNS //1: CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION }); + sDefaults.putStringArray(KEY_CARRIER_DEFAULT_ACTIONS_ON_RESET, new String[]{ + "6" //6: CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS + }); sDefaults.putStringArray(KEY_CARRIER_DEFAULT_REDIRECTION_URL_STRING_ARRAY, null); sDefaults.putInt(KEY_MONTHLY_DATA_CYCLE_DAY_INT, DATA_CYCLE_USE_PLATFORM_DEFAULT); diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java index f9875c5859ab..ec9ca1d31eca 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java +++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java @@ -402,7 +402,7 @@ public class TelephonyIntents { * <ul> * <li>apnType</li><dd>A string with the apn type.</dd> * <li>redirectionUrl</li><dd>redirection url string</dd> - * <li>subId</dt><li>Sub Id which associated the data connection failure.</dd> + * <li>subId</li><dd>Sub Id which associated the data connection failure.</dd> * </ul> * <p class="note">This is a protected intent that can only be sent by the system.</p> */ @@ -415,7 +415,7 @@ public class TelephonyIntents { * <ul> * <li>apnType</li><dd>A string with the apn type.</dd> * <li>errorCode</li><dd>A integer with dataFailCause.</dd> - * <li>subId</dt><li>Sub Id which associated the data connection failure.</dd> + * <li>subId</li><dd>Sub Id which associated the data connection failure.</dd> * </ul> * <p class="note">This is a protected intent that can only be sent by the system. </p> */ @@ -432,13 +432,25 @@ public class TelephonyIntents { * IPV4V6)</dd> * <li>pcoId</li><dd>An integer indicating the pco id for the data.</dd> * <li>pcoValue</li><dd>A byte array of pco data read from modem.</dd> - * <li>subId</dt><li>Sub Id which associated the data connection.</dd> + * <li>subId</li><dd>Sub Id which associated the data connection.</dd> * </ul> * <p class="note">This is a protected intent that can only be sent by the system. </p> */ public static final String ACTION_CARRIER_SIGNAL_PCO_VALUE = "com.android.internal.telephony.CARRIER_SIGNAL_PCO_VALUE"; + /** + * <p>Broadcast Action: when framework reset all carrier actions on sim load or absent. + * intended for carrier apps clean up (clear UI e.g.) and only sent to the specified carrier app + * The intent will have the following extra values:</p> + * <ul> + * <li>subId</li><dd>Sub Id which associated the data connection failure.</dd> + * </ul> + * <p class="note">This is a protected intent that can only be sent by the system.</p> + */ + public static final String ACTION_CARRIER_SIGNAL_RESET = + "com.android.internal.telephony.CARRIER_SIGNAL_RESET"; + // CARRIER_SIGNAL_ACTION extra keys public static final String EXTRA_REDIRECTION_URL_KEY = "redirectionUrl"; public static final String EXTRA_ERROR_CODE_KEY = "errorCode"; diff --git a/tests/FeatureSplit/feature1/AndroidManifest.xml b/tests/FeatureSplit/feature1/AndroidManifest.xml index 42619b623e10..b87361faac62 100644 --- a/tests/FeatureSplit/feature1/AndroidManifest.xml +++ b/tests/FeatureSplit/feature1/AndroidManifest.xml @@ -16,7 +16,7 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.test.split.feature" - featureName="feature1"> + featureSplit="feature1"> <uses-sdk android:minSdkVersion="21" /> diff --git a/tests/FeatureSplit/feature1/res/layout/included.xml b/tests/FeatureSplit/feature1/res/layout/included.xml new file mode 100644 index 000000000000..c64bdb7ff85f --- /dev/null +++ b/tests/FeatureSplit/feature1/res/layout/included.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> diff --git a/tests/FeatureSplit/feature1/res/layout/main.xml b/tests/FeatureSplit/feature1/res/layout/main.xml new file mode 100644 index 000000000000..dbea42ab23d0 --- /dev/null +++ b/tests/FeatureSplit/feature1/res/layout/main.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <include layout="@layout/included" + android:layout_width="match_parent" + android:layout_height="match_parent" /> +</FrameLayout> diff --git a/tests/FeatureSplit/feature1/src/com/android/test/split/feature/one/One.java b/tests/FeatureSplit/feature1/src/com/android/test/split/feature/one/One.java index def133919f90..61ac9dfba1cb 100644 --- a/tests/FeatureSplit/feature1/src/com/android/test/split/feature/one/One.java +++ b/tests/FeatureSplit/feature1/src/com/android/test/split/feature/one/One.java @@ -15,17 +15,16 @@ */ package com.android.test.split.feature.one; -import com.android.test.split.feature.ActivityMain; - +import android.app.Activity; import android.widget.TextView; import android.os.Bundle; -public class One extends ActivityMain { +public class One extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - ((TextView) findViewById(com.android.test.split.feature.R.id.text)) - .setText(R.string.feature_string); + setContentView(R.layout.main); + ((TextView) findViewById(R.id.text)).setText(R.string.feature_string); } } diff --git a/tests/FeatureSplit/feature2/AndroidManifest.xml b/tests/FeatureSplit/feature2/AndroidManifest.xml index b50044ac37b7..abd0b5eb6933 100644 --- a/tests/FeatureSplit/feature2/AndroidManifest.xml +++ b/tests/FeatureSplit/feature2/AndroidManifest.xml @@ -16,7 +16,7 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.test.split.feature" - featureName="feature2"> + featureSplit="feature2"> <uses-sdk android:minSdkVersion="21" /> diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java index 47630e28b372..7a1c2395c438 100644 --- a/tests/net/java/com/android/server/connectivity/TetheringTest.java +++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java @@ -223,8 +223,6 @@ public class TetheringTest { @Test public void workingLocalOnlyHotspot() throws Exception { when(mConnectivityManager.isTetheringSupported()).thenReturn(true); - when(mWifiManager.setWifiApEnabled(any(WifiConfiguration.class), anyBoolean())) - .thenReturn(true); // Emulate externally-visible WifiManager effects, causing the // per-interface state machine to start up, and telling us that @@ -238,6 +236,9 @@ public class TetheringTest { verify(mNMService, times(1)).setIpForwardingEnabled(true); verify(mNMService, times(1)).startTethering(any(String[].class)); verifyNoMoreInteractions(mNMService); + verify(mWifiManager).updateInterfaceIpState( + mTestIfname, WifiManager.IFACE_IP_MODE_LOCAL_ONLY); + verifyNoMoreInteractions(mWifiManager); verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY); // UpstreamNetworkMonitor will be started, and will register two callbacks: // a "listen all" and a "track default". @@ -263,6 +264,7 @@ public class TetheringTest { verify(mNMService, times(1)).stopTethering(); verify(mNMService, times(1)).setIpForwardingEnabled(false); verifyNoMoreInteractions(mNMService); + verifyNoMoreInteractions(mWifiManager); // Asking for the last error after the per-interface state machine // has been reaped yields an unknown interface error. assertEquals(ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE, @@ -272,13 +274,12 @@ public class TetheringTest { @Test public void workingWifiTethering() throws Exception { when(mConnectivityManager.isTetheringSupported()).thenReturn(true); - when(mWifiManager.setWifiApEnabled(any(WifiConfiguration.class), anyBoolean())) - .thenReturn(true); + when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true); // Emulate pressing the WiFi tethering button. mTethering.startTethering(ConnectivityManager.TETHERING_WIFI, null, false); mLooper.dispatchAll(); - verify(mWifiManager, times(1)).setWifiApEnabled(null, true); + verify(mWifiManager, times(1)).startSoftAp(null); verifyNoMoreInteractions(mWifiManager); verifyNoMoreInteractions(mConnectivityManager); verifyNoMoreInteractions(mNMService); @@ -295,6 +296,9 @@ public class TetheringTest { verify(mNMService, times(1)).setIpForwardingEnabled(true); verify(mNMService, times(1)).startTethering(any(String[].class)); verifyNoMoreInteractions(mNMService); + verify(mWifiManager).updateInterfaceIpState( + mTestIfname, WifiManager.IFACE_IP_MODE_TETHERED); + verifyNoMoreInteractions(mWifiManager); verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_ACTIVE_TETHER); // UpstreamNetworkMonitor will be started, and will register two callbacks: // a "listen all" and a "track default". @@ -322,7 +326,7 @@ public class TetheringTest { // Emulate pressing the WiFi tethering button. mTethering.stopTethering(ConnectivityManager.TETHERING_WIFI); mLooper.dispatchAll(); - verify(mWifiManager, times(1)).setWifiApEnabled(null, false); + verify(mWifiManager, times(1)).stopSoftAp(); verifyNoMoreInteractions(mWifiManager); verifyNoMoreInteractions(mConnectivityManager); verifyNoMoreInteractions(mNMService); @@ -341,6 +345,7 @@ public class TetheringTest { verify(mNMService, times(1)).stopTethering(); verify(mNMService, times(1)).setIpForwardingEnabled(false); verifyNoMoreInteractions(mNMService); + verifyNoMoreInteractions(mWifiManager); // Asking for the last error after the per-interface state machine // has been reaped yields an unknown interface error. assertEquals(ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE, diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp index 60b01e372d7b..b872ebbeb159 100644 --- a/tools/aapt2/Debug.cpp +++ b/tools/aapt2/Debug.cpp @@ -274,7 +274,13 @@ class XmlPrinter : public xml::Visitor { if (!attr.namespace_uri.empty()) { std::cerr << attr.namespace_uri << ":"; } - std::cerr << attr.name << "=" << attr.value << "\n"; + std::cerr << attr.name; + + if (attr.compiled_attribute) { + std::cerr << "(" << attr.compiled_attribute.value().id.value_or_default(ResourceId(0x0)) + << ")"; + } + std::cerr << "=" << attr.value << "\n"; } const size_t previous_size = prefix_.size(); diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp index 87fda16ee956..1965ad941b2e 100644 --- a/tools/aapt2/Main.cpp +++ b/tools/aapt2/Main.cpp @@ -19,6 +19,8 @@ #include "androidfw/StringPiece.h" +#include "Diagnostics.h" + namespace aapt { // DO NOT UPDATE, this is more of a marketing version. @@ -33,8 +35,8 @@ int PrintVersion() { return 0; } -extern int Compile(const std::vector<android::StringPiece>& args); -extern int Link(const std::vector<android::StringPiece>& args); +extern int Compile(const std::vector<android::StringPiece>& args, IDiagnostics* diagnostics); +extern int Link(const std::vector<android::StringPiece>& args, IDiagnostics* diagnostics); extern int Dump(const std::vector<android::StringPiece>& args); extern int Diff(const std::vector<android::StringPiece>& args); extern int Optimize(const std::vector<android::StringPiece>& args); @@ -53,9 +55,11 @@ int main(int argc, char** argv) { android::StringPiece command(argv[0]); if (command == "compile" || command == "c") { - return aapt::Compile(args); + aapt::StdErrDiagnostics diagnostics; + return aapt::Compile(args, &diagnostics); } else if (command == "link" || command == "l") { - return aapt::Link(args); + aapt::StdErrDiagnostics diagnostics; + return aapt::Link(args, &diagnostics); } else if (command == "dump" || command == "d") { return aapt::Dump(args); } else if (command == "diff") { diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp index b93c6ecea274..5413b336ea90 100644 --- a/tools/aapt2/cmd/Compile.cpp +++ b/tools/aapt2/cmd/Compile.cpp @@ -598,6 +598,9 @@ static bool CompileFile(IAaptContext* context, const CompileOptions& options, class CompileContext : public IAaptContext { public: + CompileContext(IDiagnostics* diagnostics) : diagnostics_(diagnostics) { + } + PackageType GetPackageType() override { // Every compilation unit starts as an app and then gets linked as potentially something else. return PackageType::kApp; @@ -612,7 +615,7 @@ class CompileContext : public IAaptContext { } IDiagnostics* GetDiagnostics() override { - return &diagnostics_; + return diagnostics_; } NameMangler* GetNameMangler() override { @@ -639,7 +642,7 @@ class CompileContext : public IAaptContext { } private: - StdErrDiagnostics diagnostics_; + IDiagnostics* diagnostics_; bool verbose_ = false; }; @@ -647,8 +650,8 @@ class CompileContext : public IAaptContext { * Entry point for compilation phase. Parses arguments and dispatches to the * correct steps. */ -int Compile(const std::vector<StringPiece>& args) { - CompileContext context; +int Compile(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) { + CompileContext context(diagnostics); CompileOptions options; bool verbose = false; diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index 258516db2ac9..93748d358d7a 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -118,7 +118,8 @@ struct LinkOptions { class LinkContext : public IAaptContext { public: - LinkContext() : name_mangler_({}), symbols_(&name_mangler_) { + LinkContext(IDiagnostics* diagnostics) + : diagnostics_(diagnostics), name_mangler_({}), symbols_(&name_mangler_) { } PackageType GetPackageType() override { @@ -130,7 +131,7 @@ class LinkContext : public IAaptContext { } IDiagnostics* GetDiagnostics() override { - return &diagnostics_; + return diagnostics_; } NameMangler* GetNameMangler() override { @@ -181,7 +182,7 @@ class LinkContext : public IAaptContext { DISALLOW_COPY_AND_ASSIGN(LinkContext); PackageType package_type_ = PackageType::kApp; - StdErrDiagnostics diagnostics_; + IDiagnostics* diagnostics_; NameMangler name_mangler_; std::string compilation_package_; uint8_t package_id_ = 0x0; @@ -1736,8 +1737,8 @@ class LinkCommand { std::map<size_t, std::string> shared_libs_; }; -int Link(const std::vector<StringPiece>& args) { - LinkContext context; +int Link(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) { + LinkContext context(diagnostics); LinkOptions options; std::vector<std::string> overlay_arg_list; std::vector<std::string> extra_java_packages; diff --git a/tools/aapt2/flatten/TableFlattener.cpp b/tools/aapt2/flatten/TableFlattener.cpp index d44b3e095c0f..f4d02262f25c 100644 --- a/tools/aapt2/flatten/TableFlattener.cpp +++ b/tools/aapt2/flatten/TableFlattener.cpp @@ -573,10 +573,17 @@ bool TableFlattener::Consume(IAaptContext* context, ResourceTable* table) { // Write the ResTable header. ChunkWriter table_writer(buffer_); - ResTable_header* table_header = - table_writer.StartChunk<ResTable_header>(RES_TABLE_TYPE); + ResTable_header* table_header = table_writer.StartChunk<ResTable_header>(RES_TABLE_TYPE); table_header->packageCount = util::HostToDevice32(table->packages.size()); + // Write a self mapping entry for this package if the ID is non-standard (0x7f). + if (context->GetPackageType() == PackageType::kApp) { + const uint8_t package_id = context->GetPackageId(); + if (package_id != kFrameworkPackageId && package_id != kAppPackageId) { + table->included_packages_[package_id] = context->GetCompilationPackage(); + } + } + // Flatten the values string pool. StringPool::FlattenUtf8(table_writer.buffer(), table->string_pool); diff --git a/tools/aapt2/flatten/TableFlattener_test.cpp b/tools/aapt2/flatten/TableFlattener_test.cpp index 8dff3a27b79f..6d1350d433a4 100644 --- a/tools/aapt2/flatten/TableFlattener_test.cpp +++ b/tools/aapt2/flatten/TableFlattener_test.cpp @@ -400,7 +400,7 @@ TEST_F(TableFlattenerTest, FlattenTableReferencingSharedLibraries) { const DynamicRefTable* dynamic_ref_table = result.getDynamicRefTableForCookie(1); ASSERT_NE(nullptr, dynamic_ref_table); - const KeyedVector<String16, uint8_t> entries = dynamic_ref_table->entries(); + const KeyedVector<String16, uint8_t>& entries = dynamic_ref_table->entries(); ssize_t idx = entries.indexOfKey(android::String16("lib_one")); ASSERT_GE(idx, 0); @@ -411,6 +411,26 @@ TEST_F(TableFlattenerTest, FlattenTableReferencingSharedLibraries) { EXPECT_EQ(0x03u, entries.valueAt(idx)); } +TEST_F(TableFlattenerTest, PackageWithNonStandardIdHasDynamicRefTable) { + std::unique_ptr<IAaptContext> context = + test::ContextBuilder().SetCompilationPackage("app").SetPackageId(0x80).Build(); + std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder() + .SetPackageId("app", 0x80) + .AddSimple("app:id/foo", ResourceId(0x80010000)) + .Build(); + + ResTable result; + ASSERT_TRUE(Flatten(context.get(), {}, table.get(), &result)); + + const DynamicRefTable* dynamic_ref_table = result.getDynamicRefTableForCookie(1); + ASSERT_NE(nullptr, dynamic_ref_table); + + const KeyedVector<String16, uint8_t>& entries = dynamic_ref_table->entries(); + ssize_t idx = entries.indexOfKey(android::String16("app")); + ASSERT_GE(idx, 0); + EXPECT_EQ(0x80u, entries.valueAt(idx)); +} + TEST_F(TableFlattenerTest, LongPackageNameIsTruncated) { std::string kPackageName(256, 'F'); diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp index 494d9d25b008..f0613e74b5f8 100644 --- a/tools/aapt2/flatten/XmlFlattener_test.cpp +++ b/tools/aapt2/flatten/XmlFlattener_test.cpp @@ -35,13 +35,16 @@ class XmlFlattenerTest : public ::testing::Test { .SetNameManglerPolicy(NameManglerPolicy{"com.app.test"}) .AddSymbolSource( test::StaticSymbolSourceBuilder() - .AddSymbol("android:attr/id", ResourceId(0x010100d0), - test::AttributeBuilder().Build()) + .AddPublicSymbol("android:attr/id", ResourceId(0x010100d0), + test::AttributeBuilder().Build()) .AddSymbol("com.app.test:id/id", ResourceId(0x7f020000)) .AddPublicSymbol("android:attr/paddingStart", ResourceId(0x010103b3), test::AttributeBuilder().Build()) .AddPublicSymbol("android:attr/colorAccent", ResourceId(0x01010435), test::AttributeBuilder().Build()) + .AddSymbol("com.app.test.feature:id/foo", ResourceId(0x80020000)) + .AddSymbol("com.app.test.feature:attr/foo", ResourceId(0x80010000), + test::AttributeBuilder().Build()) .Build()) .Build(); } @@ -65,7 +68,7 @@ class XmlFlattenerTest : public ::testing::Test { } protected: - std::unique_ptr<IAaptContext> context_; + std::unique_ptr<test::Context> context_; }; TEST_F(XmlFlattenerTest, FlattenXmlWithNoCompiledAttributes) { @@ -218,14 +221,10 @@ TEST_F(XmlFlattenerTest, AssignSpecialAttributeIndices) { EXPECT_EQ(tree.indexOfStyle(), 1); } -/* - * The device ResXMLParser in libandroidfw differentiates between empty - * namespace and null - * namespace. - */ +// The device ResXMLParser in libandroidfw differentiates between empty namespace and null +// namespace. TEST_F(XmlFlattenerTest, NoNamespaceIsNotTheSameAsEmptyNamespace) { - std::unique_ptr<xml::XmlResource> doc = - test::BuildXmlDom("<View package=\"android\"/>"); + std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom("<View package=\"android\"/>"); android::ResXMLTree tree; ASSERT_TRUE(Flatten(doc.get(), &tree)); @@ -261,4 +260,44 @@ TEST_F(XmlFlattenerTest, EmptyStringValueInAttributeIsNotNull) { EXPECT_NE(nullptr, tree.getAttributeStringValue(idx, &len)); } +TEST_F(XmlFlattenerTest, FlattenNonStandardPackageId) { + context_->SetCompilationPackage("com.app.test.feature"); + context_->SetPackageId(0x80); + context_->SetNameManglerPolicy({"com.app.test.feature"}); + + std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF( + <View xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@id/foo" + app:foo="@id/foo" />)EOF"); + + XmlReferenceLinker linker; + ASSERT_TRUE(linker.Consume(context_.get(), doc.get())); + + // The tree needs a custom DynamicRefTable since it is not using a standard app ID (0x7f). + android::DynamicRefTable dynamic_ref_table; + dynamic_ref_table.addMapping(0x80, 0x80); + + android::ResXMLTree tree(&dynamic_ref_table); + ASSERT_TRUE(Flatten(doc.get(), &tree)); + + while (tree.next() != android::ResXMLTree::START_TAG) { + ASSERT_NE(android::ResXMLTree::BAD_DOCUMENT, tree.getEventType()); + ASSERT_NE(android::ResXMLTree::END_DOCUMENT, tree.getEventType()); + } + + ssize_t idx; + + idx = tree.indexOfAttribute(xml::kSchemaAndroid, "id"); + ASSERT_GE(idx, 0); + EXPECT_EQ(idx, tree.indexOfID()); + EXPECT_EQ(ResourceId(0x010100d0), ResourceId(tree.getAttributeNameResID(idx))); + + idx = tree.indexOfAttribute(xml::kSchemaAuto, "foo"); + ASSERT_GE(idx, 0); + EXPECT_EQ(ResourceId(0x80010000), ResourceId(tree.getAttributeNameResID(idx))); + EXPECT_EQ(android::Res_value::TYPE_REFERENCE, tree.getAttributeDataType(idx)); + EXPECT_EQ(ResourceId(0x80020000), tree.getAttributeData(idx)); +} + } // namespace aapt diff --git a/tools/aapt2/jni/aapt2_jni.cpp b/tools/aapt2/jni/aapt2_jni.cpp index ce3d282e6f9b..ad5ad4c336e5 100644 --- a/tools/aapt2/jni/aapt2_jni.cpp +++ b/tools/aapt2/jni/aapt2_jni.cpp @@ -24,13 +24,14 @@ #include "android-base/logging.h" #include "ScopedUtfChars.h" +#include "Diagnostics.h" #include "util/Util.h" using android::StringPiece; namespace aapt { -extern int Compile(const std::vector<StringPiece> &args); -extern int Link(const std::vector<StringPiece> &args); +extern int Compile(const std::vector<StringPiece>& args, IDiagnostics* iDiagnostics); +extern int Link(const std::vector<StringPiece>& args, IDiagnostics* iDiagnostics); } /* @@ -77,20 +78,66 @@ static std::vector<StringPiece> extract_pieces(const std::vector<ScopedUtfChars> return pieces; } +class JniDiagnostics : public aapt::IDiagnostics { + public: + JniDiagnostics(JNIEnv* env, jobject diagnostics_obj) + : env_(env), diagnostics_obj_(diagnostics_obj) { + mid_ = NULL; + } + + void Log(Level level, aapt::DiagMessageActual& actual_msg) override { + jint level_value; + switch (level) { + case Level::Error: + level_value = 3; + break; + + case Level::Warn: + level_value = 2; + break; + + case Level::Note: + level_value = 1; + break; + } + jstring message = env_->NewStringUTF(actual_msg.message.c_str()); + jstring path = env_->NewStringUTF(actual_msg.source.path.c_str()); + jlong line = -1; + if (actual_msg.source.line) { + line = actual_msg.source.line.value(); + } + if (!mid_) { + jclass diagnostics_cls = env_->GetObjectClass(diagnostics_obj_); + mid_ = env_->GetMethodID(diagnostics_cls, "log", "(ILjava/lang/String;JLjava/lang/String;)V"); + } + env_->CallVoidMethod(diagnostics_obj_, mid_, level_value, path, line, message); + } + + private: + JNIEnv* env_; + jobject diagnostics_obj_; + jmethodID mid_; + DISALLOW_COPY_AND_ASSIGN(JniDiagnostics); +}; + JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeCompile( - JNIEnv *env, jclass aapt_obj, jobject arguments_obj) { + JNIEnv* env, jclass aapt_obj, jobject arguments_obj, jobject diagnostics_obj) { std::vector<ScopedUtfChars> compile_args_jni = list_to_utfchars(env, arguments_obj); std::vector<StringPiece> compile_args = extract_pieces(compile_args_jni); - return aapt::Compile(compile_args); + JniDiagnostics diagnostics(env, diagnostics_obj); + return aapt::Compile(compile_args, &diagnostics); } -JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeLink( - JNIEnv *env, jclass aapt_obj, jobject arguments_obj) { +JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeLink(JNIEnv* env, + jclass aapt_obj, + jobject arguments_obj, + jobject diagnostics_obj) { std::vector<ScopedUtfChars> link_args_jni = list_to_utfchars(env, arguments_obj); std::vector<StringPiece> link_args = extract_pieces(link_args_jni); - return aapt::Link(link_args); + JniDiagnostics diagnostics(env, diagnostics_obj); + return aapt::Link(link_args, &diagnostics); } JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_ping( diff --git a/tools/aapt2/jni/com_android_tools_aapt2_Aapt2Jni.h b/tools/aapt2/jni/com_android_tools_aapt2_Aapt2Jni.h index 90150b4d731e..3cd98658fab2 100644 --- a/tools/aapt2/jni/com_android_tools_aapt2_Aapt2Jni.h +++ b/tools/aapt2/jni/com_android_tools_aapt2_Aapt2Jni.h @@ -18,18 +18,18 @@ JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_ping /* * Class: com_android_tools_aapt2_Aapt2Jni * Method: nativeCompile - * Signature: (Ljava/util/List;)I + * Signature: (Ljava/util/List;Lcom/android/tools/aapt2/Aapt2JniDiagnostics;)I */ -JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeCompile - (JNIEnv *, jclass, jobject); +JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeCompile(JNIEnv*, jclass, jobject, + jobject); /* * Class: com_android_tools_aapt2_Aapt2Jni * Method: nativeLink - * Signature: (Ljava/util/List;)I + * Signature: (Ljava/util/List;Lcom/android/tools/aapt2/Aapt2JniDiagnostics;)I */ -JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeLink - (JNIEnv *, jclass, jobject); +JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeLink(JNIEnv*, jclass, jobject, + jobject); #ifdef __cplusplus } diff --git a/tools/aapt2/test/Context.h b/tools/aapt2/test/Context.h index 29d183876c4c..0564db063b9a 100644 --- a/tools/aapt2/test/Context.h +++ b/tools/aapt2/test/Context.h @@ -52,15 +52,27 @@ class Context : public IAaptContext { return compilation_package_.value(); } + void SetCompilationPackage(const android::StringPiece& package) { + compilation_package_ = package.to_string(); + } + uint8_t GetPackageId() override { CHECK(bool(package_id_)) << "package ID not set"; return package_id_.value(); } + void SetPackageId(uint8_t package_id) { + package_id_ = package_id; + } + NameMangler* GetNameMangler() override { return &name_mangler_; } + void SetNameManglerPolicy(const NameManglerPolicy& policy) { + name_mangler_ = NameMangler(policy); + } + bool IsVerbose() override { return false; } diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 229aa97c9247..a7b4544f3752 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -81,7 +81,7 @@ interface IWifiManager boolean disableNetwork(int netId); - void startScan(in ScanSettings requested, in WorkSource ws); + void startScan(in ScanSettings requested, in WorkSource ws, in String packageName); List<ScanResult> getScanResults(String callingPackage); @@ -125,6 +125,8 @@ interface IWifiManager void setWifiApEnabled(in WifiConfiguration wifiConfig, boolean enable); + void updateInterfaceIpState(String ifaceName, int mode); + boolean startSoftAp(in WifiConfiguration wifiConfig); boolean stopSoftAp(); diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index ed54c3b3f192..ab069f2a83d2 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -20,7 +20,6 @@ import android.annotation.Nullable; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; -import android.bluetooth.BluetoothAdapter; import android.content.Context; import android.content.pm.ParceledListSlice; import android.net.ConnectivityManager; @@ -46,9 +45,9 @@ import com.android.internal.util.Protocol; import com.android.server.net.NetworkPinner; import java.net.InetAddress; +import java.util.Collections; import java.util.List; import java.util.concurrent.CountDownLatch; -import java.util.Collections; /** * This class provides the primary API for managing all aspects of Wi-Fi @@ -446,6 +445,35 @@ public class WifiManager { * @hide */ public static final int SAP_START_FAILURE_NO_CHANNEL = 1; + + /** + * Interface IP mode for configuration error. + * + * @see updateInterfaceIpState(String, int) + * + * @hide + */ + public static final int IFACE_IP_MODE_CONFIGURATION_ERROR = 0; + + /** + * Interface IP mode for tethering. + * + * @see updateInterfaceIpState(String, int) + * + * @hide + */ + public static final int IFACE_IP_MODE_TETHERED = 1; + + /** + * Interface IP mode for Local Only Hotspot. + * + * @see updateInterfaceIpState(String, int) + * + * @hide + */ + public static final int IFACE_IP_MODE_LOCAL_ONLY = 2; + + /** * Broadcast intent action indicating that a connection to the supplicant has * been established (and it is now possible @@ -1429,19 +1457,15 @@ public class WifiManager { * @return {@code true} if the operation succeeded, i.e., the scan was initiated */ public boolean startScan() { - try { - mService.startScan(null, null); - return true; - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return startScan(null); } /** @hide */ @SystemApi public boolean startScan(WorkSource workSource) { try { - mService.startScan(null, workSource); + String packageName = mContext.getOpPackageName(); + mService.startScan(null, workSource, packageName); return true; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1732,6 +1756,26 @@ public class WifiManager { } /** + * Call allowing ConnectivityService to update WifiService with interface mode changes. + * + * The possible modes include: {@link IFACE_IP_MODE_TETHERED}, + * {@link IFACE_IP_MODE_LOCAL_ONLY}, + * {@link IFACE_IP_MODE_CONFIGURATION_ERROR} + * + * @param ifaceName String name of the updated interface + * @param mode int representing the new mode + * + * @hide + */ + public void updateInterfaceIpState(String ifaceName, int mode) { + try { + mService.updateInterfaceIpState(ifaceName, mode); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Start SoftAp mode with the specified configuration. * Note that starting in access point mode disables station * mode operation |