diff options
127 files changed, 2466 insertions, 2116 deletions
diff --git a/api/current.txt b/api/current.txt index 53b074031580..d3184d6e109a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -6890,7 +6890,7 @@ package android.app.job { } public abstract class JobServiceEngine { - ctor public JobServiceEngine(android.content.Context); + ctor public JobServiceEngine(android.app.Service); method public final android.os.IBinder getBinder(); method public final void jobFinished(android.app.job.JobParameters, boolean); method public abstract boolean onStartJob(android.app.job.JobParameters); @@ -6994,12 +6994,12 @@ package android.app.usage { } public class StorageStatsManager { - method public long getFreeBytes(java.lang.String); - method public long getTotalBytes(java.lang.String); - method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle); - method public android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle); - method public android.app.usage.StorageStats queryStatsForUid(java.lang.String, int); - method public android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle); + method public long getFreeBytes(java.util.UUID) throws java.io.IOException; + method public long getTotalBytes(java.util.UUID) throws java.io.IOException; + method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.util.UUID, android.os.UserHandle) throws java.io.IOException; + method public android.app.usage.StorageStats queryStatsForPackage(java.util.UUID, java.lang.String, android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; + method public android.app.usage.StorageStats queryStatsForUid(java.util.UUID, int) throws java.io.IOException; + method public android.app.usage.StorageStats queryStatsForUser(java.util.UUID, android.os.UserHandle) throws java.io.IOException; } public final class UsageEvents implements android.os.Parcelable { @@ -10217,12 +10217,12 @@ package android.content.pm { field public java.lang.String[] splitNames; field public java.lang.String[] splitPublicSourceDirs; field public java.lang.String[] splitSourceDirs; + field public java.util.UUID storageUuid; field public int targetSdkVersion; field public java.lang.String taskAffinity; field public int theme; field public int uiOptions; field public int uid; - field public java.lang.String volumeUuid; } public static class ApplicationInfo.DisplayNameComparator implements java.util.Comparator { @@ -24011,7 +24011,6 @@ package android.media.browse { method public android.content.ComponentName getServiceComponent(); method public android.media.session.MediaSession.Token getSessionToken(); method public boolean isConnected(); - method public void search(java.lang.String, android.os.Bundle, android.media.browse.MediaBrowser.SearchCallback); method public void subscribe(java.lang.String, android.media.browse.MediaBrowser.SubscriptionCallback); method public void subscribe(java.lang.String, android.os.Bundle, android.media.browse.MediaBrowser.SubscriptionCallback); method public void unsubscribe(java.lang.String); @@ -24047,12 +24046,6 @@ package android.media.browse { field public static final int FLAG_PLAYABLE = 2; // 0x2 } - public static abstract class MediaBrowser.SearchCallback { - ctor public MediaBrowser.SearchCallback(); - method public void onError(java.lang.String, android.os.Bundle); - method public void onSearchResult(java.lang.String, android.os.Bundle, java.util.List<android.media.browse.MediaBrowser.MediaItem>); - } - public static abstract class MediaBrowser.SubscriptionCallback { ctor public MediaBrowser.SubscriptionCallback(); method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>); @@ -24261,8 +24254,6 @@ package android.media.session { public final class MediaController { ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token); - method public void addQueueItem(android.media.MediaDescription); - method public void addQueueItem(android.media.MediaDescription, int); method public void adjustVolume(int, int); method public boolean dispatchMediaButtonEvent(android.view.KeyEvent); method public android.os.Bundle getExtras(); @@ -24274,15 +24265,11 @@ package android.media.session { method public java.util.List<android.media.session.MediaSession.QueueItem> getQueue(); method public java.lang.CharSequence getQueueTitle(); method public int getRatingType(); - method public int getRepeatMode(); method public android.app.PendingIntent getSessionActivity(); method public android.media.session.MediaSession.Token getSessionToken(); method public android.media.session.MediaController.TransportControls getTransportControls(); - method public boolean isShuffleModeEnabled(); method public void registerCallback(android.media.session.MediaController.Callback); method public void registerCallback(android.media.session.MediaController.Callback, android.os.Handler); - method public void removeQueueItem(android.media.MediaDescription); - method public void removeQueueItemAt(int); method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver); method public void setVolumeTo(int, int); method public void unregisterCallback(android.media.session.MediaController.Callback); @@ -24296,10 +24283,8 @@ package android.media.session { method public void onPlaybackStateChanged(android.media.session.PlaybackState); method public void onQueueChanged(java.util.List<android.media.session.MediaSession.QueueItem>); method public void onQueueTitleChanged(java.lang.CharSequence); - method public void onRepeatModeChanged(int); method public void onSessionDestroyed(); method public void onSessionEvent(java.lang.String, android.os.Bundle); - method public void onShuffleModeChanged(boolean); } public static final class MediaController.PlaybackInfo { @@ -24328,8 +24313,6 @@ package android.media.session { method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle); method public void sendCustomAction(java.lang.String, android.os.Bundle); method public void setRating(android.media.Rating); - method public void setRepeatMode(int); - method public void setShuffleModeEnabled(boolean); method public void skipToNext(); method public void skipToPrevious(); method public void skipToQueueItem(long); @@ -24356,18 +24339,13 @@ package android.media.session { method public void setQueue(java.util.List<android.media.session.MediaSession.QueueItem>); method public void setQueueTitle(java.lang.CharSequence); method public void setRatingType(int); - method public void setRepeatMode(int); method public void setSessionActivity(android.app.PendingIntent); - method public void setShuffleModeEnabled(boolean); field public static final deprecated int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1 - field public static final int FLAG_HANDLES_QUEUE_COMMANDS = 4; // 0x4 field public static final deprecated int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2 } public static abstract class MediaSession.Callback { ctor public MediaSession.Callback(); - method public void onAddQueueItem(android.media.MediaDescription); - method public void onAddQueueItem(android.media.MediaDescription, int); method public void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver); method public void onCustomAction(java.lang.String, android.os.Bundle); method public void onFastForward(); @@ -24381,13 +24359,9 @@ package android.media.session { method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle); method public void onPrepareFromSearch(java.lang.String, android.os.Bundle); method public void onPrepareFromUri(android.net.Uri, android.os.Bundle); - method public void onRemoveQueueItem(android.media.MediaDescription); - method public void onRemoveQueueItemAt(int); method public void onRewind(); method public void onSeekTo(long); method public void onSetRating(android.media.Rating); - method public void onSetRepeatMode(int); - method public void onSetShuffleModeEnabled(boolean); method public void onSkipToNext(); method public void onSkipToPrevious(); method public void onSkipToQueueItem(long); @@ -24448,17 +24422,12 @@ package android.media.session { field public static final long ACTION_REWIND = 8L; // 0x8L field public static final long ACTION_SEEK_TO = 256L; // 0x100L field public static final long ACTION_SET_RATING = 128L; // 0x80L - field public static final long ACTION_SET_REPEAT_MODE = 262144L; // 0x40000L - field public static final long ACTION_SET_SHUFFLE_MODE_ENABLED = 524288L; // 0x80000L field public static final long ACTION_SKIP_TO_NEXT = 32L; // 0x20L field public static final long ACTION_SKIP_TO_PREVIOUS = 16L; // 0x10L field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L field public static final long ACTION_STOP = 1L; // 0x1L field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR; field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL - field public static final int REPEAT_MODE_ALL = 2; // 0x2 - field public static final int REPEAT_MODE_NONE = 0; // 0x0 - field public static final int REPEAT_MODE_ONE = 1; // 0x1 field public static final int STATE_BUFFERING = 6; // 0x6 field public static final int STATE_CONNECTING = 8; // 0x8 field public static final int STATE_ERROR = 7; // 0x7 @@ -30802,6 +30771,7 @@ 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); @@ -30826,6 +30796,7 @@ 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); @@ -31355,6 +31326,7 @@ 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); @@ -31400,6 +31372,7 @@ 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; } @@ -32030,15 +32003,16 @@ package android.os.storage { } public class StorageManager { - method public void allocateBytes(java.io.File, long, int) 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, int) throws java.io.IOException; - method public long getAllocatableBytes(java.io.File, int) throws java.io.IOException; - method public long getCacheQuotaBytes(java.io.File); - method public long getCacheSizeBytes(java.io.File); + 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; method public java.lang.String getMountedObbPath(java.lang.String); method public android.os.storage.StorageVolume getPrimaryStorageVolume(); method public android.os.storage.StorageVolume getStorageVolume(java.io.File); method public java.util.List<android.os.storage.StorageVolume> getStorageVolumes(); + method public java.util.UUID getUuidForPath(java.io.File) throws java.io.IOException; method public boolean isCacheBehaviorGroup(java.io.File) throws java.io.IOException; method public boolean isCacheBehaviorTombstone(java.io.File) throws java.io.IOException; method public boolean isEncrypted(java.io.File); @@ -32050,7 +32024,10 @@ package android.os.storage { method public void setCacheBehaviorTombstone(java.io.File, boolean) throws java.io.IOException; method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener); 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; } public final class StorageVolume implements android.os.Parcelable { @@ -37352,7 +37329,6 @@ package android.service.media { method public abstract void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>); method public void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>, android.os.Bundle); method public void onLoadItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>); - method public void onSearch(java.lang.String, android.os.Bundle, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>); method public void setSessionToken(android.media.session.MediaSession.Token); field public static final java.lang.String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService"; } diff --git a/api/removed.txt b/api/removed.txt index 1e8370e97dc5..0f5b81abad4c 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -22,6 +22,20 @@ package android.app.admin { } +package android.app.usage { + + 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; + method public deprecated boolean isQuotaSupported(java.lang.String); + method public deprecated android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle) throws java.io.IOException; + method public deprecated android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; + method public deprecated android.app.usage.StorageStats queryStatsForUid(java.lang.String, int) throws java.io.IOException; + method public deprecated android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle) throws java.io.IOException; + } + +} + package android.content { public abstract class Context { @@ -37,6 +51,10 @@ package android.content { package android.content.pm { + public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable { + field public deprecated java.lang.String volumeUuid; + } + public class ComponentInfo extends android.content.pm.PackageItemInfo { field public deprecated boolean encryptionAware; } @@ -180,10 +198,14 @@ package android.os { package android.os.storage { public class StorageManager { - method public deprecated long getCacheQuotaBytes(); - method public deprecated long getCacheSizeBytes(); - method public deprecated long getExternalCacheQuotaBytes(); - method public deprecated long getExternalCacheSizeBytes(); + method public deprecated void allocateBytes(java.io.File, long, int) throws java.io.IOException; + method public deprecated long getAllocatableBytes(java.io.File, int) throws java.io.IOException; + method public deprecated long getCacheQuotaBytes(java.io.File) throws java.io.IOException; + method public deprecated long getCacheQuotaBytes() throws java.io.IOException; + method public deprecated long getCacheSizeBytes(java.io.File) throws java.io.IOException; + method public deprecated long getCacheSizeBytes() throws java.io.IOException; + method public deprecated long getExternalCacheQuotaBytes() throws java.io.IOException; + method public deprecated long getExternalCacheSizeBytes() throws java.io.IOException; method public android.os.storage.StorageVolume getPrimaryVolume(); method public android.os.storage.StorageVolume[] getVolumeList(); method public deprecated boolean isCacheBehaviorAtomic(java.io.File) throws java.io.IOException; diff --git a/api/system-current.txt b/api/system-current.txt index a40634206e83..b2168327a786 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -7326,7 +7326,7 @@ package android.app.job { } public abstract class JobServiceEngine { - ctor public JobServiceEngine(android.content.Context); + ctor public JobServiceEngine(android.app.Service); method public final android.os.IBinder getBinder(); method public final void jobFinished(android.app.job.JobParameters, boolean); method public abstract boolean onStartJob(android.app.job.JobParameters); @@ -7459,12 +7459,12 @@ package android.app.usage { } public class StorageStatsManager { - method public long getFreeBytes(java.lang.String); - method public long getTotalBytes(java.lang.String); - method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle); - method public android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle); - method public android.app.usage.StorageStats queryStatsForUid(java.lang.String, int); - method public android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle); + method public long getFreeBytes(java.util.UUID) throws java.io.IOException; + method public long getTotalBytes(java.util.UUID) throws java.io.IOException; + method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.util.UUID, android.os.UserHandle) throws java.io.IOException; + method public android.app.usage.StorageStats queryStatsForPackage(java.util.UUID, java.lang.String, android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; + method public android.app.usage.StorageStats queryStatsForUid(java.util.UUID, int) throws java.io.IOException; + method public android.app.usage.StorageStats queryStatsForUser(java.util.UUID, android.os.UserHandle) throws java.io.IOException; } public final class UsageEvents implements android.os.Parcelable { @@ -10792,12 +10792,12 @@ package android.content.pm { field public java.lang.String[] splitNames; field public java.lang.String[] splitPublicSourceDirs; field public java.lang.String[] splitSourceDirs; + field public java.util.UUID storageUuid; field public int targetSdkVersion; field public java.lang.String taskAffinity; field public int theme; field public int uiOptions; field public int uid; - field public java.lang.String volumeUuid; } public static class ApplicationInfo.DisplayNameComparator implements java.util.Comparator { @@ -25933,7 +25933,6 @@ package android.media.browse { method public android.content.ComponentName getServiceComponent(); method public android.media.session.MediaSession.Token getSessionToken(); method public boolean isConnected(); - method public void search(java.lang.String, android.os.Bundle, android.media.browse.MediaBrowser.SearchCallback); method public void subscribe(java.lang.String, android.media.browse.MediaBrowser.SubscriptionCallback); method public void subscribe(java.lang.String, android.os.Bundle, android.media.browse.MediaBrowser.SubscriptionCallback); method public void unsubscribe(java.lang.String); @@ -25969,12 +25968,6 @@ package android.media.browse { field public static final int FLAG_PLAYABLE = 2; // 0x2 } - public static abstract class MediaBrowser.SearchCallback { - ctor public MediaBrowser.SearchCallback(); - method public void onError(java.lang.String, android.os.Bundle); - method public void onSearchResult(java.lang.String, android.os.Bundle, java.util.List<android.media.browse.MediaBrowser.MediaItem>); - } - public static abstract class MediaBrowser.SubscriptionCallback { ctor public MediaBrowser.SubscriptionCallback(); method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>); @@ -26183,8 +26176,6 @@ package android.media.session { public final class MediaController { ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token); - method public void addQueueItem(android.media.MediaDescription); - method public void addQueueItem(android.media.MediaDescription, int); method public void adjustVolume(int, int); method public boolean dispatchMediaButtonEvent(android.view.KeyEvent); method public android.os.Bundle getExtras(); @@ -26196,15 +26187,11 @@ package android.media.session { method public java.util.List<android.media.session.MediaSession.QueueItem> getQueue(); method public java.lang.CharSequence getQueueTitle(); method public int getRatingType(); - method public int getRepeatMode(); method public android.app.PendingIntent getSessionActivity(); method public android.media.session.MediaSession.Token getSessionToken(); method public android.media.session.MediaController.TransportControls getTransportControls(); - method public boolean isShuffleModeEnabled(); method public void registerCallback(android.media.session.MediaController.Callback); method public void registerCallback(android.media.session.MediaController.Callback, android.os.Handler); - method public void removeQueueItem(android.media.MediaDescription); - method public void removeQueueItemAt(int); method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver); method public void setVolumeTo(int, int); method public void unregisterCallback(android.media.session.MediaController.Callback); @@ -26218,10 +26205,8 @@ package android.media.session { method public void onPlaybackStateChanged(android.media.session.PlaybackState); method public void onQueueChanged(java.util.List<android.media.session.MediaSession.QueueItem>); method public void onQueueTitleChanged(java.lang.CharSequence); - method public void onRepeatModeChanged(int); method public void onSessionDestroyed(); method public void onSessionEvent(java.lang.String, android.os.Bundle); - method public void onShuffleModeChanged(boolean); } public static final class MediaController.PlaybackInfo { @@ -26250,8 +26235,6 @@ package android.media.session { method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle); method public void sendCustomAction(java.lang.String, android.os.Bundle); method public void setRating(android.media.Rating); - method public void setRepeatMode(int); - method public void setShuffleModeEnabled(boolean); method public void skipToNext(); method public void skipToPrevious(); method public void skipToQueueItem(long); @@ -26278,18 +26261,13 @@ package android.media.session { method public void setQueue(java.util.List<android.media.session.MediaSession.QueueItem>); method public void setQueueTitle(java.lang.CharSequence); method public void setRatingType(int); - method public void setRepeatMode(int); method public void setSessionActivity(android.app.PendingIntent); - method public void setShuffleModeEnabled(boolean); field public static final deprecated int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1 - field public static final int FLAG_HANDLES_QUEUE_COMMANDS = 4; // 0x4 field public static final deprecated int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2 } public static abstract class MediaSession.Callback { ctor public MediaSession.Callback(); - method public void onAddQueueItem(android.media.MediaDescription); - method public void onAddQueueItem(android.media.MediaDescription, int); method public void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver); method public void onCustomAction(java.lang.String, android.os.Bundle); method public void onFastForward(); @@ -26303,13 +26281,9 @@ package android.media.session { method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle); method public void onPrepareFromSearch(java.lang.String, android.os.Bundle); method public void onPrepareFromUri(android.net.Uri, android.os.Bundle); - method public void onRemoveQueueItem(android.media.MediaDescription); - method public void onRemoveQueueItemAt(int); method public void onRewind(); method public void onSeekTo(long); method public void onSetRating(android.media.Rating); - method public void onSetRepeatMode(int); - method public void onSetShuffleModeEnabled(boolean); method public void onSkipToNext(); method public void onSkipToPrevious(); method public void onSkipToQueueItem(long); @@ -26380,17 +26354,12 @@ package android.media.session { field public static final long ACTION_REWIND = 8L; // 0x8L field public static final long ACTION_SEEK_TO = 256L; // 0x100L field public static final long ACTION_SET_RATING = 128L; // 0x80L - field public static final long ACTION_SET_REPEAT_MODE = 262144L; // 0x40000L - field public static final long ACTION_SET_SHUFFLE_MODE_ENABLED = 524288L; // 0x80000L field public static final long ACTION_SKIP_TO_NEXT = 32L; // 0x20L field public static final long ACTION_SKIP_TO_PREVIOUS = 16L; // 0x10L field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L field public static final long ACTION_STOP = 1L; // 0x1L field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR; field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL - field public static final int REPEAT_MODE_ALL = 2; // 0x2 - field public static final int REPEAT_MODE_NONE = 0; // 0x0 - field public static final int REPEAT_MODE_ONE = 1; // 0x1 field public static final int STATE_BUFFERING = 6; // 0x6 field public static final int STATE_CONNECTING = 8; // 0x8 field public static final int STATE_ERROR = 7; // 0x7 @@ -33561,6 +33530,7 @@ 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); @@ -33585,6 +33555,7 @@ 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); @@ -34144,6 +34115,7 @@ 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); @@ -34189,6 +34161,7 @@ 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; } @@ -34924,15 +34897,16 @@ package android.os.storage { } public class StorageManager { - method public void allocateBytes(java.io.File, long, int) 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, int) throws java.io.IOException; - method public long getAllocatableBytes(java.io.File, int) throws java.io.IOException; - method public long getCacheQuotaBytes(java.io.File); - method public long getCacheSizeBytes(java.io.File); + 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; method public java.lang.String getMountedObbPath(java.lang.String); method public android.os.storage.StorageVolume getPrimaryStorageVolume(); method public android.os.storage.StorageVolume getStorageVolume(java.io.File); method public java.util.List<android.os.storage.StorageVolume> getStorageVolumes(); + method public java.util.UUID getUuidForPath(java.io.File) throws java.io.IOException; method public boolean isCacheBehaviorGroup(java.io.File) throws java.io.IOException; method public boolean isCacheBehaviorTombstone(java.io.File) throws java.io.IOException; method public boolean isEncrypted(java.io.File); @@ -34944,7 +34918,10 @@ package android.os.storage { method public void setCacheBehaviorTombstone(java.io.File, boolean) throws java.io.IOException; method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener); 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; } public final class StorageVolume implements android.os.Parcelable { @@ -40464,7 +40441,6 @@ package android.service.media { method public abstract void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>); method public void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>, android.os.Bundle); method public void onLoadItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>); - method public void onSearch(java.lang.String, android.os.Bundle, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>); method public void setSessionToken(android.media.session.MediaSession.Token); field public static final java.lang.String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService"; } diff --git a/api/system-removed.txt b/api/system-removed.txt index 7bdb9571bad0..823d88faaece 100644 --- a/api/system-removed.txt +++ b/api/system-removed.txt @@ -20,6 +20,20 @@ package android.app.admin { } +package android.app.usage { + + 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; + method public deprecated boolean isQuotaSupported(java.lang.String); + method public deprecated android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle) throws java.io.IOException; + method public deprecated android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; + method public deprecated android.app.usage.StorageStats queryStatsForUid(java.lang.String, int) throws java.io.IOException; + method public deprecated android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle) throws java.io.IOException; + } + +} + package android.content { public abstract class Context { @@ -35,6 +49,10 @@ package android.content { package android.content.pm { + public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable { + field public deprecated java.lang.String volumeUuid; + } + public class ComponentInfo extends android.content.pm.PackageItemInfo { field public deprecated boolean encryptionAware; } @@ -174,10 +192,14 @@ package android.os { package android.os.storage { public class StorageManager { - method public deprecated long getCacheQuotaBytes(); - method public deprecated long getCacheSizeBytes(); - method public deprecated long getExternalCacheQuotaBytes(); - method public deprecated long getExternalCacheSizeBytes(); + method public deprecated void allocateBytes(java.io.File, long, int) throws java.io.IOException; + method public deprecated long getAllocatableBytes(java.io.File, int) throws java.io.IOException; + method public deprecated long getCacheQuotaBytes(java.io.File) throws java.io.IOException; + method public deprecated long getCacheQuotaBytes() throws java.io.IOException; + method public deprecated long getCacheSizeBytes(java.io.File) throws java.io.IOException; + method public deprecated long getCacheSizeBytes() throws java.io.IOException; + method public deprecated long getExternalCacheQuotaBytes() throws java.io.IOException; + method public deprecated long getExternalCacheSizeBytes() throws java.io.IOException; method public android.os.storage.StorageVolume getPrimaryVolume(); method public android.os.storage.StorageVolume[] getVolumeList(); method public deprecated boolean isCacheBehaviorAtomic(java.io.File) throws java.io.IOException; diff --git a/api/test-current.txt b/api/test-current.txt index df84e13b5cd1..e3292f9b1bbc 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -6920,7 +6920,7 @@ package android.app.job { } public abstract class JobServiceEngine { - ctor public JobServiceEngine(android.content.Context); + ctor public JobServiceEngine(android.app.Service); method public final android.os.IBinder getBinder(); method public final void jobFinished(android.app.job.JobParameters, boolean); method public abstract boolean onStartJob(android.app.job.JobParameters); @@ -7024,13 +7024,13 @@ package android.app.usage { } public class StorageStatsManager { - method public long getFreeBytes(java.lang.String); - method public long getTotalBytes(java.lang.String); - method public boolean isQuotaSupported(java.lang.String); - method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle); - method public android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle); - method public android.app.usage.StorageStats queryStatsForUid(java.lang.String, int); - method public android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle); + method public long getFreeBytes(java.util.UUID) throws java.io.IOException; + method public long getTotalBytes(java.util.UUID) throws java.io.IOException; + method public boolean isQuotaSupported(java.util.UUID); + method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.util.UUID, android.os.UserHandle) throws java.io.IOException; + method public android.app.usage.StorageStats queryStatsForPackage(java.util.UUID, java.lang.String, android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; + method public android.app.usage.StorageStats queryStatsForUid(java.util.UUID, int) throws java.io.IOException; + method public android.app.usage.StorageStats queryStatsForUser(java.util.UUID, android.os.UserHandle) throws java.io.IOException; } public final class UsageEvents implements android.os.Parcelable { @@ -10253,12 +10253,12 @@ package android.content.pm { field public java.lang.String[] splitNames; field public java.lang.String[] splitPublicSourceDirs; field public java.lang.String[] splitSourceDirs; + field public java.util.UUID storageUuid; field public int targetSdkVersion; field public java.lang.String taskAffinity; field public int theme; field public int uiOptions; field public int uid; - field public java.lang.String volumeUuid; } public static class ApplicationInfo.DisplayNameComparator implements java.util.Comparator { @@ -24118,7 +24118,6 @@ package android.media.browse { method public android.content.ComponentName getServiceComponent(); method public android.media.session.MediaSession.Token getSessionToken(); method public boolean isConnected(); - method public void search(java.lang.String, android.os.Bundle, android.media.browse.MediaBrowser.SearchCallback); method public void subscribe(java.lang.String, android.media.browse.MediaBrowser.SubscriptionCallback); method public void subscribe(java.lang.String, android.os.Bundle, android.media.browse.MediaBrowser.SubscriptionCallback); method public void unsubscribe(java.lang.String); @@ -24154,12 +24153,6 @@ package android.media.browse { field public static final int FLAG_PLAYABLE = 2; // 0x2 } - public static abstract class MediaBrowser.SearchCallback { - ctor public MediaBrowser.SearchCallback(); - method public void onError(java.lang.String, android.os.Bundle); - method public void onSearchResult(java.lang.String, android.os.Bundle, java.util.List<android.media.browse.MediaBrowser.MediaItem>); - } - public static abstract class MediaBrowser.SubscriptionCallback { ctor public MediaBrowser.SubscriptionCallback(); method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>); @@ -24368,8 +24361,6 @@ package android.media.session { public final class MediaController { ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token); - method public void addQueueItem(android.media.MediaDescription); - method public void addQueueItem(android.media.MediaDescription, int); method public void adjustVolume(int, int); method public boolean dispatchMediaButtonEvent(android.view.KeyEvent); method public android.os.Bundle getExtras(); @@ -24381,15 +24372,11 @@ package android.media.session { method public java.util.List<android.media.session.MediaSession.QueueItem> getQueue(); method public java.lang.CharSequence getQueueTitle(); method public int getRatingType(); - method public int getRepeatMode(); method public android.app.PendingIntent getSessionActivity(); method public android.media.session.MediaSession.Token getSessionToken(); method public android.media.session.MediaController.TransportControls getTransportControls(); - method public boolean isShuffleModeEnabled(); method public void registerCallback(android.media.session.MediaController.Callback); method public void registerCallback(android.media.session.MediaController.Callback, android.os.Handler); - method public void removeQueueItem(android.media.MediaDescription); - method public void removeQueueItemAt(int); method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver); method public void setVolumeTo(int, int); method public void unregisterCallback(android.media.session.MediaController.Callback); @@ -24403,10 +24390,8 @@ package android.media.session { method public void onPlaybackStateChanged(android.media.session.PlaybackState); method public void onQueueChanged(java.util.List<android.media.session.MediaSession.QueueItem>); method public void onQueueTitleChanged(java.lang.CharSequence); - method public void onRepeatModeChanged(int); method public void onSessionDestroyed(); method public void onSessionEvent(java.lang.String, android.os.Bundle); - method public void onShuffleModeChanged(boolean); } public static final class MediaController.PlaybackInfo { @@ -24435,8 +24420,6 @@ package android.media.session { method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle); method public void sendCustomAction(java.lang.String, android.os.Bundle); method public void setRating(android.media.Rating); - method public void setRepeatMode(int); - method public void setShuffleModeEnabled(boolean); method public void skipToNext(); method public void skipToPrevious(); method public void skipToQueueItem(long); @@ -24463,18 +24446,13 @@ package android.media.session { method public void setQueue(java.util.List<android.media.session.MediaSession.QueueItem>); method public void setQueueTitle(java.lang.CharSequence); method public void setRatingType(int); - method public void setRepeatMode(int); method public void setSessionActivity(android.app.PendingIntent); - method public void setShuffleModeEnabled(boolean); field public static final deprecated int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1 - field public static final int FLAG_HANDLES_QUEUE_COMMANDS = 4; // 0x4 field public static final deprecated int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2 } public static abstract class MediaSession.Callback { ctor public MediaSession.Callback(); - method public void onAddQueueItem(android.media.MediaDescription); - method public void onAddQueueItem(android.media.MediaDescription, int); method public void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver); method public void onCustomAction(java.lang.String, android.os.Bundle); method public void onFastForward(); @@ -24488,13 +24466,9 @@ package android.media.session { method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle); method public void onPrepareFromSearch(java.lang.String, android.os.Bundle); method public void onPrepareFromUri(android.net.Uri, android.os.Bundle); - method public void onRemoveQueueItem(android.media.MediaDescription); - method public void onRemoveQueueItemAt(int); method public void onRewind(); method public void onSeekTo(long); method public void onSetRating(android.media.Rating); - method public void onSetRepeatMode(int); - method public void onSetShuffleModeEnabled(boolean); method public void onSkipToNext(); method public void onSkipToPrevious(); method public void onSkipToQueueItem(long); @@ -24555,17 +24529,12 @@ package android.media.session { field public static final long ACTION_REWIND = 8L; // 0x8L field public static final long ACTION_SEEK_TO = 256L; // 0x100L field public static final long ACTION_SET_RATING = 128L; // 0x80L - field public static final long ACTION_SET_REPEAT_MODE = 262144L; // 0x40000L - field public static final long ACTION_SET_SHUFFLE_MODE_ENABLED = 524288L; // 0x80000L field public static final long ACTION_SKIP_TO_NEXT = 32L; // 0x20L field public static final long ACTION_SKIP_TO_PREVIOUS = 16L; // 0x10L field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L field public static final long ACTION_STOP = 1L; // 0x1L field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR; field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL - field public static final int REPEAT_MODE_ALL = 2; // 0x2 - field public static final int REPEAT_MODE_NONE = 0; // 0x0 - field public static final int REPEAT_MODE_ONE = 1; // 0x1 field public static final int STATE_BUFFERING = 6; // 0x6 field public static final int STATE_CONNECTING = 8; // 0x8 field public static final int STATE_ERROR = 7; // 0x7 @@ -30909,6 +30878,7 @@ 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); @@ -30933,6 +30903,7 @@ 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); @@ -31483,6 +31454,7 @@ 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); @@ -31528,6 +31500,7 @@ 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; } @@ -32162,15 +32135,16 @@ package android.os.storage { } public class StorageManager { - method public void allocateBytes(java.io.File, long, int) 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, int) throws java.io.IOException; - method public long getAllocatableBytes(java.io.File, int) throws java.io.IOException; - method public long getCacheQuotaBytes(java.io.File); - method public long getCacheSizeBytes(java.io.File); + 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; method public java.lang.String getMountedObbPath(java.lang.String); method public android.os.storage.StorageVolume getPrimaryStorageVolume(); method public android.os.storage.StorageVolume getStorageVolume(java.io.File); method public java.util.List<android.os.storage.StorageVolume> getStorageVolumes(); + method public java.util.UUID getUuidForPath(java.io.File) throws java.io.IOException; method public boolean isCacheBehaviorGroup(java.io.File) throws java.io.IOException; method public boolean isCacheBehaviorTombstone(java.io.File) throws java.io.IOException; method public boolean isEncrypted(java.io.File); @@ -32182,7 +32156,10 @@ package android.os.storage { method public void setCacheBehaviorTombstone(java.io.File, boolean) throws java.io.IOException; method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener); 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; } public final class StorageVolume implements android.os.Parcelable { @@ -37505,7 +37482,6 @@ package android.service.media { method public abstract void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>); method public void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>, android.os.Bundle); method public void onLoadItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>); - method public void onSearch(java.lang.String, android.os.Bundle, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>); method public void setSessionToken(android.media.session.MediaSession.Token); field public static final java.lang.String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService"; } diff --git a/api/test-removed.txt b/api/test-removed.txt index 1e8370e97dc5..0f5b81abad4c 100644 --- a/api/test-removed.txt +++ b/api/test-removed.txt @@ -22,6 +22,20 @@ package android.app.admin { } +package android.app.usage { + + 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; + method public deprecated boolean isQuotaSupported(java.lang.String); + method public deprecated android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle) throws java.io.IOException; + method public deprecated android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; + method public deprecated android.app.usage.StorageStats queryStatsForUid(java.lang.String, int) throws java.io.IOException; + method public deprecated android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle) throws java.io.IOException; + } + +} + package android.content { public abstract class Context { @@ -37,6 +51,10 @@ package android.content { package android.content.pm { + public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable { + field public deprecated java.lang.String volumeUuid; + } + public class ComponentInfo extends android.content.pm.PackageItemInfo { field public deprecated boolean encryptionAware; } @@ -180,10 +198,14 @@ package android.os { package android.os.storage { public class StorageManager { - method public deprecated long getCacheQuotaBytes(); - method public deprecated long getCacheSizeBytes(); - method public deprecated long getExternalCacheQuotaBytes(); - method public deprecated long getExternalCacheSizeBytes(); + method public deprecated void allocateBytes(java.io.File, long, int) throws java.io.IOException; + method public deprecated long getAllocatableBytes(java.io.File, int) throws java.io.IOException; + method public deprecated long getCacheQuotaBytes(java.io.File) throws java.io.IOException; + method public deprecated long getCacheQuotaBytes() throws java.io.IOException; + method public deprecated long getCacheSizeBytes(java.io.File) throws java.io.IOException; + method public deprecated long getCacheSizeBytes() throws java.io.IOException; + method public deprecated long getExternalCacheQuotaBytes() throws java.io.IOException; + method public deprecated long getExternalCacheSizeBytes() throws java.io.IOException; method public android.os.storage.StorageVolume getPrimaryVolume(); method public android.os.storage.StorageVolume[] getVolumeList(); method public deprecated boolean isCacheBehaviorAtomic(java.io.File) throws java.io.IOException; diff --git a/cmds/media/src/com/android/commands/media/Media.java b/cmds/media/src/com/android/commands/media/Media.java index 4be46540e19b..9df229cbf490 100644 --- a/cmds/media/src/com/android/commands/media/Media.java +++ b/cmds/media/src/com/android/commands/media/Media.java @@ -228,16 +228,6 @@ public class Media extends BaseCommand { System.out.println("onVolumeInfoChanged " + info); } - @Override - public void onRepeatModeChanged(int repeatMode) throws RemoteException { - System.out.println("onRepeatModeChanged " + repeatMode); - } - - @Override - public void onShuffleModeChanged(boolean enabled) throws RemoteException { - System.out.println("onShuffleModeChanged " + enabled); - } - void printUsageMessage() { try { System.out.println("V2Monitoring session " + mController.getTag() diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 169dcb01c90a..c4b7ed771b70 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2070,6 +2070,7 @@ public class Activity extends ContextThemeWrapper if (args == null) { throw new IllegalArgumentException("Expected non-null picture-in-picture args"); } + updatePictureInPictureArgsForContentInsets(args); return ActivityManagerNative.getDefault().enterPictureInPictureMode(mToken, args); } catch (RemoteException e) { return false; @@ -2087,11 +2088,27 @@ public class Activity extends ContextThemeWrapper if (args == null) { throw new IllegalArgumentException("Expected non-null picture-in-picture args"); } + updatePictureInPictureArgsForContentInsets(args); ActivityManagerNative.getDefault().setPictureInPictureArgs(mToken, args); } catch (RemoteException e) { } } + /** + * Updates the provided {@param args} with the last known content insets for this activity, to + * be used with the source hint rect for the transition into PiP. + */ + private void updatePictureInPictureArgsForContentInsets(PictureInPictureArgs args) { + if (args != null && args.hasSourceBoundsHint() && getWindow() != null && + getWindow().peekDecorView() != null && + getWindow().peekDecorView().getViewRootImpl() != null) { + args.setSourceRectHintInsets( + getWindow().peekDecorView().getViewRootImpl().getLastContentInsets()); + } else { + args.setSourceRectHintInsets(null); + } + } + void dispatchMovedToDisplay(int displayId, Configuration config) { updateDisplay(displayId); onMovedToDisplay(displayId, config); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 8ed52a1bba59..cab2114f6918 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -4202,9 +4202,22 @@ public class Notification implements Parcelable * @hide */ public RemoteViews makePublicContentView() { + return makePublicView(false /* ambient */); + } + + /** + * Construct a RemoteViews for the display in public contexts like on the lockscreen. + * + * @hide + */ + public RemoteViews makePublicAmbientNotification() { + return makePublicView(true /* ambient */); + } + + private RemoteViews makePublicView(boolean ambient) { if (mN.publicVersion != null) { final Builder builder = recoverBuilder(mContext, mN.publicVersion); - return builder.createContentView(); + return ambient ? builder.makeAmbientNotification() : builder.createContentView(); } Bundle savedBundle = mN.extras; Style style = mStyle; @@ -4221,14 +4234,15 @@ public class Notification implements Parcelable publicExtras.putBoolean(EXTRA_CHRONOMETER_COUNT_DOWN, savedBundle.getBoolean(EXTRA_CHRONOMETER_COUNT_DOWN)); publicExtras.putCharSequence(EXTRA_TITLE, - mContext.getString(R.string.notification_hidden_text)); + mContext.getString(com.android.internal.R.string.notification_hidden_text)); mN.extras = publicExtras; - final RemoteViews publicView = applyStandardTemplate(getBaseLayoutResource()); + final RemoteViews view = ambient ? makeAmbientNotification() + : applyStandardTemplate(getBaseLayoutResource()); mN.extras = savedBundle; mN.mLargeIcon = largeIcon; mN.largeIcon = largeIconLegacy; mStyle = style; - return publicView; + return view; } /** diff --git a/core/java/android/app/PictureInPictureArgs.java b/core/java/android/app/PictureInPictureArgs.java index 0ce5eebed287..2fa636046901 100644 --- a/core/java/android/app/PictureInPictureArgs.java +++ b/core/java/android/app/PictureInPictureArgs.java @@ -49,6 +49,13 @@ public final class PictureInPictureArgs implements Parcelable { @Nullable private Rect mSourceRectHint; + /** + * The content insets that are used with the source hint rect for the transition into PiP where + * the insets are removed at the beginning of the transition. + */ + @Nullable + private Rect mSourceRectHintInsets; + PictureInPictureArgs(Parcel in) { if (in.readInt() != 0) { mAspectRatio = in.readFloat(); @@ -60,6 +67,9 @@ public final class PictureInPictureArgs implements Parcelable { if (in.readInt() != 0) { mSourceRectHint = Rect.CREATOR.createFromParcel(in); } + if (in.readInt() != 0) { + mSourceRectHintInsets = Rect.CREATOR.createFromParcel(in); + } } /** @@ -94,6 +104,9 @@ public final class PictureInPictureArgs implements Parcelable { if (otherArgs.hasSourceBoundsHint()) { mSourceRectHint = new Rect(otherArgs.getSourceRectHint()); } + if (otherArgs.hasSourceBoundsHintInsets()) { + mSourceRectHintInsets = new Rect(otherArgs.getSourceRectHintInsets()); + } } /** @@ -167,7 +180,19 @@ public final class PictureInPictureArgs implements Parcelable { } /** - * @return the launch bounds + * Sets the insets to be used with the source rect hint bounds. + * @hide + */ + public void setSourceRectHintInsets(Rect insets) { + if (insets == null) { + mSourceRectHintInsets = null; + } else { + mSourceRectHintInsets = new Rect(insets); + } + } + + /** + * @return the source rect hint * @hide */ public Rect getSourceRectHint() { @@ -175,6 +200,14 @@ public final class PictureInPictureArgs implements Parcelable { } /** + * @return the source rect hint insets. + * @hide + */ + public Rect getSourceRectHintInsets() { + return mSourceRectHintInsets; + } + + /** * @return whether there are launch bounds set * @hide */ @@ -182,12 +215,23 @@ public final class PictureInPictureArgs implements Parcelable { return mSourceRectHint != null && !mSourceRectHint.isEmpty(); } + /** + * @return whether there are source rect hint insets set + * @hide + */ + public boolean hasSourceBoundsHintInsets() { + return mSourceRectHintInsets != null; + } + @Override public PictureInPictureArgs clone() { PictureInPictureArgs args = new PictureInPictureArgs(mAspectRatio, mUserActions); if (mSourceRectHint != null) { args.setSourceRectHint(mSourceRectHint); } + if (mSourceRectHintInsets != null) { + args.setSourceRectHintInsets(mSourceRectHintInsets); + } return args; } @@ -216,6 +260,12 @@ public final class PictureInPictureArgs implements Parcelable { } else { out.writeInt(0); } + if (mSourceRectHintInsets != null) { + out.writeInt(1); + mSourceRectHintInsets.writeToParcel(out, 0); + } else { + out.writeInt(0); + } } public static final Creator<PictureInPictureArgs> CREATOR = diff --git a/core/java/android/app/job/JobParameters.java b/core/java/android/app/job/JobParameters.java index 016a0fa8b92b..673d1b886b25 100644 --- a/core/java/android/app/job/JobParameters.java +++ b/core/java/android/app/job/JobParameters.java @@ -164,6 +164,20 @@ public class JobParameters implements Parcelable { * you should not call {@link JobService#jobFinished(JobParameters, boolean)} yourself * (otherwise you risk losing an upcoming JobWorkItem that is being enqueued at the same time). * + * <p>Once you are done with the {@link JobWorkItem} returned by this method, you must call + * {@link #completeWork(JobWorkItem)} with it to inform the system that you are done + * executing the work. The job will not be finished until all dequeued work has been + * completed. You do not, however, have to complete each returned work item before deqeueing + * the next one -- you can use {@link #dequeueWork()} multiple times before completing + * previous work if you want to process work in parallel, and you can complete the work + * in whatever order you want.</p> + * + * <p>If the job runs to the end of its available time period before all work has been + * completed, it will stop as normal. You should return true from + * {@link JobService#onStopJob(JobParameters)} in order to have the job rescheduled, and by + * doing so any pending as well as remaining uncompleted work will be re-queued + * for the next time the job runs.</p> + * * @return Returns a new {@link JobWorkItem} if there is one pending, otherwise null. * If null is returned, the system will also stop the job if all work has also been completed. * (This means that for correct operation, you must always call dequeueWork() after you have diff --git a/core/java/android/app/job/JobServiceEngine.java b/core/java/android/app/job/JobServiceEngine.java index 879212ea1fb3..a62861902a55 100644 --- a/core/java/android/app/job/JobServiceEngine.java +++ b/core/java/android/app/job/JobServiceEngine.java @@ -54,7 +54,7 @@ public abstract class JobServiceEngine { /** * Context we are running in. */ - private final Context mContext; + private final Service mService; private final IJobService mBinder; @@ -182,12 +182,12 @@ public abstract class JobServiceEngine { /** * Create a new engine, ready for use. * - * @param context The {@link Service} that is creating this engine. + * @param service The {@link Service} that is creating this engine and in which it will run. */ - public JobServiceEngine(Context context) { - mContext = context; + public JobServiceEngine(Service service) { + mService = service; mBinder = new JobInterface(this); - mHandler = new JobHandler(mContext.getMainLooper()); + mHandler = new JobHandler(mService.getMainLooper()); } /** diff --git a/core/java/android/app/job/JobWorkItem.java b/core/java/android/app/job/JobWorkItem.java index 4bb057e689b2..05687ee9aace 100644 --- a/core/java/android/app/job/JobWorkItem.java +++ b/core/java/android/app/job/JobWorkItem.java @@ -27,6 +27,7 @@ import android.os.Parcelable; final public class JobWorkItem implements Parcelable { final Intent mIntent; int mWorkId; + Object mGrants; /** * Create a new piece of work. @@ -57,6 +58,20 @@ final public class JobWorkItem implements Parcelable { return mWorkId; } + /** + * @hide + */ + public void setGrants(Object grants) { + mGrants = grants; + } + + /** + * @hide + */ + public Object getGrants() { + return mGrants; + } + public String toString() { return "JobWorkItem{id=" + mWorkId + " intent=" + mIntent + "}"; } diff --git a/core/java/android/app/usage/StorageStatsManager.java b/core/java/android/app/usage/StorageStatsManager.java index 6fc4f5c1c95c..4b6479ad4a7b 100644 --- a/core/java/android/app/usage/StorageStatsManager.java +++ b/core/java/android/app/usage/StorageStatsManager.java @@ -16,17 +16,25 @@ package android.app.usage; +import static android.os.storage.StorageManager.convert; + +import android.annotation.NonNull; import android.annotation.TestApi; import android.annotation.WorkerThread; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.os.ParcelableException; import android.os.RemoteException; import android.os.UserHandle; +import android.os.storage.StorageManager; import com.android.internal.util.Preconditions; import java.io.File; +import java.io.IOException; +import java.util.UUID; /** * Provides access to detailed storage statistics. @@ -50,36 +58,49 @@ public class StorageStatsManager { /** {@hide} */ @TestApi - public boolean isQuotaSupported(String volumeUuid) { + public boolean isQuotaSupported(@NonNull UUID storageUuid) { try { - return mService.isQuotaSupported(volumeUuid, mContext.getOpPackageName()); + return mService.isQuotaSupported(convert(storageUuid), mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } + /** @removed */ + @Deprecated + public boolean isQuotaSupported(String uuid) { + return isQuotaSupported(convert(uuid)); + } + /** - * Return the total space on the requested storage volume. + * Return the total size of the media hosting this storage volume. * <p> - * To reduce end user confusion, this value is the total storage size + * To reduce end user confusion, this value matches the total storage size * advertised in a retail environment, which is typically larger than the - * actual writable partition total size. - * <p> - * This method may take several seconds to calculate the requested values, - * so it should only be called from a worker thread. + * actual usable partition space. * - * @param volumeUuid the UUID of the storage volume you're interested in, or - * {@code null} to specify the default internal storage. + * @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(String volumeUuid) { + public long getTotalBytes(@NonNull UUID storageUuid) throws IOException { try { - return mService.getTotalBytes(volumeUuid, mContext.getOpPackageName()); + return mService.getTotalBytes(convert(storageUuid), mContext.getOpPackageName()); + } catch (ParcelableException e) { + e.maybeRethrow(IOException.class); + throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } + /** @removed */ + @Deprecated + public long getTotalBytes(String uuid) throws IOException { + return getTotalBytes(convert(uuid)); + } + /** * Return the free space on the requested storage volume. * <p> @@ -90,18 +111,28 @@ public class StorageStatsManager { * This method may take several seconds to calculate the requested values, * so it should only be called from a worker thread. * - * @param volumeUuid the UUID of the storage volume you're interested in, or - * {@code null} to specify the default internal storage. + * @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(String volumeUuid) { + public long getFreeBytes(@NonNull UUID storageUuid) throws IOException { try { - return mService.getFreeBytes(volumeUuid, mContext.getOpPackageName()); + return mService.getFreeBytes(convert(storageUuid), mContext.getOpPackageName()); + } catch (ParcelableException e) { + e.maybeRethrow(IOException.class); + throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } + /** @removed */ + @Deprecated + public long getFreeBytes(String uuid) throws IOException { + return getFreeBytes(convert(uuid)); + } + /** * Return storage statistics for a specific package on the requested storage * volume. @@ -112,27 +143,41 @@ public class StorageStatsManager { * Note: if the requested package uses the {@code android:sharedUserId} * manifest feature, this call will be forced into a slower manual * calculation path. If possible, consider always using - * {@link #queryStatsForUid(String, int)}, which is typically faster. + * {@link #queryStatsForUid(UUID, int)}, which is typically faster. * </p> * - * @param volumeUuid the UUID of the storage volume you're interested in, or - * {@code null} to specify the default internal storage. + * @param storageUuid the UUID of the storage volume you're interested in, + * such as {@link StorageManager#UUID_DEFAULT}. * @param packageName the package name you're interested in. * @param user the user you're interested in. - * @see ApplicationInfo#volumeUuid + * @throws PackageManager.NameNotFoundException when the requested package + * name isn't installed for the requested user. + * @throws IOException when the storage device isn't present. + * @see ApplicationInfo#storageUuid * @see PackageInfo#packageName */ @WorkerThread - public StorageStats queryStatsForPackage(String volumeUuid, String packageName, - UserHandle user) { + public @NonNull StorageStats queryStatsForPackage(@NonNull UUID storageUuid, String packageName, + UserHandle user) throws PackageManager.NameNotFoundException, IOException { try { - return mService.queryStatsForPackage(volumeUuid, packageName, user.getIdentifier(), - mContext.getOpPackageName()); + return mService.queryStatsForPackage(convert(storageUuid), packageName, + user.getIdentifier(), mContext.getOpPackageName()); + } catch (ParcelableException e) { + e.maybeRethrow(PackageManager.NameNotFoundException.class); + e.maybeRethrow(IOException.class); + throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } + /** @removed */ + @Deprecated + public StorageStats queryStatsForPackage(String uuid, String packageName, + UserHandle user) throws PackageManager.NameNotFoundException, IOException { + return queryStatsForPackage(convert(uuid), packageName, user); + } + /** * Return storage statistics for a specific UID on the requested storage * volume. @@ -140,21 +185,32 @@ public class StorageStatsManager { * This method may take several seconds to calculate the requested values, * so it should only be called from a worker thread. * - * @param volumeUuid the UUID of the storage volume you're interested in, or - * {@code null} to specify the default internal storage. + * @param storageUuid the UUID of the storage volume you're interested in, + * such as {@link StorageManager#UUID_DEFAULT}. * @param uid the UID you're interested in. - * @see ApplicationInfo#volumeUuid + * @throws IOException when the storage device isn't present. + * @see ApplicationInfo#storageUuid * @see ApplicationInfo#uid */ @WorkerThread - public StorageStats queryStatsForUid(String volumeUuid, int uid) { + public StorageStats queryStatsForUid(@NonNull UUID storageUuid, int uid) throws IOException { try { - return mService.queryStatsForUid(volumeUuid, uid, mContext.getOpPackageName()); + return mService.queryStatsForUid(convert(storageUuid), uid, + mContext.getOpPackageName()); + } catch (ParcelableException e) { + e.maybeRethrow(IOException.class); + throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } + /** @removed */ + @Deprecated + public StorageStats queryStatsForUid(String uuid, int uid) throws IOException { + return queryStatsForUid(convert(uuid), uid); + } + /** * Return storage statistics for a specific {@link UserHandle} on the * requested storage volume. @@ -162,21 +218,32 @@ public class StorageStatsManager { * This method may take several seconds to calculate the requested values, * so it should only be called from a worker thread. * - * @param volumeUuid the UUID of the storage volume you're interested in, or - * {@code null} to specify the default internal storage. + * @param storageUuid the UUID of the storage volume you're interested in, + * such as {@link StorageManager#UUID_DEFAULT}. * @param user the user you're interested in. + * @throws IOException when the storage device isn't present. * @see android.os.Process#myUserHandle() */ @WorkerThread - public StorageStats queryStatsForUser(String volumeUuid, UserHandle user) { + public StorageStats queryStatsForUser(@NonNull UUID storageUuid, UserHandle user) + throws IOException { try { - return mService.queryStatsForUser(volumeUuid, user.getIdentifier(), + return mService.queryStatsForUser(convert(storageUuid), user.getIdentifier(), mContext.getOpPackageName()); + } catch (ParcelableException e) { + e.maybeRethrow(IOException.class); + throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } + /** @removed */ + @Deprecated + public StorageStats queryStatsForUser(String uuid, UserHandle user) throws IOException { + return queryStatsForUser(convert(uuid), user); + } + /** * Return shared/external storage statistics for a specific * {@link UserHandle} on the requested storage volume. @@ -184,20 +251,32 @@ public class StorageStatsManager { * This method may take several seconds to calculate the requested values, * so it should only be called from a worker thread. * - * @param volumeUuid the UUID of the storage volume you're interested in, or - * {@code null} to specify the default internal storage. + * @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. * @see android.os.Process#myUserHandle() */ @WorkerThread - public ExternalStorageStats queryExternalStatsForUser(String volumeUuid, UserHandle user) { + public ExternalStorageStats queryExternalStatsForUser(@NonNull UUID storageUuid, + UserHandle user) throws IOException { try { - return mService.queryExternalStatsForUser(volumeUuid, user.getIdentifier(), + return mService.queryExternalStatsForUser(convert(storageUuid), user.getIdentifier(), mContext.getOpPackageName()); + } catch (ParcelableException e) { + e.maybeRethrow(IOException.class); + throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } + /** @removed */ + @Deprecated + public ExternalStorageStats queryExternalStatsForUser(String uuid, UserHandle user) + throws IOException { + return queryExternalStatsForUser(convert(uuid), user); + } + /** {@hide} */ public long getCacheQuotaBytes(String volumeUuid, int uid) { try { diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index 23e54baab622..d64f018c3f2e 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -1787,7 +1787,7 @@ public class IntentFilter implements Parcelable { sb.append(", mHasPartialTypes="); sb.append(mHasPartialTypes); du.println(sb.toString()); } - { + if (getAutoVerify()) { sb.setLength(0); sb.append(prefix); sb.append("AutoVerify="); sb.append(getAutoVerify()); du.println(sb.toString()); diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 5f53e27eeb07..8b2809af5cb2 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -29,6 +29,7 @@ import android.os.Environment; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; +import android.os.storage.StorageManager; import android.text.TextUtils; import android.util.Printer; import android.util.SparseArray; @@ -41,6 +42,7 @@ import java.text.Collator; import java.util.Arrays; import java.util.Comparator; import java.util.Objects; +import java.util.UUID; /** * Information you can retrieve about a particular application. This @@ -621,12 +623,17 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { */ public float maxAspectRatio; + /** @removed */ + @Deprecated + public String volumeUuid; + /** * UUID of the storage volume on which this application is being hosted. For * apps hosted on the default internal storage at - * {@link Environment#getDataDirectory()}, the UUID value is {@code null}. + * {@link Environment#getDataDirectory()}, the UUID value is + * {@link StorageManager#UUID_DEFAULT}. */ - public String volumeUuid; + public UUID storageUuid; /** {@hide} */ public String scanSourceDir; @@ -1134,6 +1141,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { compatibleWidthLimitDp = orig.compatibleWidthLimitDp; largestWidthLimitDp = orig.largestWidthLimitDp; volumeUuid = orig.volumeUuid; + storageUuid = orig.storageUuid; scanSourceDir = orig.scanSourceDir; scanPublicSourceDir = orig.scanPublicSourceDir; sourceDir = orig.sourceDir; @@ -1195,7 +1203,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { dest.writeInt(requiresSmallestWidthDp); dest.writeInt(compatibleWidthLimitDp); dest.writeInt(largestWidthLimitDp); - dest.writeString(volumeUuid); + dest.writeUuid(storageUuid); dest.writeString(scanSourceDir); dest.writeString(scanPublicSourceDir); dest.writeString(sourceDir); @@ -1257,7 +1265,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { requiresSmallestWidthDp = source.readInt(); compatibleWidthLimitDp = source.readInt(); largestWidthLimitDp = source.readInt(); - volumeUuid = source.readString(); + storageUuid = source.readUuid(); + volumeUuid = StorageManager.convert(storageUuid); scanSourceDir = source.readString(); scanPublicSourceDir = source.readString(); sourceDir = source.readString(); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index d6bc6a143006..1f78bff9e1a7 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -67,6 +67,7 @@ import android.os.PatternMatcher; import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; +import android.os.storage.StorageManager; import android.system.ErrnoException; import android.system.OsConstants; import android.system.StructStat; @@ -117,6 +118,7 @@ import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; import java.util.zip.ZipEntry; @@ -5774,11 +5776,14 @@ public class PackageParser { } public void setApplicationVolumeUuid(String volumeUuid) { + final UUID storageUuid = StorageManager.convert(volumeUuid); this.applicationInfo.volumeUuid = volumeUuid; + this.applicationInfo.storageUuid = storageUuid; if (childPackages != null) { final int packageCount = childPackages.size(); for (int i = 0; i < packageCount; i++) { childPackages.get(i).applicationInfo.volumeUuid = volumeUuid; + childPackages.get(i).applicationInfo.storageUuid = storageUuid; } } } diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java index 9b5ff29d592e..167c46d6ded0 100644 --- a/core/java/android/os/Bundle.java +++ b/core/java/android/os/Bundle.java @@ -25,6 +25,7 @@ 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. @@ -476,6 +477,18 @@ 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. @@ -858,6 +871,26 @@ 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 c3836a38c822..c1647c74f363 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -16,8 +16,6 @@ package android.os; -import android.annotation.IntegerRes; -import android.annotation.NonNull; import android.annotation.Nullable; import android.text.TextUtils; import android.util.ArrayMap; @@ -29,6 +27,9 @@ import android.util.SparseArray; import android.util.SparseBooleanArray; import android.util.SparseIntArray; +import dalvik.annotation.optimization.FastNative; +import dalvik.system.VMRuntime; + import libcore.util.SneakyThrow; import java.io.ByteArrayInputStream; @@ -49,9 +50,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; - -import dalvik.annotation.optimization.FastNative; -import dalvik.system.VMRuntime; +import java.util.UUID; /** * Container for a message (data and object references) that can @@ -243,6 +242,7 @@ 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,6 +831,15 @@ 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. @@ -1678,6 +1687,9 @@ 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) { @@ -2182,6 +2194,13 @@ 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() { @@ -2731,6 +2750,9 @@ 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/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index b5af766fd159..394253173553 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -66,6 +66,7 @@ import com.android.internal.util.Preconditions; import java.io.File; import java.io.FileDescriptor; +import java.io.FileNotFoundException; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -77,6 +78,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Objects; +import java.util.UUID; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; @@ -117,19 +119,66 @@ public class StorageManager { public static final String UUID_PRIVATE_INTERNAL = null; /** {@hide} */ public static final String UUID_PRIMARY_PHYSICAL = "primary_physical"; + /** {@hide} */ + public static final String UUID_SYSTEM = "system"; + // NOTE: UUID constants below are namespaced + // uuid -v5 ad99aa3d-308e-4191-a200-ebcab371c0ad default + // uuid -v5 ad99aa3d-308e-4191-a200-ebcab371c0ad primary_physical + // uuid -v5 ad99aa3d-308e-4191-a200-ebcab371c0ad system /** - * Activity Action: Allows the user to manage their storage. This activity provides the ability - * to free up space on the device by deleting data such as apps. + * UUID representing the default internal storage of this device which + * provides {@link Environment#getDataDirectory()}. * <p> - * Input: Nothing. + * This value is constant across all devices and it will never change, and + * thus it cannot be used to uniquely identify a particular physical device. + * + * @see #getUuidForPath(File) + */ + public static final UUID UUID_DEFAULT = UUID + .fromString("41217664-9172-527a-b3d5-edabb50a7d69"); + + /** {@hide} */ + public static final UUID UUID_PRIMARY_PHYSICAL_ = UUID + .fromString("0f95a519-dae7-5abf-9519-fbd6209e05fd"); + + /** {@hide} */ + public static final UUID UUID_SYSTEM_ = UUID + .fromString("5d258386-e60d-59e3-826d-0089cdd42cc0"); + + /** + * Activity Action: Allows the user to manage their storage. This activity + * provides the ability to free up space on the device by deleting data such + * as apps. * <p> - * Output: Nothing. + * If the sending application has a specific storage device or allocation + * size in mind, they can optionally define {@link #EXTRA_UUID} or + * {@link #EXTRA_REQUESTED_BYTES}, respectively. */ @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_MANAGE_STORAGE - = "android.os.storage.action.MANAGE_STORAGE"; + public static final String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE"; + + /** + * Extra {@link UUID} used to indicate the storage volume where an + * application is interested in allocating or managing disk space. + * + * @see #ACTION_MANAGE_STORAGE + * @see #UUID_DEFAULT + * @see #getUuidForPath(File) + */ + public static final String EXTRA_UUID = "android.os.storage.extra.UUID"; + + /** + * Extra used to indicate the total size (in bytes) that an application is + * interested in allocating. + * <p> + * When defined, the management UI will help guide the user to free up + * enough disk space to reach this requested value. + * + * @see #ACTION_MANAGE_STORAGE + */ + public static final String EXTRA_REQUESTED_BYTES = "android.os.storage.extra.REQUESTED_BYTES"; /** {@hide} */ public static final int DEBUG_FORCE_ADOPTABLE = 1 << 0; @@ -668,34 +717,44 @@ public class StorageManager { } } - /** {@hide} */ - public @Nullable String findUuidForPath(File path) { + /** + * Return a UUID identifying the storage volume that hosts the given + * filesystem path. + * <p> + * If this path is hosted by the default internal storage of the device at + * {@link Environment#getDataDirectory()}, the returned value will be + * {@link #UUID_DEFAULT}. + * + * @throws IOException when the storage device at the given path isn't + * present, or when it doesn't have a valid UUID. + */ + public @NonNull UUID getUuidForPath(@NonNull File path) throws IOException { Preconditions.checkNotNull(path); final String pathString = path.getAbsolutePath(); if (FileUtils.contains(Environment.getDataDirectory().getAbsolutePath(), pathString)) { - return StorageManager.UUID_PRIVATE_INTERNAL; + return UUID_DEFAULT; } try { for (VolumeInfo vol : mStorageManager.getVolumes(0)) { if (vol.path != null && FileUtils.contains(vol.path, pathString)) { // TODO: verify that emulated adopted devices have UUID of // underlying volume - return vol.fsUuid; + return convert(vol.fsUuid); } } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } - throw new IllegalStateException("Failed to find a storage device for " + path); + throw new FileNotFoundException("Failed to find a storage device for " + path); } /** {@hide} */ - public @Nullable File findPathForUuid(String volumeUuid) { + public @NonNull File findPathForUuid(String volumeUuid) throws FileNotFoundException { final VolumeInfo vol = findVolumeByQualifiedUuid(volumeUuid); if (vol != null) { return vol.getPath(); } - throw new IllegalStateException("Failed to find a storage device for " + volumeUuid); + throw new FileNotFoundException("Failed to find a storage device for " + volumeUuid); } /** {@hide} */ @@ -1451,7 +1510,7 @@ public class StorageManager { /** * Return quota size in bytes for all cached data belonging to the calling - * app on the filesystem that hosts the given path. + * app on the given storage volume. * <p> * If your app goes above this quota, your cached files will be some of the * first to be deleted when additional disk space is needed. Conversely, if @@ -1466,21 +1525,34 @@ public class StorageManager { * as a single unit. * </p> * - * @see #getCacheSizeBytes(File) + * @param storageUuid the UUID of the storage volume that you're interested + * in. The UUID for a specific path can be obtained using + * {@link #getUuidForPath(File)}. + * @throws IOException when the storage device isn't present, or when it + * doesn't support cache quotas. + * @see #getCacheSizeBytes(UUID) */ - public long getCacheQuotaBytes(File path) { + public long getCacheQuotaBytes(@NonNull UUID storageUuid) throws IOException { try { - final String volumeUuid = findUuidForPath(path); final ApplicationInfo app = mContext.getApplicationInfo(); - return mStorageManager.getCacheQuotaBytes(volumeUuid, app.uid); + return mStorageManager.getCacheQuotaBytes(convert(storageUuid), app.uid); + } catch (ParcelableException e) { + e.maybeRethrow(IOException.class); + throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } + /** @removed */ + @Deprecated + public long getCacheQuotaBytes(@NonNull File path) throws IOException { + return getCacheQuotaBytes(getUuidForPath(path)); + } + /** * Return total size in bytes of all cached data belonging to the calling - * app on the filesystem that hosts the given path. + * app on the given storage volume. * <p> * Cached data tracked by this method always includes * {@link Context#getCacheDir()} and {@link Context#getCodeCacheDir()}, and @@ -1493,13 +1565,20 @@ public class StorageManager { * as a single unit. * </p> * - * @see #getCacheQuotaBytes() + * @param storageUuid the UUID of the storage volume that you're interested + * in. The UUID for a specific path can be obtained using + * {@link #getUuidForPath(File)}. + * @throws IOException when the storage device isn't present, or when it + * doesn't support cache quotas. + * @see #getCacheQuotaBytes(UUID) */ - public long getCacheSizeBytes(File path) { + public long getCacheSizeBytes(@NonNull UUID storageUuid) throws IOException { try { - final String volumeUuid = findUuidForPath(path); final ApplicationInfo app = mContext.getApplicationInfo(); - return mStorageManager.getCacheSizeBytes(volumeUuid, app.uid); + return mStorageManager.getCacheSizeBytes(convert(storageUuid), app.uid); + } catch (ParcelableException e) { + e.maybeRethrow(IOException.class); + throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1507,25 +1586,31 @@ public class StorageManager { /** @removed */ @Deprecated - public long getCacheQuotaBytes() { + public long getCacheSizeBytes(@NonNull File path) throws IOException { + return getCacheSizeBytes(getUuidForPath(path)); + } + + /** @removed */ + @Deprecated + public long getCacheQuotaBytes() throws IOException { return getCacheQuotaBytes(mContext.getCacheDir()); } /** @removed */ @Deprecated - public long getCacheSizeBytes() { + public long getCacheSizeBytes() throws IOException { return getCacheSizeBytes(mContext.getCacheDir()); } /** @removed */ @Deprecated - public long getExternalCacheQuotaBytes() { + public long getExternalCacheQuotaBytes() throws IOException { return getCacheQuotaBytes(mContext.getExternalCacheDir()); } /** @removed */ @Deprecated - public long getExternalCacheSizeBytes() { + public long getExternalCacheSizeBytes() throws IOException { return getCacheSizeBytes(mContext.getExternalCacheDir()); } @@ -1542,8 +1627,8 @@ public class StorageManager { * this flag to take effect. * </p> * - * @see #getAllocatableBytes(File, int) - * @see #allocateBytes(File, long, int) + * @see #getAllocatableBytes(UUID, int) + * @see #allocateBytes(UUID, long, int) * @see #allocateBytes(FileDescriptor, long, int) */ @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE) @@ -1558,32 +1643,43 @@ public class StorageManager { /** * Return the maximum number of new bytes that your app can allocate for - * itself using {@link #allocateBytes(File, long, int)} at the given path. - * This value is typically larger than {@link File#getUsableSpace()}, since - * the system may be willing to delete cached files to satisfy an allocation - * request. + * itself on the given storage volume. This value is typically larger than + * {@link File#getUsableSpace()}, since the system may be willing to delete + * cached files to satisfy an allocation request. You can then allocate + * space for yourself using {@link #allocateBytes(UUID, long, int)} or + * {@link #allocateBytes(FileDescriptor, long, int)}. * <p> * This method is best used as a pre-flight check, such as deciding if there * is enough space to store an entire music album before you allocate space * for each audio file in the album. Attempts to allocate disk space beyond * 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 + * {@link #EXTRA_UUID} and {@link #EXTRA_REQUESTED_BYTES} options to help + * involve the user in freeing up disk space. * <p class="note"> * Note: if your app uses the {@code android:sharedUserId} manifest feature, * then allocatable space for all packages in your shared UID is tracked * together as a single unit. * </p> * - * @param path the path where you're considering allocating disk space, - * since allocatable space can vary widely depending on the - * underlying storage device. + * @param storageUuid the UUID of the storage volume where you're + * considering allocating disk space, since allocatable space can + * 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(File, long, int)}. + * 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 long getAllocatableBytes(File path, @AllocateFlags int flags) throws IOException { + public long getAllocatableBytes(@NonNull UUID storageUuid, @AllocateFlags int flags) + throws IOException { try { - final String volumeUuid = findUuidForPath(path); - return mStorageManager.getAllocatableBytes(volumeUuid, flags); + return mStorageManager.getAllocatableBytes(convert(storageUuid), flags); } catch (ParcelableException e) { e.maybeRethrow(IOException.class); throw new RuntimeException(e); @@ -1592,28 +1688,40 @@ public class StorageManager { } } + /** @removed */ + @Deprecated + public long getAllocatableBytes(@NonNull File path, @AllocateFlags int flags) + throws IOException { + return getAllocatableBytes(getUuidForPath(path), flags); + } + /** - * Allocate the requested number of bytes for your application to use at the - * given path. This will cause the system to delete any cached files - * necessary to satisfy your request. + * Allocate the requested number of bytes for your application to use on the + * given storage volume. This will cause the system to delete any cached + * files necessary to satisfy your request. * <p> * Attempts to allocate disk space beyond the value returned by - * {@link #getAllocatableBytes(File, int)} will fail. + * {@link #getAllocatableBytes(UUID, int)} will fail. * <p> * Since multiple apps can be running simultaneously, this method may be * subject to race conditions. If possible, consider using * {@link #allocateBytes(FileDescriptor, long, int)} which will guarantee * that bytes are allocated to an opened file. * - * @param path the path where you'd like to allocate disk space. + * @param storageUuid the UUID of the storage volume where you'd like to + * 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. - * @see #getAllocatableBytes(File, int) + * @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(File path, long bytes, @AllocateFlags int flags) throws IOException { + public void allocateBytes(@NonNull UUID storageUuid, long bytes, @AllocateFlags int flags) + throws IOException { try { - final String volumeUuid = findUuidForPath(path); - mStorageManager.allocateBytes(volumeUuid, bytes, flags); + mStorageManager.allocateBytes(convert(storageUuid), bytes, flags); } catch (ParcelableException e) { e.maybeRethrow(IOException.class); } catch (RemoteException e) { @@ -1621,13 +1729,20 @@ public class StorageManager { } } + /** @removed */ + @Deprecated + public void allocateBytes(@NonNull File path, long bytes, @AllocateFlags int flags) + throws IOException { + allocateBytes(getUuidForPath(path), bytes, flags); + } + /** * Allocate the requested number of bytes for your application to use in the * given open file. This will cause the system to delete any cached files * necessary to satisfy your request. * <p> * Attempts to allocate disk space beyond the value returned by - * {@link #getAllocatableBytes(File, int)} will fail. + * {@link #getAllocatableBytes(UUID, int)} will fail. * <p> * This method guarantees that bytes have been allocated to the opened file, * otherwise it will throw if fast allocation is not possible. Fast @@ -1636,9 +1751,15 @@ public class StorageManager { * * @param fd the open file that you'd like to allocate disk space for. * @param bytes the number of bytes to allocate. This is the desired final - * size of the open file. + * size of the open file. If the open file is smaller than this + * 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. - * @see #getAllocatableBytes(File, int) + * @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) @@ -1777,6 +1898,32 @@ public class StorageManager { return isCacheBehavior(path, XATTR_CACHE_TOMBSTONE); } + /** {@hide} */ + public static UUID convert(String uuid) { + if (Objects.equals(uuid, UUID_PRIVATE_INTERNAL)) { + return UUID_DEFAULT; + } else if (Objects.equals(uuid, UUID_PRIMARY_PHYSICAL)) { + return UUID_PRIMARY_PHYSICAL_; + } else if (Objects.equals(uuid, UUID_SYSTEM)) { + return UUID_SYSTEM_; + } else { + return UUID.fromString(uuid); + } + } + + /** {@hide} */ + public static String convert(UUID storageUuid) { + if (UUID_DEFAULT.equals(storageUuid)) { + return UUID_PRIVATE_INTERNAL; + } else if (UUID_PRIMARY_PHYSICAL_.equals(storageUuid)) { + return UUID_PRIMARY_PHYSICAL; + } else if (UUID_SYSTEM_.equals(storageUuid)) { + return UUID_SYSTEM; + } else { + return storageUuid.toString(); + } + } + private final Object mFuseAppLoopLock = new Object(); @GuardedBy("mFuseAppLoopLock") diff --git a/core/java/android/view/IPinnedStackController.aidl b/core/java/android/view/IPinnedStackController.aidl index 2fe98c0b6f05..dbeb747adfba 100644 --- a/core/java/android/view/IPinnedStackController.aidl +++ b/core/java/android/view/IPinnedStackController.aidl @@ -28,4 +28,9 @@ interface IPinnedStackController { * Notifies the controller that the PiP is currently minimized. */ oneway void setIsMinimized(boolean isMinimized); + + /** + * @return what WM considers to be the current device rotation. + */ + int getDisplayRotation(); } diff --git a/core/java/android/view/IPinnedStackListener.aidl b/core/java/android/view/IPinnedStackListener.aidl index 782f3499fb79..9382741a81ec 100644 --- a/core/java/android/view/IPinnedStackListener.aidl +++ b/core/java/android/view/IPinnedStackListener.aidl @@ -41,9 +41,13 @@ oneway interface IPinnedStackListener { * current state with the aspect ratio applied. The {@param animatingBounds} are provided * to indicate the current target bounds of the pinned stack (the final bounds if animating, * the current bounds if not), which may be helpful in calculating dependent animation bounds. + * + * The {@param displayRotation} is provided so that the client can verify when making certain + * calls that it will not provide stale information based on an old display rotation (ie. if + * the WM has changed in the mean time but the client has not received onMovementBoundsChanged). */ void onMovementBoundsChanged(in Rect insetBounds, in Rect normalBounds, in Rect animatingBounds, - boolean fromImeAdjustement); + boolean fromImeAdjustement, int displayRotation); /** * Called when window manager decides to adjust the pinned stack bounds because of the IME, or diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index a7ececf6c782..080ffeb011f8 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1561,6 +1561,16 @@ public final class ViewRootImpl implements ViewParent, host.dispatchApplyWindowInsets(getWindowInsets(true /* forceConstruct */)); } + /** + * @return the last content insets for use in adjusting the source hint rect for the + * picture-in-picture transition. + * + * @hide + */ + public Rect getLastContentInsets() { + return mAttachInfo.mContentInsets; + } + private static boolean shouldUseDisplaySize(final WindowManager.LayoutParams lp) { return lp.type == TYPE_STATUS_BAR_PANEL || lp.type == TYPE_INPUT_METHOD diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java index 6dbc09ceef97..bf0e10f993ad 100644 --- a/core/java/android/view/WindowManagerInternal.java +++ b/core/java/android/view/WindowManagerInternal.java @@ -303,13 +303,16 @@ public abstract class WindowManagerInternal { * hidden, no matter how WindowManagerService will react / has reacted * to corresponding API calls. Note that this state is not guaranteed * to be synchronized with state in WindowManagerService. + * @param dismissImeOnBackKeyPressed {@code true} if the software keyboard is shown and the back + * key is expected to dismiss the software keyboard. * @param targetWindowToken token to identify the target window that the IME is associated with. * {@code null} when application, system, or the IME itself decided to * change its window visibility before being associated with any target * window. */ public abstract void updateInputMethodWindowStatus(@NonNull IBinder imeToken, - boolean imeWindowVisible, @Nullable IBinder targetWindowToken); + boolean imeWindowVisible, boolean dismissImeOnBackKeyPressed, + @Nullable IBinder targetWindowToken); /** * Returns true when the hardware keyboard is available. diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index bb6e0eed57cc..030c78b7f4b6 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -1537,6 +1537,18 @@ public interface WindowManagerPolicy { public void setLastInputMethodWindowLw(WindowState ime, WindowState target); /** + * An internal callback (from InputMethodManagerService) to notify a state change regarding + * whether the back key should dismiss the software keyboard (IME) or not. + * + * @param newValue {@code true} if the software keyboard is shown and the back key is expected + * to dismiss the software keyboard. + * @hide + */ + default void setDismissImeOnBackKeyPressed(boolean newValue) { + // Default implementation does nothing. + } + + /** * Show the recents task list app. * @hide */ diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index baf6db93daaf..80b6b0848a0b 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -82,6 +82,7 @@ import android.widget.PopupWindow; import static android.app.ActivityManager.StackId; import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; +import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; @@ -2182,19 +2183,22 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind final boolean wasAdjustedForStack = mElevationAdjustedForStack; // Do not use a shadow when we are in resizing mode (mBackdropFrameRenderer not null) // since the shadow is bound to the content size and not the target size. - if (StackId.hasWindowShadow(mStackId) && !isResizing()) { + if ((mStackId == FREEFORM_WORKSPACE_STACK_ID) && !isResizing()) { elevation = hasWindowFocus() ? DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP; // Add a maximum shadow height value to the top level view. // Note that pinned stack doesn't have focus // so maximum shadow height adjustment isn't needed. // TODO(skuhne): Remove this if clause once b/22668382 got fixed. - if (!mAllowUpdateElevation && mStackId != PINNED_STACK_ID) { + if (!mAllowUpdateElevation) { elevation = DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP; } // Convert the DP elevation into physical pixels. elevation = dipToPx(elevation); mElevationAdjustedForStack = true; + } else if (mStackId == PINNED_STACK_ID) { + elevation = dipToPx(DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP); + mElevationAdjustedForStack = true; } else { mElevationAdjustedForStack = false; } diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp index 520302ee02b9..2c7174d71c6b 100644 --- a/core/jni/android_hardware_SensorManager.cpp +++ b/core/jni/android_hardware_SensorManager.cpp @@ -24,6 +24,7 @@ #include <ScopedLocalRef.h> #include <android_runtime/AndroidRuntime.h> #include <android_runtime/android_hardware_HardwareBuffer.h> +#include <vndk/hardware_buffer.h> #include <sensor/Sensor.h> #include <sensor/SensorEventQueue.h> #include <sensor/SensorManager.h> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 45dccb6bfe33..6a31e161842b 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -852,6 +852,8 @@ 1 - Go to sleep (doze) 2 - Really go to sleep (don't doze) 3 - Really go to sleep and go home (don't doze) + 4 - Go to home + 5 - Dismiss IME if shown. Otherwise go to home --> <integer name="config_shortPressOnPowerBehavior">1</integer> diff --git a/libs/hwui/tests/unit/FontRendererTests.cpp b/libs/hwui/tests/unit/FontRendererTests.cpp index ee202367d73e..773a7ea54a52 100644 --- a/libs/hwui/tests/unit/FontRendererTests.cpp +++ b/libs/hwui/tests/unit/FontRendererTests.cpp @@ -28,7 +28,7 @@ static bool isZero(uint8_t* data, int size) { return true; } -RENDERTHREAD_OPENGL_PIPELINE_TEST(FontRenderer, renderDropShadow) { +RENDERTHREAD_OPENGL_PIPELINE_TEST(FontRenderer, DISABLED_renderDropShadow) { SkPaint paint; paint.setTextSize(10); paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); diff --git a/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp b/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp index 8312bda8d67d..5383e5756b93 100644 --- a/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp +++ b/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp @@ -26,7 +26,7 @@ using namespace android; using namespace android::uirenderer; -RENDERTHREAD_OPENGL_PIPELINE_TEST(TextDropShadowCache, addRemove) { +RENDERTHREAD_OPENGL_PIPELINE_TEST(TextDropShadowCache, DISABLED_addRemove) { SkPaint paint; paint.setTextSize(20); diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java index 5bf205e12799..789d5e0d8478 100644 --- a/media/java/android/media/browse/MediaBrowser.java +++ b/media/java/android/media/browse/MediaBrowser.java @@ -365,7 +365,7 @@ public final class MediaBrowser { * @param parentId The id of the parent media item whose list of children * will be subscribed. * @param options The bundle of service-specific arguments to send to the media - * browse service. The contents of this bundle may affect the + * browser service. The contents of this bundle may affect the * information returned when browsing. * @param callback The callback to receive the list of children. */ @@ -453,7 +453,7 @@ public final class MediaBrowser { try { mServiceBinder.getMediaItem(mediaId, receiver, mServiceCallbacks); } catch (RemoteException e) { - Log.i(TAG, "Remote error getting media item.", e); + Log.i(TAG, "Remote error getting media item."); mHandler.post(new Runnable() { @Override public void run() { @@ -463,62 +463,6 @@ public final class MediaBrowser { } } - /** - * Searches {@link MediaItem media items} from the connected service. Not - * all services may support this, and {@link SearchCallback#onError} will be - * called if not implemented. - * - * @param query The search query that contains keywords separated by space. Should not be - * an empty string. - * @param extras The bundle of service-specific arguments to send to the media browser - * service. The contents of this bundle may affect the search result. - * @param callback The callback to receive the search result. - * @throws IllegalStateException if the browser is not connected to the media browser service. - */ - public void search(@NonNull final String query, final Bundle extras, SearchCallback callback) { - if (TextUtils.isEmpty(query)) { - throw new IllegalArgumentException("query cannot be empty."); - } - if (callback == null) { - throw new IllegalArgumentException("callback cannot be null."); - } - if (mState != CONNECT_STATE_CONNECTED) { - throw new IllegalStateException("search() called while not connected (state=" - + getStateLabel(mState) + ")"); - } - ResultReceiver receiver = new ResultReceiver(mHandler) { - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - if (resultCode != 0 || resultData == null - || !resultData.containsKey(MediaBrowserService.KEY_SEARCH_RESULTS)) { - callback.onError(query, extras); - return; - } - Parcelable[] items = resultData.getParcelableArray( - MediaBrowserService.KEY_SEARCH_RESULTS); - List<MediaItem> results = null; - if (items != null) { - results = new ArrayList<>(); - for (Parcelable item : items) { - results.add((MediaItem) item); - } - } - callback.onSearchResult(query, extras, results); - } - }; - try { - mServiceBinder.search(query, extras, receiver, mServiceCallbacks); - } catch (RemoteException e) { - Log.i(TAG, "Remote error getting media item.", e); - mHandler.post(new Runnable() { - @Override - public void run() { - callback.onError(query, extras); - } - }); - } - } - private void subscribeInternal(String parentId, Bundle options, SubscriptionCallback callback) { // Check arguments. if (TextUtils.isEmpty(parentId)) { @@ -945,7 +889,7 @@ public final class MediaBrowser { * @param parentId The media id of the parent media item. * @param children The children which were loaded. * @param options The bundle of service-specific arguments sent to the media - * browse service. The contents of this bundle may affect the + * browser service. The contents of this bundle may affect the * information returned when browsing. */ public void onChildrenLoaded(@NonNull String parentId, @NonNull List<MediaItem> children, @@ -1004,32 +948,6 @@ public final class MediaBrowser { } /** - * Callback for receiving the result of {@link #search}. - */ - public static abstract class SearchCallback { - /** - * Called when the {@link #search} finished successfully. - * - * @param query The search query sent for the search request to the connected service. - * @param extras The bundle of service-specific arguments sent to the connected service. - * @param items The list of media items which contains the search result. - */ - public void onSearchResult(@NonNull String query, Bundle extras, - @NonNull List<MediaItem> items) { - } - - /** - * Called when an error happens while {@link #search} or the connected service doesn't - * support {@link #search}. - * - * @param query The search query sent for the search request to the connected service. - * @param extras The bundle of service-specific arguments sent to the connected service. - */ - public void onError(@NonNull String query, Bundle extras) { - } - } - - /** * ServiceConnection to the other app. */ private class MediaServiceConnection implements ServiceConnection { diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl index 4f3314c1e8ab..3affee5c0aa7 100644 --- a/media/java/android/media/session/ISession.aidl +++ b/media/java/android/media/session/ISession.aidl @@ -45,8 +45,6 @@ interface ISession { void setQueueTitle(CharSequence title); void setExtras(in Bundle extras); void setRatingType(int type); - void setRepeatMode(int repeatMode); - void setShuffleModeEnabled(boolean enabled); // These commands relate to volume handling void setPlaybackToLocal(in AudioAttributes attributes); diff --git a/media/java/android/media/session/ISessionCallback.aidl b/media/java/android/media/session/ISessionCallback.aidl index a146c6226171..893bd3c8cbb1 100644 --- a/media/java/android/media/session/ISessionCallback.aidl +++ b/media/java/android/media/session/ISessionCallback.aidl @@ -16,7 +16,6 @@ package android.media.session; import android.content.Intent; -import android.media.MediaDescription; import android.media.Rating; import android.net.Uri; import android.os.Bundle; @@ -47,13 +46,7 @@ oneway interface ISessionCallback { void onRewind(); void onSeekTo(long pos); void onRate(in Rating rating); - void onRepeatMode(int repeatMode); - void onShuffleMode(boolean enabled); void onCustomAction(String action, in Bundle args); - void onAddQueueItem(in MediaDescription description); - void onAddQueueItemAt(in MediaDescription description, int index); - void onRemoveQueueItem(in MediaDescription description); - void onRemoveQueueItemAt(int index); // These callbacks are for volume handling void onAdjustVolume(int direction); diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl index 7b5233ac0704..249bcdc802ce 100644 --- a/media/java/android/media/session/ISessionController.aidl +++ b/media/java/android/media/session/ISessionController.aidl @@ -18,7 +18,6 @@ package android.media.session; import android.app.PendingIntent; import android.content.Intent; import android.content.pm.ParceledListSlice; -import android.media.MediaDescription; import android.media.MediaMetadata; import android.media.Rating; import android.media.session.ISessionControllerCallback; @@ -49,19 +48,6 @@ interface ISessionController { ParcelableVolumeInfo getVolumeAttributes(); void adjustVolume(int direction, int flags, String packageName); void setVolumeTo(int value, int flags, String packageName); - MediaMetadata getMetadata(); - PlaybackState getPlaybackState(); - ParceledListSlice getQueue(); - void addQueueItem(in MediaDescription description); - void addQueueItemAt(in MediaDescription description, int index); - void removeQueueItem(in MediaDescription description); - void removeQueueItemAt(int index); - - CharSequence getQueueTitle(); - Bundle getExtras(); - int getRatingType(); - int getRepeatMode(); - boolean isShuffleModeEnabled(); // These commands are for the TransportControls void prepare(); @@ -81,7 +67,11 @@ interface ISessionController { void rewind(); void seekTo(long pos); void rate(in Rating rating); - void repeatMode(int repeatMode); - void shuffleMode(boolean enabled); void sendCustomAction(String action, in Bundle args); + MediaMetadata getMetadata(); + PlaybackState getPlaybackState(); + ParceledListSlice getQueue(); + CharSequence getQueueTitle(); + Bundle getExtras(); + int getRatingType(); } diff --git a/media/java/android/media/session/ISessionControllerCallback.aidl b/media/java/android/media/session/ISessionControllerCallback.aidl index 9517c088bcf3..cf3176706d7e 100644 --- a/media/java/android/media/session/ISessionControllerCallback.aidl +++ b/media/java/android/media/session/ISessionControllerCallback.aidl @@ -36,6 +36,4 @@ oneway interface ISessionControllerCallback { void onQueueTitleChanged(CharSequence title); void onExtrasChanged(in Bundle extras); void onVolumeInfoChanged(in ParcelableVolumeInfo info); - void onRepeatModeChanged(int repeatMode); - void onShuffleModeChanged(boolean shuffleMode); } diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java index bab2af25dde5..622900f5c7f9 100644 --- a/media/java/android/media/session/MediaController.java +++ b/media/java/android/media/session/MediaController.java @@ -23,7 +23,6 @@ import android.content.Context; import android.content.pm.ParceledListSlice; import android.media.AudioAttributes; import android.media.AudioManager; -import android.media.MediaDescription; import android.media.MediaMetadata; import android.media.Rating; import android.media.VolumeProvider; @@ -39,7 +38,6 @@ import android.util.Log; import android.view.KeyEvent; import java.lang.ref.WeakReference; -import java.lang.UnsupportedOperationException; import java.util.ArrayList; import java.util.List; @@ -65,9 +63,7 @@ public final class MediaController { private static final int MSG_UPDATE_QUEUE = 5; private static final int MSG_UPDATE_QUEUE_TITLE = 6; private static final int MSG_UPDATE_EXTRAS = 7; - private static final int MSG_UPDATE_REPEAT_MODE = 8; - private static final int MSG_UPDATE_SHUFFLE_MODE = 9; - private static final int MSG_DESTROYED = 10; + private static final int MSG_DESTROYED = 8; private final ISessionController mSessionBinder; @@ -113,7 +109,8 @@ public final class MediaController { } /** - * Get a {@link TransportControls} instance to send transport actions to this session. + * Get a {@link TransportControls} instance to send transport actions to + * the associated session. * * @return A transport controls instance. */ @@ -152,7 +149,7 @@ public final class MediaController { try { return mSessionBinder.getPlaybackState(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getPlaybackState", e); + Log.wtf(TAG, "Error calling getPlaybackState.", e); return null; } } @@ -166,7 +163,7 @@ public final class MediaController { try { return mSessionBinder.getMetadata(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getMetadata", e); + Log.wtf(TAG, "Error calling getMetadata.", e); return null; } } @@ -184,103 +181,12 @@ public final class MediaController { return queue.getList(); } } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getQueue", e); + Log.wtf(TAG, "Error calling getQueue.", e); } return null; } /** - * Add a queue item from the given {@code description} at the end of the play queue - * of this session. Not all sessions may support this. - * - * @param description The {@link MediaDescription} for creating the - * {@link MediaSession.QueueItem} to be inserted. - * @throws UnsupportedOperationException If this session doesn't support this. - * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS - */ - public void addQueueItem(MediaDescription description) { - try { - long flags = mSessionBinder.getFlags(); - if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) { - throw new UnsupportedOperationException( - "This session doesn't support queue management operations"); - } - mSessionBinder.addQueueItem(description); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling addQueueItem", e); - } - } - - /** - * Add a queue item from the given {@code description} at the specified position - * in the play queue of this session. Shifts the queue item currently at that position - * (if any) and any subsequent queue items to the right (adds one to their indices). - * Not all sessions may support this. - * - * @param description The {@link MediaDescription} for creating the - * {@link MediaSession.QueueItem} to be inserted. - * @param index The index at which the created {@link MediaSession.QueueItem} is to be inserted. - * @throws UnsupportedOperationException If this session doesn't support this. - * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS - */ - public void addQueueItem(MediaDescription description, int index) { - try { - long flags = mSessionBinder.getFlags(); - if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) { - throw new UnsupportedOperationException( - "This session doesn't support queue management operations"); - } - mSessionBinder.addQueueItemAt(description, index); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling addQueueItemAt", e); - } - } - - /** - * Remove the first occurrence of the specified {@link MediaSession.QueueItem} - * with the given {@link MediaDescription description} in the play queue of the associated - * session. Not all sessions may support this. - * - * @param description The {@link MediaDescription} for denoting the - * {@link MediaSession.QueueItem} to be removed. - * @throws UnsupportedOperationException If this session doesn't support this. - * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS - */ - public void removeQueueItem(MediaDescription description) { - try { - long flags = mSessionBinder.getFlags(); - if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) { - throw new UnsupportedOperationException( - "This session doesn't support queue management operations"); - } - mSessionBinder.removeQueueItem(description); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling removeQueueItem", e); - } - } - - /** - * Remove an queue item at the specified position in the play queue - * of this session. Not all sessions may support this. - * - * @param index The index of the element to be removed. - * @throws UnsupportedOperationException If this session doesn't support this. - * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS - */ - public void removeQueueItemAt(int index) { - try { - long flags = mSessionBinder.getFlags(); - if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) { - throw new UnsupportedOperationException( - "This session doesn't support queue management operations"); - } - mSessionBinder.removeQueueItemAt(index); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling removeQueueItemAt", e); - } - } - - /** * Get the queue title for this session. */ public @Nullable CharSequence getQueueTitle() { @@ -322,41 +228,12 @@ public final class MediaController { try { return mSessionBinder.getRatingType(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getRatingType", e); + Log.wtf(TAG, "Error calling getRatingType.", e); return Rating.RATING_NONE; } } /** - * Get the repeat mode for this session. - * - * @return The latest repeat mode set to the session, or - * {@link PlaybackState#REPEAT_MODE_NONE} if not set. - */ - public int getRepeatMode() { - try { - return mSessionBinder.getRepeatMode(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getRepeatMode", e); - return PlaybackState.REPEAT_MODE_NONE; - } - } - - /** - * Return whether the shuffle mode is enabled for this session. - * - * @return {@code true} if the shuffle mode is enabled, {@code false} if disabled or not set. - */ - public boolean isShuffleModeEnabled() { - try { - return mSessionBinder.isShuffleModeEnabled(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling isShuffleModeEnabled", e); - return false; - } - } - - /** * Get the flags for this session. Flags are defined in {@link MediaSession}. * * @return The current set of flags for the session. @@ -365,7 +242,7 @@ public final class MediaController { try { return mSessionBinder.getFlags(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getFlags", e); + Log.wtf(TAG, "Error calling getFlags.", e); } return 0; } @@ -382,7 +259,7 @@ public final class MediaController { result.maxVolume, result.currentVolume); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getAudioInfo", e); + Log.wtf(TAG, "Error calling getAudioInfo.", e); } return null; } @@ -397,7 +274,7 @@ public final class MediaController { try { return mSessionBinder.getLaunchPendingIntent(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getPendingIntent", e); + Log.wtf(TAG, "Error calling getPendingIntent.", e); } return null; } @@ -426,7 +303,7 @@ public final class MediaController { try { mSessionBinder.setVolumeTo(value, flags, mContext.getPackageName()); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling setVolumeTo", e); + Log.wtf(TAG, "Error calling setVolumeTo.", e); } } @@ -447,7 +324,7 @@ public final class MediaController { try { mSessionBinder.adjustVolume(direction, flags, mContext.getPackageName()); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling adjustVolumeBy", e); + Log.wtf(TAG, "Error calling adjustVolumeBy.", e); } } @@ -513,7 +390,7 @@ public final class MediaController { try { mSessionBinder.sendCommand(command, args, cb); } catch (RemoteException e) { - Log.d(TAG, "Dead object in sendCommand", e); + Log.d(TAG, "Dead object in sendCommand.", e); } } @@ -527,7 +404,7 @@ public final class MediaController { try { mPackageName = mSessionBinder.getPackageName(); } catch (RemoteException e) { - Log.d(TAG, "Dead object in getPackageName", e); + Log.d(TAG, "Dead object in getPackageName.", e); } } return mPackageName; @@ -544,7 +421,7 @@ public final class MediaController { try { mTag = mSessionBinder.getTag(); } catch (RemoteException e) { - Log.d(TAG, "Dead object in getTag", e); + Log.d(TAG, "Dead object in getTag.", e); } } return mTag; @@ -702,25 +579,6 @@ public final class MediaController { */ public void onAudioInfoChanged(PlaybackInfo info) { } - - /** - * Override to handle changes to the repeat mode. - * - * @param repeatMode The repeat mode. It should be one of followings: - * {@link PlaybackState#REPEAT_MODE_NONE}, - * {@link PlaybackState#REPEAT_MODE_ONE}, - * {@link PlaybackState#REPEAT_MODE_ALL} - */ - public void onRepeatModeChanged(@PlaybackState.RepeatMode int repeatMode) { - } - - /** - * Override to handle changes to the shuffle mode. - * - * @param enabled {@code true} if the shuffle mode is enabled, {@code false} otherwise. - */ - public void onShuffleModeChanged(boolean enabled) { - } } /** @@ -744,7 +602,7 @@ public final class MediaController { try { mSessionBinder.prepare(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling prepare", e); + Log.wtf(TAG, "Error calling prepare.", e); } } @@ -763,12 +621,12 @@ public final class MediaController { public void prepareFromMediaId(String mediaId, Bundle extras) { if (TextUtils.isEmpty(mediaId)) { throw new IllegalArgumentException( - "You must specify a non-empty String for prepareFromMediaId"); + "You must specify a non-empty String for prepareFromMediaId."); } try { mSessionBinder.prepareFromMediaId(mediaId, extras); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling prepare(" + mediaId + ")", e); + Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e); } } @@ -794,7 +652,7 @@ public final class MediaController { try { mSessionBinder.prepareFromSearch(query, extras); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling prepare(" + query + ")", e); + Log.wtf(TAG, "Error calling prepare(" + query + ").", e); } } @@ -813,12 +671,12 @@ public final class MediaController { public void prepareFromUri(Uri uri, Bundle extras) { if (uri == null || Uri.EMPTY.equals(uri)) { throw new IllegalArgumentException( - "You must specify a non-empty Uri for prepareFromUri"); + "You must specify a non-empty Uri for prepareFromUri."); } try { mSessionBinder.prepareFromUri(uri, extras); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling prepare(" + uri + ")", e); + Log.wtf(TAG, "Error calling prepare(" + uri + ").", e); } } @@ -829,7 +687,7 @@ public final class MediaController { try { mSessionBinder.play(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling play", e); + Log.wtf(TAG, "Error calling play.", e); } } @@ -843,12 +701,12 @@ public final class MediaController { public void playFromMediaId(String mediaId, Bundle extras) { if (TextUtils.isEmpty(mediaId)) { throw new IllegalArgumentException( - "You must specify a non-empty String for playFromMediaId"); + "You must specify a non-empty String for playFromMediaId."); } try { mSessionBinder.playFromMediaId(mediaId, extras); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling play(" + mediaId + ")", e); + Log.wtf(TAG, "Error calling play(" + mediaId + ").", e); } } @@ -870,7 +728,7 @@ public final class MediaController { try { mSessionBinder.playFromSearch(query, extras); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling play(" + query + ")", e); + Log.wtf(TAG, "Error calling play(" + query + ").", e); } } @@ -884,12 +742,12 @@ public final class MediaController { public void playFromUri(Uri uri, Bundle extras) { if (uri == null || Uri.EMPTY.equals(uri)) { throw new IllegalArgumentException( - "You must specify a non-empty Uri for playFromUri"); + "You must specify a non-empty Uri for playFromUri."); } try { mSessionBinder.playFromUri(uri, extras); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling play(" + uri + ")", e); + Log.wtf(TAG, "Error calling play(" + uri + ").", e); } } @@ -901,7 +759,7 @@ public final class MediaController { try { mSessionBinder.skipToQueueItem(id); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling skipToItem(" + id + ")", e); + Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e); } } @@ -913,7 +771,7 @@ public final class MediaController { try { mSessionBinder.pause(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling pause", e); + Log.wtf(TAG, "Error calling pause.", e); } } @@ -925,7 +783,7 @@ public final class MediaController { try { mSessionBinder.stop(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling stop", e); + Log.wtf(TAG, "Error calling stop.", e); } } @@ -938,7 +796,7 @@ public final class MediaController { try { mSessionBinder.seekTo(pos); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling seekTo", e); + Log.wtf(TAG, "Error calling seekTo.", e); } } @@ -950,7 +808,7 @@ public final class MediaController { try { mSessionBinder.fastForward(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling fastForward", e); + Log.wtf(TAG, "Error calling fastForward.", e); } } @@ -961,7 +819,7 @@ public final class MediaController { try { mSessionBinder.next(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling next", e); + Log.wtf(TAG, "Error calling next.", e); } } @@ -973,7 +831,7 @@ public final class MediaController { try { mSessionBinder.rewind(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling rewind", e); + Log.wtf(TAG, "Error calling rewind.", e); } } @@ -984,7 +842,7 @@ public final class MediaController { try { mSessionBinder.previous(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling previous", e); + Log.wtf(TAG, "Error calling previous.", e); } } @@ -999,36 +857,7 @@ public final class MediaController { try { mSessionBinder.rate(rating); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling rate", e); - } - } - - /** - * Set the repeat mode for this session. - * - * @param repeatMode The repeat mode. Must be one of the followings: - * {@link PlaybackState#REPEAT_MODE_NONE}, - * {@link PlaybackState#REPEAT_MODE_ONE}, - * {@link PlaybackState#REPEAT_MODE_ALL} - */ - public void setRepeatMode(@PlaybackState.RepeatMode int repeatMode) { - try { - mSessionBinder.repeatMode(repeatMode); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling setRepeatMode", e); - } - } - - /** - * Set the shuffle mode for this session. - * - * @param enabled {@code true} to enable the shuffle mode, {@code false} to disable. - */ - public void setShuffleModeEnabled(boolean enabled) { - try { - mSessionBinder.shuffleMode(enabled); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling shuffleMode", e); + Log.wtf(TAG, "Error calling rate.", e); } } @@ -1042,7 +871,7 @@ public final class MediaController { public void sendCustomAction(@NonNull PlaybackState.CustomAction customAction, @Nullable Bundle args) { if (customAction == null) { - throw new IllegalArgumentException("CustomAction cannot be null"); + throw new IllegalArgumentException("CustomAction cannot be null."); } sendCustomAction(customAction.getAction(), args); } @@ -1058,12 +887,12 @@ public final class MediaController { */ public void sendCustomAction(@NonNull String action, @Nullable Bundle args) { if (TextUtils.isEmpty(action)) { - throw new IllegalArgumentException("CustomAction cannot be null"); + throw new IllegalArgumentException("CustomAction cannot be null."); } try { mSessionBinder.sendCustomAction(action, args); } catch (RemoteException e) { - Log.d(TAG, "Dead object in sendCustomAction", e); + Log.d(TAG, "Dead object in sendCustomAction.", e); } } } @@ -1233,21 +1062,6 @@ public final class MediaController { } } - @Override - public void onRepeatModeChanged(int repeatMode) { - MediaController controller = mController.get(); - if (controller != null) { - controller.postMessage(MSG_UPDATE_REPEAT_MODE, repeatMode, null); - } - } - - @Override - public void onShuffleModeChanged(boolean enabled) { - MediaController controller = mController.get(); - if (controller != null) { - controller.postMessage(MSG_UPDATE_SHUFFLE_MODE, enabled, null); - } - } } private final static class MessageHandler extends Handler { @@ -1286,12 +1100,6 @@ public final class MediaController { case MSG_UPDATE_VOLUME: mCallback.onAudioInfoChanged((PlaybackInfo) msg.obj); break; - case MSG_UPDATE_REPEAT_MODE: - mCallback.onRepeatModeChanged((int) msg.obj); - break; - case MSG_UPDATE_SHUFFLE_MODE: - mCallback.onShuffleModeChanged((boolean) msg.obj); - break; case MSG_DESTROYED: mCallback.onSessionDestroyed(); break; diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java index f10f4427d6f0..dfd2bb35d6ea 100644 --- a/media/java/android/media/session/MediaSession.java +++ b/media/java/android/media/session/MediaSession.java @@ -93,12 +93,6 @@ public final class MediaSession { public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 1 << 1; /** - * Set this flag on the session to indicate that it handles queue - * management commands through its {@link Callback}. - */ - public static final int FLAG_HANDLES_QUEUE_COMMANDS = 1 << 2; - - /** * System only flag for a session that needs to have priority over all other * sessions. This flag ensures this session will receive media button events * regardless of the current ordering in the system. @@ -112,7 +106,6 @@ public final class MediaSession { @IntDef(flag = true, value = { FLAG_HANDLES_MEDIA_BUTTONS, FLAG_HANDLES_TRANSPORT_CONTROLS, - FLAG_HANDLES_QUEUE_COMMANDS, FLAG_EXCLUSIVE_GLOBAL_PRIORITY }) public @interface SessionFlags { } @@ -493,41 +486,6 @@ public final class MediaSession { } /** - * Set the repeat mode for this session. - * <p> - * Note that if this method is not called before, {@link MediaController#getRepeatMode} - * will return {@link PlaybackState#REPEAT_MODE_NONE}. - * - * @param repeatMode The repeat mode. Must be one of the followings: - * {@link PlaybackState#REPEAT_MODE_NONE}, - * {@link PlaybackState#REPEAT_MODE_ONE}, - * {@link PlaybackState#REPEAT_MODE_ALL} - */ - public void setRepeatMode(@PlaybackState.RepeatMode int repeatMode) { - try { - mBinder.setRepeatMode(repeatMode); - } catch (RemoteException e) { - Log.e(TAG, "Error in setRepeatMode.", e); - } - } - - /** - * Set the shuffle mode for this session. - * <p> - * Note that if this method is not called before, {@link MediaController#isShuffleModeEnabled} - * will return {@code false}. - * - * @param enabled {@code true} to enable the shuffle mode, {@code false} to disable. - */ - public void setShuffleModeEnabled(boolean enabled) { - try { - mBinder.setShuffleModeEnabled(enabled); - } catch (RemoteException e) { - Log.e(TAG, "Error in setShuffleModeEnabled.", e); - } - } - - /** * Set some extras that can be associated with the {@link MediaSession}. No assumptions should * be made as to how a {@link MediaController} will handle these extras. * Keys should be fully qualified (e.g. com.example.MY_EXTRA) to avoid conflicts. @@ -646,34 +604,10 @@ public final class MediaSession { postToCallback(CallbackMessageHandler.MSG_RATE, rating); } - private void dispatchRepeatMode(int repeatMode) { - postToCallback(CallbackMessageHandler.MSG_REPEAT_MODE, repeatMode); - } - - private void dispatchShuffleMode(boolean enabled) { - postToCallback(CallbackMessageHandler.MSG_SHUFFLE_MODE, enabled); - } - private void dispatchCustomAction(String action, Bundle args) { postToCallback(CallbackMessageHandler.MSG_CUSTOM_ACTION, action, args); } - private void dispatchAddQueueItem(MediaDescription description) { - postToCallback(CallbackMessageHandler.MSG_ADD_QUEUE_ITEM, description); - } - - private void dispatchAddQueueItem(MediaDescription description, int index) { - postToCallback(CallbackMessageHandler.MSG_ADD_QUEUE_ITEM_AT, description, index); - } - - private void dispatchRemoveQueueItem(MediaDescription description) { - postToCallback(CallbackMessageHandler.MSG_REMOVE_QUEUE_ITEM, description); - } - - private void dispatchRemoveQueueItemAt(int index) { - postToCallback(CallbackMessageHandler.MSG_REMOVE_QUEUE_ITEM_AT, index); - } - private void dispatchMediaButton(Intent mediaButtonIntent) { postToCallback(CallbackMessageHandler.MSG_MEDIA_BUTTON, mediaButtonIntent); } @@ -695,22 +629,10 @@ public final class MediaSession { postToCallback(CallbackMessageHandler.MSG_COMMAND, cmd); } - private void postToCallback(int what, int arg1) { - postToCallback(what, null, arg1); - } - private void postToCallback(int what, Object obj) { postToCallback(what, obj, null); } - private void postToCallback(int what, Object obj, int arg1) { - synchronized (mLock) { - if (mCallback != null) { - mCallback.post(what, obj, arg1); - } - } - } - private void postToCallback(int what, Object obj, Bundle extras) { synchronized (mLock) { if (mCallback != null) { @@ -1048,33 +970,6 @@ public final class MediaSession { } /** - * Override to handle the setting of the repeat mode. - * <p> - * You should call {@link #setRepeatMode} before end of this method in order to notify - * the change to the {@link MediaController}, or {@link MediaController#getRepeatMode} - * could return an invalid value. - * - * @param repeatMode The repeat mode which is one of followings: - * {@link PlaybackState#REPEAT_MODE_NONE}, - * {@link PlaybackState#REPEAT_MODE_ONE}, - * {@link PlaybackState#REPEAT_MODE_ALL} - */ - public void onSetRepeatMode(@PlaybackState.RepeatMode int repeatMode) { - } - - /** - * Override to handle the setting of the shuffle mode. - * <p> - * You should call {@link #setShuffleModeEnabled} before the end of this method in order to - * notify the change to the {@link MediaController}, or - * {@link MediaController#isShuffleModeEnabled} could return an invalid value. - * - * @param enabled true when the shuffle mode is enabled, false otherwise. - */ - public void onSetShuffleModeEnabled(boolean enabled) { - } - - /** * Called when a {@link MediaController} wants a {@link PlaybackState.CustomAction} to be * performed. * @@ -1084,47 +979,6 @@ public final class MediaSession { */ public void onCustomAction(@NonNull String action, @Nullable Bundle extras) { } - - /** - * Called when a {@link MediaController} wants to add a {@link QueueItem} with the given - * {@link MediaDescription description} at the end of the play queue. - * - * @param description The {@link MediaDescription} for creating the {@link QueueItem} to be - * inserted. - */ - public void onAddQueueItem(MediaDescription description) { - } - - /** - * Called when a {@link MediaController} wants to add a {@link QueueItem} with the given - * {@link MediaDescription description} at the specified position in the play queue. - * - * @param description The {@link MediaDescription} for creating the {@link QueueItem} to be - * inserted. - * @param index The index at which the created {@link QueueItem} is to be inserted. - */ - public void onAddQueueItem(MediaDescription description, int index) { - } - - /** - * Called when a {@link MediaController} wants to remove the first occurrence of the - * specified {@link QueueItem} with the given {@link MediaDescription description} - * in the play queue. - * - * @param description The {@link MediaDescription} for denoting the {@link QueueItem} to be - * removed. - */ - public void onRemoveQueueItem(MediaDescription description) { - } - - /** - * Called when a {@link MediaController} wants to remove a {@link QueueItem} at the - * specified position in the play queue. - * - * @param index The index of the element to be removed. - */ - public void onRemoveQueueItemAt(int index) { - } } /** @@ -1297,22 +1151,6 @@ public final class MediaSession { } @Override - public void onRepeatMode(int repeatMode) { - MediaSession session = mMediaSession.get(); - if (session != null) { - session.dispatchRepeatMode(repeatMode); - } - } - - @Override - public void onShuffleMode(boolean enabled) { - MediaSession session = mMediaSession.get(); - if (session != null) { - session.dispatchShuffleMode(enabled); - } - } - - @Override public void onCustomAction(String action, Bundle args) { MediaSession session = mMediaSession.get(); if (session != null) { @@ -1321,38 +1159,6 @@ public final class MediaSession { } @Override - public void onAddQueueItem(MediaDescription description) { - MediaSession session = mMediaSession.get(); - if (session != null) { - session.dispatchAddQueueItem(description); - } - } - - @Override - public void onAddQueueItemAt(MediaDescription description, int index) { - MediaSession session = mMediaSession.get(); - if (session != null) { - session.dispatchAddQueueItem(description, index); - } - } - - @Override - public void onRemoveQueueItem(MediaDescription description) { - MediaSession session = mMediaSession.get(); - if (session != null) { - session.dispatchRemoveQueueItem(description); - } - } - - @Override - public void onRemoveQueueItemAt(int index) { - MediaSession session = mMediaSession.get(); - if (session != null) { - session.dispatchRemoveQueueItemAt(index); - } - } - - @Override public void onAdjustVolume(int direction) { MediaSession session = mMediaSession.get(); if (session != null) { @@ -1376,7 +1182,7 @@ public final class MediaSession { */ public static final class QueueItem implements Parcelable { /** - * This id is reserved. No items can be explicitly asigned this id. + * This id is reserved. No items can be explicitly assigned this id. */ public static final int UNKNOWN_ID = -1; @@ -1485,15 +1291,9 @@ public final class MediaSession { private static final int MSG_REWIND = 17; private static final int MSG_SEEK_TO = 18; private static final int MSG_RATE = 19; - private static final int MSG_REPEAT_MODE = 20; - private static final int MSG_SHUFFLE_MODE = 21; - private static final int MSG_CUSTOM_ACTION = 22; - private static final int MSG_ADJUST_VOLUME = 23; - private static final int MSG_SET_VOLUME = 24; - private static final int MSG_ADD_QUEUE_ITEM = 25; - private static final int MSG_ADD_QUEUE_ITEM_AT = 26; - private static final int MSG_REMOVE_QUEUE_ITEM = 27; - private static final int MSG_REMOVE_QUEUE_ITEM_AT = 28; + private static final int MSG_CUSTOM_ACTION = 20; + private static final int MSG_ADJUST_VOLUME = 21; + private static final int MSG_SET_VOLUME = 22; private MediaSession.Callback mCallback; @@ -1582,33 +1382,15 @@ public final class MediaSession { case MSG_RATE: mCallback.onSetRating((Rating) msg.obj); break; - case MSG_REPEAT_MODE: - mCallback.onSetRepeatMode(msg.arg1); - break; - case MSG_SHUFFLE_MODE: - mCallback.onSetShuffleModeEnabled((boolean) msg.obj); - break; case MSG_CUSTOM_ACTION: mCallback.onCustomAction((String) msg.obj, msg.getData()); break; - case MSG_ADD_QUEUE_ITEM: - mCallback.onAddQueueItem((MediaDescription) msg.obj); - break; - case MSG_ADD_QUEUE_ITEM_AT: - mCallback.onAddQueueItem((MediaDescription) msg.obj, msg.arg1); - break; - case MSG_REMOVE_QUEUE_ITEM: - mCallback.onRemoveQueueItem((MediaDescription) msg.obj); - break; - case MSG_REMOVE_QUEUE_ITEM_AT: - mCallback.onRemoveQueueItemAt(msg.arg1); - break; case MSG_ADJUST_VOLUME: synchronized (mLock) { vp = mVolumeProvider; } if (vp != null) { - vp.onAdjustVolume(msg.arg1); + vp.onAdjustVolume((int) msg.obj); } break; case MSG_SET_VOLUME: @@ -1616,7 +1398,7 @@ public final class MediaSession { vp = mVolumeProvider; } if (vp != null) { - vp.onSetVolumeTo(msg.arg1); + vp.onSetVolumeTo((int) msg.obj); } break; } diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java index 1ea61093d869..8283c8b967e8 100644 --- a/media/java/android/media/session/PlaybackState.java +++ b/media/java/android/media/session/PlaybackState.java @@ -45,8 +45,7 @@ public final class PlaybackState implements Parcelable { ACTION_SKIP_TO_PREVIOUS, ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_SET_RATING, ACTION_SEEK_TO, ACTION_PLAY_PAUSE, ACTION_PLAY_FROM_MEDIA_ID, ACTION_PLAY_FROM_SEARCH, ACTION_SKIP_TO_QUEUE_ITEM, ACTION_PLAY_FROM_URI, ACTION_PREPARE, - ACTION_PREPARE_FROM_MEDIA_ID, ACTION_PREPARE_FROM_SEARCH, ACTION_PREPARE_FROM_URI, - ACTION_SET_REPEAT_MODE, ACTION_SET_SHUFFLE_MODE_ENABLED}) + ACTION_PREPARE_FROM_MEDIA_ID, ACTION_PREPARE_FROM_SEARCH, ACTION_PREPARE_FROM_URI}) @Retention(RetentionPolicy.SOURCE) public @interface Actions {} @@ -177,20 +176,6 @@ public final class PlaybackState implements Parcelable { public static final long ACTION_PREPARE_FROM_URI = 1 << 17; /** - * Indicates this session supports the set repeat mode command. - * - * @see Builder#setActions(long) - */ - public static final long ACTION_SET_REPEAT_MODE = 1 << 18; - - /** - * Indicates this session supports the set shuffle mode enabled command. - * - * @see Builder#setActions(long) - */ - public static final long ACTION_SET_SHUFFLE_MODE_ENABLED = 1 << 19; - - /** * @hide */ @IntDef({STATE_NONE, STATE_STOPPED, STATE_PAUSED, STATE_PLAYING, STATE_FAST_FORWARDING, @@ -296,30 +281,6 @@ public final class PlaybackState implements Parcelable { */ public final static long PLAYBACK_POSITION_UNKNOWN = -1; - /** - * @hide - */ - @IntDef({REPEAT_MODE_NONE, REPEAT_MODE_ONE, REPEAT_MODE_ALL}) - @Retention(RetentionPolicy.SOURCE) - public @interface RepeatMode {} - /** - * Use this value with {@link MediaController.TransportControls#setRepeatMode} - * to indicate that the playback will be stopped at the end of the playing media list. - */ - public final static int REPEAT_MODE_NONE = 0; - - /** - * Use this value with {@link MediaController.TransportControls#setRepeatMode} - * to indicate that the playback of the current playing media item will be repeated. - */ - public final static int REPEAT_MODE_ONE = 1; - - /** - * Use this value with {@link MediaController.TransportControls#setRepeatMode} - * to indicate that the playback of the playing media list will be repeated. - */ - public final static int REPEAT_MODE_ALL = 2; - private final int mState; private final long mPosition; private final long mBufferedPosition; @@ -466,8 +427,6 @@ public final class PlaybackState implements Parcelable { * <li> {@link PlaybackState#ACTION_PREPARE_FROM_MEDIA_ID}</li> * <li> {@link PlaybackState#ACTION_PREPARE_FROM_SEARCH}</li> * <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li> - * <li> {@link PlaybackState#ACTION_SET_REPEAT_MODE}</li> - * <li> {@link PlaybackState#ACTION_SET_SHUFFLE_MODE_ENABLED}</li> * </ul> */ @Actions @@ -1002,8 +961,6 @@ public final class PlaybackState implements Parcelable { * <li> {@link PlaybackState#ACTION_PREPARE_FROM_MEDIA_ID}</li> * <li> {@link PlaybackState#ACTION_PREPARE_FROM_SEARCH}</li> * <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li> - * <li> {@link PlaybackState#ACTION_SET_REPEAT_MODE}</li> - * <li> {@link PlaybackState#ACTION_SET_SHUFFLE_MODE_ENABLED}</li> * </ul> * * @param actions The set of actions allowed. diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java index 1b55380ed5a9..71f9ba257aa3 100644 --- a/media/java/android/media/tv/TvContract.java +++ b/media/java/android/media/tv/TvContract.java @@ -436,6 +436,14 @@ public final class TvContract { public static final String PARAM_CANONICAL_GENRE = "canonical_genre"; /** + * A query, update or delete URI parameter that allows the caller to operate only on preview or + * non-preview channels. If set to "true", the operation affects the rows for preview channels + * only. If set to "false", the operation affects the rows for non-preview channels only. + * @hide + */ + public static final String PARAM_PREVIEW = "preview"; + + /** * Builds an ID that uniquely identifies a TV input service. * * @param name The {@link ComponentName} of the TV input service to build ID for. diff --git a/media/java/android/service/media/IMediaBrowserService.aidl b/media/java/android/service/media/IMediaBrowserService.aidl index e95154ff4540..84f41f6c3afe 100644 --- a/media/java/android/service/media/IMediaBrowserService.aidl +++ b/media/java/android/service/media/IMediaBrowserService.aidl @@ -19,10 +19,8 @@ oneway interface IMediaBrowserService { void addSubscriptionDeprecated(String uri, IMediaBrowserServiceCallbacks callbacks); void removeSubscriptionDeprecated(String uri, IMediaBrowserServiceCallbacks callbacks); - void getMediaItem(String uri, in ResultReceiver cb, IMediaBrowserServiceCallbacks callbacks); - void search(String query, in Bundle extras, in ResultReceiver cb, - IMediaBrowserServiceCallbacks callbacks); + void getMediaItem(String uri, in ResultReceiver cb, IMediaBrowserServiceCallbacks callbacks); void addSubscription(String uri, in IBinder token, in Bundle options, IMediaBrowserServiceCallbacks callbacks); void removeSubscription(String uri, in IBinder token, IMediaBrowserServiceCallbacks callbacks); diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java index d372efbea5ca..b52906ddd1ae 100644 --- a/media/java/android/service/media/MediaBrowserService.java +++ b/media/java/android/service/media/MediaBrowserService.java @@ -89,15 +89,8 @@ public abstract class MediaBrowserService extends Service { */ public static final String KEY_MEDIA_ITEM = "media_item"; - /** - * A key for passing the list of MediaItems to the ResultReceiver in search. - * @hide - */ - public static final String KEY_SEARCH_RESULTS = "search_results"; - private static final int RESULT_FLAG_OPTION_NOT_HANDLED = 1 << 0; private static final int RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED = 1 << 1; - private static final int RESULT_FLAG_ON_SEARCH_NOT_IMPLEMENTED = 1 << 2; private static final int RESULT_ERROR = -1; private static final int RESULT_OK = 0; @@ -105,7 +98,7 @@ public abstract class MediaBrowserService extends Service { /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(flag=true, value = { RESULT_FLAG_OPTION_NOT_HANDLED, - RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED, RESULT_FLAG_ON_SEARCH_NOT_IMPLEMENTED }) + RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED }) private @interface ResultFlags { } private final ArrayMap<IBinder, ConnectionRecord> mConnections = new ArrayMap<>(); @@ -137,7 +130,6 @@ public abstract class MediaBrowserService extends Service { * * @see #onLoadChildren * @see #onLoadItem - * @see #onSearch */ public class Result<T> { private Object mDebug; @@ -330,23 +322,6 @@ public abstract class MediaBrowserService extends Service { } }); } - - @Override - public void search(final String query, Bundle extras, ResultReceiver receiver, - final IMediaBrowserServiceCallbacks callbacks) { - mHandler.post(new Runnable() { - @Override - public void run() { - final IBinder b = callbacks.asBinder(); - ConnectionRecord connection = mConnections.get(b); - if (connection == null) { - Log.w(TAG, "search for callback that isn't registered query=" + query); - return; - } - performSearch(query, extras, connection, receiver); - } - }); - } } @Override @@ -472,32 +447,6 @@ public abstract class MediaBrowserService extends Service { } /** - * Called to get the search result. - * <p> - * Implementations must call {@link Result#sendResult result.sendResult}. If - * the search will be an expensive operation {@link Result#detach result.detach} - * may be called before returning from this function, and then {@link Result#sendResult - * result.sendResult} called when the search has been completed. - * </p><p> - * In case there are no search results, call {@link Result#sendResult} with an empty list. - * In case there are some errors happened, call {@link Result#sendResult result.sendResult} - * with {@code null}, which will invoke {@link MediaBrowser.SearchCallback#onError}. - * </p><p> - * The default implementation will invoke {@link MediaBrowser.SearchCallback#onError}. - * </p> - * - * @param query The search query sent from the media browser. It contains keywords separated - * by space. - * @param extras The bundle of service-specific arguments sent from the media browser. - * @param result The {@link Result} to send the search result. - */ - public void onSearch(@NonNull String query, Bundle extras, - Result<List<MediaBrowser.MediaItem>> result) { - result.setFlags(RESULT_FLAG_ON_SEARCH_NOT_IMPLEMENTED); - result.sendResult(null); - } - - /** * Call to set the media session. * <p> * This should be called as soon as possible during the service's startup. @@ -545,16 +494,16 @@ public abstract class MediaBrowserService extends Service { * media browser service when connecting and retrieving the root id for browsing, or null if * none. The contents of this bundle may affect the information returned when browsing. * - * @throws IllegalStateException If this method is called outside of {@link #onLoadChildren}, - * {@link #onLoadItem} or {@link #onSearch}. + * @throws IllegalStateException If this method is called outside of {@link #onLoadChildren} or + * {@link #onLoadItem}. * @see MediaBrowserService.BrowserRoot#EXTRA_RECENT * @see MediaBrowserService.BrowserRoot#EXTRA_OFFLINE * @see MediaBrowserService.BrowserRoot#EXTRA_SUGGESTED */ public final Bundle getBrowserRootHints() { if (mCurConnection == null) { - throw new IllegalStateException("This should be called inside of onLoadChildren," - + " onLoadItem or onSearch methods"); + throw new IllegalStateException("This should be called inside of onLoadChildren or" + + " onLoadItem methods"); } return mCurConnection.rootHints == null ? null : new Bundle(mCurConnection.rootHints); } @@ -771,34 +720,6 @@ public abstract class MediaBrowserService extends Service { } } - private void performSearch(String query, Bundle extras, final ConnectionRecord connection, - final ResultReceiver receiver) { - final Result<List<MediaBrowser.MediaItem>> result = - new Result<List<MediaBrowser.MediaItem>>(query) { - @Override - void onResultSent(List<MediaBrowser.MediaItem> items, @ResultFlags int flag) { - if ((flag & RESULT_FLAG_ON_SEARCH_NOT_IMPLEMENTED) != 0 - || items == null) { - receiver.send(RESULT_ERROR, null); - return; - } - Bundle bundle = new Bundle(); - bundle.putParcelableArray(KEY_SEARCH_RESULTS, - items.toArray(new MediaBrowser.MediaItem[0])); - receiver.send(RESULT_OK, bundle); - } - }; - - mCurConnection = connection; - onSearch(query, extras, result); - mCurConnection = null; - - if (!result.isDone()) { - throw new IllegalStateException("onSearch must call detach() or sendResult()" - + " before returning for query=" + query); - } - } - /** * Contains information that the browser service needs to send to the client * when first connected. diff --git a/native/android/sensor.cpp b/native/android/sensor.cpp index ae16949791bc..8e5821024cee 100644 --- a/native/android/sensor.cpp +++ b/native/android/sensor.cpp @@ -17,7 +17,6 @@ #define LOG_TAG "sensor" #include <utils/Log.h> -#include <android/hardware_buffer.h> #include <android/looper.h> #include <android/sensor.h> #include <android/sharedmem.h> @@ -28,6 +27,7 @@ #include <utils/Looper.h> #include <utils/RefBase.h> #include <utils/Timers.h> +#include <vndk/hardware_buffer.h> #include <poll.h> diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java index 8a86c13abb7d..10f3b6341e42 100644 --- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java +++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java @@ -29,6 +29,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.IPackageStatsObserver; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageStats; import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; @@ -52,6 +53,7 @@ import com.android.internal.util.ArrayUtils; import com.android.settingslib.R; import java.io.File; +import java.io.IOException; import java.text.Collator; import java.text.Normalizer; import java.text.Normalizer.Form; @@ -61,6 +63,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Objects; +import java.util.UUID; import java.util.regex.Pattern; /** @@ -114,7 +117,7 @@ public class ApplicationsState { final ArrayList<AppEntry> mAppEntries = new ArrayList<AppEntry>(); List<ApplicationInfo> mApplications = new ArrayList<ApplicationInfo>(); long mCurId = 1; - String mCurComputingSizeUuid; + UUID mCurComputingSizeUuid; String mCurComputingSizePkg; int mCurComputingSizeUserId; boolean mSessionsChanged; @@ -334,15 +337,23 @@ public class ApplicationsState { AppEntry entry = mEntriesMap.get(userId).get(packageName); if (entry != null && (entry.info.flags & ApplicationInfo.FLAG_INSTALLED) != 0) { mBackgroundHandler.post(() -> { - final StorageStats stats = mStats.queryStatsForPackage(entry.info.volumeUuid, - packageName, UserHandle.of(userId)); - final PackageStats legacyStats = new PackageStats(packageName, userId); - legacyStats.codeSize = stats.getCodeBytes(); - legacyStats.dataSize = stats.getDataBytes(); - legacyStats.cacheSize = stats.getCacheBytes(); try { - mBackgroundHandler.mStatsObserver.onGetStatsCompleted(legacyStats, true); - } catch (RemoteException ignored) { + final StorageStats stats = mStats.queryStatsForPackage( + entry.info.storageUuid, packageName, UserHandle.of(userId)); + final PackageStats legacy = new PackageStats(packageName, userId); + legacy.codeSize = stats.getCodeBytes(); + legacy.dataSize = stats.getDataBytes(); + legacy.cacheSize = stats.getCacheBytes(); + try { + mBackgroundHandler.mStatsObserver.onGetStatsCompleted(legacy, true); + } catch (RemoteException ignored) { + } + } catch (NameNotFoundException | IOException e) { + Log.w(TAG, "Failed to query stats: " + e); + try { + mBackgroundHandler.mStatsObserver.onGetStatsCompleted(null, false); + } catch (RemoteException ignored) { + } } }); } @@ -979,7 +990,7 @@ public class ApplicationsState { mMainHandler.sendMessage(m); } entry.sizeLoadStart = now; - mCurComputingSizeUuid = entry.info.volumeUuid; + mCurComputingSizeUuid = entry.info.storageUuid; mCurComputingSizePkg = entry.info.packageName; mCurComputingSizeUserId = UserHandle.getUserId(entry.info.uid); @@ -988,17 +999,17 @@ public class ApplicationsState { final StorageStats stats = mStats.queryStatsForPackage( mCurComputingSizeUuid, mCurComputingSizePkg, UserHandle.of(mCurComputingSizeUserId)); - final PackageStats legacyStats = new PackageStats( + final PackageStats legacy = new PackageStats( mCurComputingSizePkg, mCurComputingSizeUserId); - legacyStats.codeSize = stats.getCodeBytes(); - legacyStats.dataSize = stats.getDataBytes(); - legacyStats.cacheSize = stats.getCacheBytes(); + legacy.codeSize = stats.getCodeBytes(); + legacy.dataSize = stats.getDataBytes(); + legacy.cacheSize = stats.getCacheBytes(); try { - mStatsObserver.onGetStatsCompleted(legacyStats, true); + mStatsObserver.onGetStatsCompleted(legacy, true); } catch (RemoteException ignored) { } - } catch (IllegalStateException e) { - Log.e(TAG,"An exception occurred while fetching app size", e); + } catch (NameNotFoundException | IOException e) { + Log.w(TAG, "Failed to query stats: " + e); try { mStatsObserver.onGetStatsCompleted(null, false); } catch (RemoteException ignored) { diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java b/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java index 21835738fd69..34fdc9ddd99d 100644 --- a/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java +++ b/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java @@ -19,9 +19,12 @@ package com.android.settingslib.applications; import android.app.usage.StorageStats; import android.app.usage.StorageStatsManager; import android.content.Context; +import android.content.pm.PackageManager; import android.os.UserHandle; import android.support.annotation.VisibleForTesting; +import java.io.IOException; + /** * StorageStatsSource wraps the StorageStatsManager for testability purposes. */ @@ -32,17 +35,21 @@ public class StorageStatsSource { mStorageStatsManager = context.getSystemService(StorageStatsManager.class); } - public StorageStatsSource.ExternalStorageStats getExternalStorageStats(String volumeUuid, UserHandle user) { + public StorageStatsSource.ExternalStorageStats getExternalStorageStats(String volumeUuid, + UserHandle user) throws IOException { return new StorageStatsSource.ExternalStorageStats( mStorageStatsManager.queryExternalStatsForUser(volumeUuid, user)); } - public StorageStatsSource.AppStorageStats getStatsForUid(String volumeUuid, int uid) { - return new StorageStatsSource.AppStorageStatsImpl(mStorageStatsManager.queryStatsForUid(volumeUuid, uid)); + public StorageStatsSource.AppStorageStats getStatsForUid(String volumeUuid, int uid) + throws IOException { + return new StorageStatsSource.AppStorageStatsImpl( + mStorageStatsManager.queryStatsForUid(volumeUuid, uid)); } public StorageStatsSource.AppStorageStats getStatsForPackage( - String volumeUuid, String packageName, UserHandle user) { + String volumeUuid, String packageName, UserHandle user) + throws PackageManager.NameNotFoundException, IOException { return new StorageStatsSource.AppStorageStatsImpl( mStorageStatsManager.queryStatsForPackage(volumeUuid, packageName, user)); } diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java index 88f133ce57c2..ccf7a0bfdfc6 100644 --- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java +++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java @@ -20,11 +20,16 @@ import android.app.AppGlobals; import android.app.usage.StorageStatsManager; import android.content.Context; import android.os.storage.VolumeInfo; +import android.util.Log; + +import java.io.IOException; /** * PrivateStorageInfo provides information about the total and free storage on the device. */ public class PrivateStorageInfo { + private static final String TAG = "PrivateStorageInfo"; + public final long freeBytes; public final long totalBytes; @@ -41,8 +46,12 @@ public class PrivateStorageInfo { long privateTotalBytes = 0; for (VolumeInfo info : sm.getVolumes()) { if (info.getType() == VolumeInfo.TYPE_PRIVATE && info.isMountedReadable()) { - privateTotalBytes += sm.getTotalBytes(stats, info); - privateFreeBytes += sm.getFreeBytes(stats, info); + try { + privateTotalBytes += sm.getTotalBytes(stats, info); + privateFreeBytes += sm.getFreeBytes(stats, info); + } catch (IOException e) { + Log.w(TAG, e); + } } } return new PrivateStorageInfo(privateFreeBytes, privateTotalBytes); @@ -51,6 +60,11 @@ public class PrivateStorageInfo { public static long getTotalSize(VolumeInfo info, long totalInternalStorage) { final Context context = AppGlobals.getInitialApplication(); final StorageStatsManager stats = context.getSystemService(StorageStatsManager.class); - return stats.getTotalBytes(info.getFsUuid()); + try { + return stats.getTotalBytes(info.getFsUuid()); + } catch (IOException e) { + Log.w(TAG, e); + return 0; + } } } diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java index 11060e6c1a05..b57b6cc544fa 100644 --- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java +++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java @@ -20,6 +20,7 @@ import android.app.usage.StorageStatsManager; import android.os.storage.StorageManager; import android.os.storage.VolumeInfo; +import java.io.IOException; import java.util.List; /** @@ -49,12 +50,12 @@ public class StorageManagerVolumeProvider implements StorageVolumeProvider { } @Override - public long getTotalBytes(StorageStatsManager stats, VolumeInfo volume) { + public long getTotalBytes(StorageStatsManager stats, VolumeInfo volume) throws IOException { return stats.getTotalBytes(volume.getFsUuid()); } @Override - public long getFreeBytes(StorageStatsManager stats, VolumeInfo volume) { + public long getFreeBytes(StorageStatsManager stats, VolumeInfo volume) throws IOException { return stats.getFreeBytes(volume.getFsUuid()); } } diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java index 60e10a125d0b..ea28fe68e91b 100644 --- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java +++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java @@ -32,6 +32,7 @@ import android.util.Log; import android.util.SparseArray; import android.util.SparseLongArray; +import java.io.IOException; import java.lang.ref.WeakReference; import java.util.HashMap; import java.util.List; @@ -154,7 +155,7 @@ public class StorageMeasurement { try { details.totalSize = mStats.getTotalBytes(mVolume.fsUuid); details.availSize = mStats.getFreeBytes(mVolume.fsUuid); - } catch (IllegalStateException e) { + } catch (IOException e) { // The storage volume became null while we were measuring it. Log.w(TAG, e); return details; @@ -169,8 +170,14 @@ public class StorageMeasurement { final HashMap<String, Long> mediaMap = new HashMap<>(); details.mediaSize.put(user.id, mediaMap); - final ExternalStorageStats stats = mStats - .queryExternalStatsForUser(mSharedVolume.fsUuid, UserHandle.of(user.id)); + final ExternalStorageStats stats; + try { + stats = mStats.queryExternalStatsForUser(mSharedVolume.fsUuid, + UserHandle.of(user.id)); + } catch (IOException e) { + Log.w(TAG, e); + continue; + } addValue(details.usersSize, user.id, stats.getTotalBytes()); @@ -190,8 +197,13 @@ public class StorageMeasurement { if ((mVolume.getType() == VolumeInfo.TYPE_PRIVATE) && mVolume.isMountedReadable()) { for (UserInfo user : users) { - final StorageStats stats = mStats.queryStatsForUser(mVolume.fsUuid, - UserHandle.of(user.id)); + final StorageStats stats; + try { + stats = mStats.queryStatsForUser(mVolume.fsUuid, UserHandle.of(user.id)); + } catch (IOException e) { + Log.w(TAG, e); + continue; + } // Only count code once against current user if (user.id == UserHandle.myUserId()) { diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java index e5d85d147bee..4c4541315e07 100644 --- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java +++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java @@ -19,6 +19,7 @@ package com.android.settingslib.deviceinfo; import android.app.usage.StorageStatsManager; import android.os.storage.VolumeInfo; +import java.io.IOException; import java.util.List; /** @@ -46,12 +47,12 @@ public interface StorageVolumeProvider { * * @pre The volume is a private volume and is readable. */ - long getTotalBytes(StorageStatsManager stats, VolumeInfo volume); + long getTotalBytes(StorageStatsManager stats, VolumeInfo volume) throws IOException; /** * Returns the free bytes for a given storage volume. * * @pre The volume is a private volume and is readable. */ - long getFreeBytes(StorageStatsManager stats, VolumeInfo volume); + long getFreeBytes(StorageStatsManager stats, VolumeInfo volume) throws IOException; } diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java index d6bde8132327..9d09737a14dc 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java @@ -40,6 +40,8 @@ public final class CategoryKey { "com.android.settings.category.ia.language"; public static final String CATEGORY_SYSTEM_DEVELOPMENT = "com.android.settings.category.ia.development"; + public static final String CATEGORY_NOTIFICATIONS = + "com.android.settings.category.ia.notifications"; public static final Map<String, String> KEY_COMPAT_MAP; diff --git a/packages/SystemUI/res/color/segmented_button_text_selector.xml b/packages/SystemUI/res/color/segmented_button_text_selector.xml index 537cbb84f647..d4f01816a608 100644 --- a/packages/SystemUI/res/color/segmented_button_text_selector.xml +++ b/packages/SystemUI/res/color/segmented_button_text_selector.xml @@ -18,4 +18,4 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="true" android:color="?android:attr/textColorPrimary"/> <item android:alpha="0.58" android:color="?android:attr/colorForeground"/> -</selector>
\ No newline at end of file +</selector> diff --git a/packages/SystemUI/res/drawable/ic_dnd.xml b/packages/SystemUI/res/drawable/ic_dnd.xml index 17ecf217b86b..e658e687821b 100644 --- a/packages/SystemUI/res/drawable/ic_dnd.xml +++ b/packages/SystemUI/res/drawable/ic_dnd.xml @@ -17,7 +17,8 @@ android:height="24dp" android:viewportHeight="48.0" android:viewportWidth="48.0" - android:width="24dp" > + android:width="24dp" + android:tint="?android:attr/colorControlNormal"> <path android:fillColor="#FFFFFFFF" diff --git a/packages/SystemUI/res/drawable/ic_dnd_total_silence.xml b/packages/SystemUI/res/drawable/ic_dnd_total_silence.xml index 487597454e27..0515b35fb875 100644 --- a/packages/SystemUI/res/drawable/ic_dnd_total_silence.xml +++ b/packages/SystemUI/res/drawable/ic_dnd_total_silence.xml @@ -17,7 +17,8 @@ android:height="24dp" android:viewportHeight="24.0" android:viewportWidth="24.0" - android:width="24dp" > + android:width="24dp" + android:tint="?android:attr/colorControlNormal"> <path android:fillColor="#FFFFFFFF" diff --git a/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml b/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml index 5aecebae1865..169cc71722a2 100644 --- a/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml +++ b/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml @@ -16,7 +16,6 @@ --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:name="root" - android:alpha="0.3" android:height="48dp" android:width="48dp" android:viewportHeight="48" diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_in.xml b/packages/SystemUI/res/drawable/ic_qs_signal_in.xml index 236fdac09c4b..5e7cd974818a 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_in.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_in.xml @@ -17,7 +17,8 @@ Copyright (C) 2014 The Android Open Source Project android:width="6.0dp" android:height="32dp" android:viewportWidth="6.0" - android:viewportHeight="24.0"> + android:viewportHeight="24.0" + android:tint="?android:attr/textColorSecondary"> <path android:fillColor="#FFFFFFFF" android:pathData="M6.000000,15.700000l-3.000000,5.599999 -3.000000,-5.599999z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_out.xml b/packages/SystemUI/res/drawable/ic_qs_signal_out.xml index c510972a5df8..0dca1db32f88 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_out.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_out.xml @@ -17,7 +17,8 @@ Copyright (C) 2014 The Android Open Source Project android:width="6.0dp" android:height="32dp" android:viewportWidth="6.0" - android:viewportHeight="24.0"> + android:viewportHeight="24.0" + android:tint="?android:attr/textColorSecondary"> <path android:fillColor="#FFFFFFFF" android:pathData="M0.000000,13.700000l3.000000,-5.700000 3.000000,5.700000z"/> diff --git a/packages/SystemUI/res/drawable/segmented_buttons_background.xml b/packages/SystemUI/res/drawable/segmented_buttons_background.xml index b243dc7ce8c0..755c917cf20c 100644 --- a/packages/SystemUI/res/drawable/segmented_buttons_background.xml +++ b/packages/SystemUI/res/drawable/segmented_buttons_background.xml @@ -17,6 +17,6 @@ <corners android:radius="@dimen/borderless_button_radius" /> - <solid android:color="@color/segmented_buttons_background" /> + <solid android:color="?android:attr/colorPrimaryDark" /> -</shape>
\ No newline at end of file +</shape> diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_1x.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_1x.xml index d7463a446657..be9a7e266c6f 100644 --- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_1x.xml +++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_1x.xml @@ -14,10 +14,10 @@ Copyright (C) 2014 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="8.5dp" - android:height="17dp" - android:viewportWidth="12.0" - android:viewportHeight="24.0"> + android:width="17dp" + android:height="17dp" + android:viewportWidth="12.0" + android:viewportHeight="12.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M3.500000,11.000000L1.800000,11.000000L1.800000,4.400000L0.200000,5.100000L0.200000,3.700000l3.100000,-1.300000l0.200000,0.000000L3.500000,11.000000z"/> diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_3g.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_3g.xml index 6309b6d9903b..fd7a65841129 100644 --- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_3g.xml +++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_3g.xml @@ -14,10 +14,10 @@ Copyright (C) 2014 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="9.208dp" + android:width="17dp" android:height="17dp" android:viewportWidth="13.0" - android:viewportHeight="24.0"> + android:viewportHeight="13.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M2.000000,6.000000l0.800000,0.000000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000s0.200000,-0.500000 0.200000,-0.900000c0.000000,-0.300000 -0.100000,-0.600000 -0.200000,-0.800000S3.200000,3.700000 2.900000,3.700000C2.700000,3.700000 2.500000,3.800000 2.300000,4.000000S2.100000,4.400000 2.100000,4.700000L0.500000,4.700000C0.500000,4.000000 0.700000,3.400000 1.100000,3.000000s1.000000,-0.600000 1.700000,-0.600000c0.800000,0.000000 1.400000,0.200000 1.900000,0.600000s0.700000,1.000000 0.700000,1.800000c0.000000,0.400000 -0.100000,0.700000 -0.300000,1.100000S4.600000,6.500000 4.300000,6.600000C4.700000,6.800000 5.000000,7.100000 5.200000,7.400000s0.300000,0.700000 0.300000,1.200000c0.000000,0.800000 -0.200000,1.400000 -0.700000,1.800000s-1.100000,0.700000 -1.900000,0.700000c-0.700000,0.000000 -1.300000,-0.200000 -1.800000,-0.600000s-0.700000,-1.000000 -0.700000,-1.800000L2.000000,8.700000C2.000000,9.000000 2.100000,9.300000 2.300000,9.500000s0.400000,0.300000 0.600000,0.300000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000S3.900000,9.000000 3.900000,8.600000c0.000000,-0.500000 -0.100000,-0.800000 -0.300000,-1.000000S3.200000,7.300000 2.800000,7.300000L2.000000,7.300000L2.000000,6.000000z"/> diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g.xml index 4067ae5b4800..02c4ab6161c6 100644 --- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g.xml +++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g.xml @@ -14,10 +14,10 @@ Copyright (C) 2014 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="8.5dp" + android:width="17dp" android:height="17dp" android:viewportWidth="12.0" - android:viewportHeight="24.0"> + android:viewportHeight="12.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M4.600000,7.800000l0.700000,0.000000l0.000000,1.300000L4.600000,9.100000L4.600000,11.000000L3.000000,11.000000L3.000000,9.200000L0.100000,9.200000L0.000000,8.100000L3.000000,2.500000l1.700000,0.000000L4.700000,7.800000zM1.600000,7.800000L3.000000,7.800000l0.000000,-3.000000L2.900000,5.000000L1.600000,7.800000z"/> diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml index 3cdd3e104bfb..daf40618c24a 100644 --- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml +++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml @@ -14,10 +14,10 @@ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="17.0dp" + android:width="25.5dp" android:height="17.0dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> + android:viewportWidth="18.0" + android:viewportHeight="12.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M4.6,7.8l0.7,0.0l0.0,1.3L4.6,9.1L4.6,11.0L3.0,11.0L3.0,9.2L0.1,9.2L0.0,8.2l3.0,-5.7l1.7,0.0L4.6,7.8L4.6,7.8zM1.7,7.8L3.0,7.8l0.0,-3.0L2.9,5.0L1.7,7.8z"/> diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_e.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_e.xml index acaa9b1c2be8..cd0cc6585391 100644 --- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_e.xml +++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_e.xml @@ -14,10 +14,10 @@ Copyright (C) 2014 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="3.541dp" + android:width="7.083dp" android:height="17dp" android:viewportWidth="5.0" - android:viewportHeight="24.0"> + android:viewportHeight="12.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M4.400000,7.300000L1.700000,7.300000l0.000000,2.400000l3.300000,0.000000L5.000000,11.000000L0.000000,11.000000L0.000000,2.500000l4.900000,0.000000l0.000000,1.300000L1.700000,3.800000l0.000000,2.100000l2.800000,0.000000L4.500000,7.300000z"/> diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_g.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_g.xml index 7985237d8a44..92ed49c71189 100644 --- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_g.xml +++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_g.xml @@ -14,10 +14,10 @@ Copyright (C) 2014 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="4.958dp" + android:width="9.154dp" android:height="17dp" android:viewportWidth="7.0" - android:viewportHeight="24.0"> + android:viewportHeight="13"> <path android:fillColor="#FFFFFFFF" android:pathData="M6.500000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S0.700000,9.000000 0.700000,7.900000L0.700000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000s1.200000,-0.800000 2.100000,-0.800000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000L4.700000,5.200000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000S4.000000,3.700000 3.600000,3.700000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S2.300000,5.000000 2.300000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L4.700000,7.800000L3.500000,7.800000L3.500000,6.600000l2.900000,0.000000L6.400000,9.900000z"/> diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_h.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_h.xml index fda87612582e..ca61b6f0299c 100644 --- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_h.xml +++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_h.xml @@ -14,10 +14,10 @@ Copyright (C) 2014 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="4.25dp" + android:width="9.5dp" android:height="17dp" android:viewportWidth="6.0" - android:viewportHeight="24.0"> + android:viewportHeight="12.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M6.000000,11.000000L4.400000,11.000000L4.400000,7.500000L1.700000,7.500000L1.700000,11.000000L0.000000,11.000000L0.000000,2.500000l1.700000,0.000000l0.000000,3.700000l2.700000,0.000000L4.400000,2.500000L6.000000,2.500000L6.000000,11.000000z"/> diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte.xml index c08ff20c54fc..add96b4352e8 100644 --- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte.xml +++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte.xml @@ -14,10 +14,10 @@ Copyright (C) 2014 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="9.208dp" + android:width="18.417dp" android:height="17dp" - android:viewportWidth="13.0" - android:viewportHeight="24.0"> + android:viewportWidth="13" + android:viewportHeight="12.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M2.000000,9.700000l2.000000,0.000000L4.000000,11.000000L0.300000,11.000000L0.300000,2.500000L2.000000,2.500000L2.000000,9.700000z"/> diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml index db18fad637e7..8811d2f9b7ba 100644 --- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml +++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml @@ -14,10 +14,10 @@ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="17.0dp" + android:width="25.0dp" android:height="17.0dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> + android:viewportWidth="18.0" + android:viewportHeight="12.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M2.0,9.7l2.0,0.0L4.0,11.0L0.4,11.0L0.4,2.5L2.0,2.5L2.0,9.7z"/> diff --git a/packages/SystemUI/res/drawable/stat_sys_roaming.xml b/packages/SystemUI/res/drawable/stat_sys_roaming.xml index 4baa472acb88..363e231cf03c 100644 --- a/packages/SystemUI/res/drawable/stat_sys_roaming.xml +++ b/packages/SystemUI/res/drawable/stat_sys_roaming.xml @@ -14,10 +14,10 @@ Copyright (C) 2014 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="8.5dp" + android:width="4.25dp" android:height="17dp" android:viewportWidth="6.0" - android:viewportHeight="12.0"> + android:viewportHeight="24.0"> <path android:fillColor="#FFFFFFFF" android:pathData="M2.800000,7.900000l-1.000000,0.000000L1.800000,11.000000L0.200000,11.000000L0.200000,2.500000l2.700000,0.000000c0.900000,0.000000 1.500000,0.200000 2.000000,0.700000s0.700000,1.100000 0.700000,1.900000c0.000000,0.600000 -0.100000,1.100000 -0.300000,1.500000S4.800000,7.200000 4.400000,7.400000l1.500000,3.500000L5.900000,11.000000L4.100000,11.000000L2.800000,7.900000zM1.800000,6.500000l1.100000,0.000000c0.400000,0.000000 0.600000,-0.100000 0.800000,-0.400000S4.000000,5.600000 4.000000,5.200000c0.000000,-0.400000 -0.100000,-0.800000 -0.300000,-1.000000S3.300000,3.800000 2.900000,3.800000L1.800000,3.800000L1.800000,6.500000z"/> diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_disconnected.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_disconnected.xml new file mode 100644 index 000000000000..f4e8af468b76 --- /dev/null +++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_disconnected.xml @@ -0,0 +1,42 @@ +<!-- + Copyright (C) 2016 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="18.41dp" + android:height="17dp" + android:viewportWidth="26.0" + android:viewportHeight="24.0"> + <path + android:fillColor="?attr/backgroundColor" + android:pathData="M21.0,8.5 + c0.85,0.0 1.6,0.23 2.3,0.62l2.24,-2.79 + C25.1,5.96 20.26,2.0 13.0,2.0 + S0.9,5.9 0.42,6.32 + l12.57,15.6 4.21,-5.17 + c-0.76,-0.87 -1.22,-2.0 -1.22,-3.25 + c0.0,-2.76 2.24,-5.0 5.0,-5.0z" + android:fillAlpha=".3"/> + <path + android:fillColor="?attr/backgroundColor" + android:pathData="M21.0,10.0 + c-1.93,0.0 -3.5,1.57 -3.5,3.5l1.75,0.0 + c0.0,-0.9 0.78,-1.75 1.75,-1.75s1.7,0.78 1.75,1.75 + c0.0,0.48 -0.2,0.92 -0.51,1.24l-1.09,1.1 + c-0.6,0.63 -1.02,1.51 -1.02,2.47l0.0,0.44l1.75,0.0 + c0.0,-1.3 0.39,-1.84 1.03,-2.47l0.78,-0.8 + c0.5,-0.5 0.82,-1.2 0.82,-1.97 + C24.5,11.57 22.93,10.0 21.0,10.0z + m-0.95,11.95l1.9,0.0l0.0,-1.9l-1.9,0.0l0.0,1.9z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_null.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_null.xml index 5169de46ea29..c1856fa30e7e 100644 --- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_null.xml +++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_null.xml @@ -20,5 +20,8 @@ Copyright (C) 2014 The Android Open Source Project android:viewportHeight="24.0"> <path android:fillColor="?attr/backgroundColor" - android:pathData="M13.000000,2.000000C7.700000,2.000000 3.700000,3.900000 0.400000,6.400000L13.000000,22.000000L25.600000,6.500000C22.299999,4.000000 18.299999,2.000000 13.000000,2.000000zM13.000000,18.600000L3.300000,7.000000l0.000000,0.000000l0.000000,0.000000C6.000000,5.300000 8.700000,4.000000 13.000000,4.000000s7.000000,1.400000 9.700000,3.000000l0.000000,0.000000l0.000000,0.000000L13.000000,18.600000z"/> + android:pathData="M17.500000,16.500000L5.800000,3.400000c0.000000,0.000000 0.000000,0.000000 0.000000,0.000000l-2.700000,-3.000000L1.600000,1.800000l2.200000,2.500000c-2.000000,1.000000 -3.200000,2.000000 -3.400000,2.200000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l3.200000,-3.900000l2.400000,2.700000l1.500000,-1.400000L17.500000,16.500000L17.500000,16.500000z"/> + <path + android:fillColor="?attr/backgroundColor" + android:pathData="M25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000c-1.900000,0.000000 -3.600000,0.300000 -5.200000,0.700000L18.700001,15.000000L25.600000,6.500000z"/> </vector> diff --git a/packages/SystemUI/res/layout/mobile_signal_group.xml b/packages/SystemUI/res/layout/mobile_signal_group.xml index 33effba53059..6d4365c644e4 100644 --- a/packages/SystemUI/res/layout/mobile_signal_group.xml +++ b/packages/SystemUI/res/layout/mobile_signal_group.xml @@ -63,20 +63,21 @@ systemui:hasOverlappingRendering="false" /> <ImageView - android:id="@+id/mobile_type" + android:id="@+id/mobile_roaming" android:layout_height="wrap_content" android:layout_width="wrap_content" + android:src="@drawable/stat_sys_roaming" + android:contentDescription="@string/accessibility_data_connection_roaming" + android:visibility="gone" /> <ImageView - android:id="@+id/mobile_roaming" + android:id="@+id/mobile_type" android:layout_width="wrap_content" android:layout_height="17dp" - android:paddingStart="22dp" + android:paddingStart="19dp" android:paddingTop="1.5dp" android:paddingBottom="3dp" android:scaleType="fitCenter" - android:src="@drawable/stat_sys_roaming" - android:contentDescription="@string/accessibility_data_connection_roaming" android:visibility="gone" /> </FrameLayout> </LinearLayout> diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml index ff22ffb319fb..0c9858dc8397 100644 --- a/packages/SystemUI/res/layout/notification_info.xml +++ b/packages/SystemUI/res/layout/notification_info.xml @@ -114,6 +114,7 @@ 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/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml index da7e4d79fc46..5766dc1c5b4f 100644 --- a/packages/SystemUI/res/layout/signal_cluster_view.xml +++ b/packages/SystemUI/res/layout/signal_cluster_view.xml @@ -52,9 +52,54 @@ android:alpha="0.0" /> </FrameLayout> + <ViewStub + android:id="@+id/connected_device_signals_stub" + android:layout="@layout/connected_device_signal" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + <LinearLayout + android:id="@+id/mobile_signal_group" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + > + </LinearLayout> + <View + android:id="@+id/wifi_signal_spacer" + android:layout_width="@dimen/status_bar_wifi_signal_spacer_width" + android:layout_height="4dp" + android:visibility="gone" + /> + <FrameLayout + android:id="@+id/no_sims_combo" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:contentDescription="@string/accessibility_no_sims"> + <com.android.systemui.statusbar.AlphaOptimizedImageView + android:theme="@style/DualToneLightTheme" + android:id="@+id/no_sims" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:src="@drawable/stat_sys_no_sims" + /> + <com.android.systemui.statusbar.AlphaOptimizedImageView + android:theme="@style/DualToneDarkTheme" + android:id="@+id/no_sims_dark" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:src="@drawable/stat_sys_no_sims" + android:alpha="0.0" + /> + </FrameLayout> + <View + android:id="@+id/wifi_airplane_spacer" + android:layout_width="@dimen/status_bar_airplane_spacer_width" + android:layout_height="4dp" + android:visibility="gone" + /> <FrameLayout android:layout_height="17dp" - android:layout_width="wrap_content"> + android:layout_width="wrap_content" + android:paddingStart="2dp"> <ImageView android:id="@+id/wifi_in" android:layout_height="wrap_content" @@ -96,50 +141,6 @@ android:layout_width="wrap_content" /> </FrameLayout> - <View - android:id="@+id/wifi_signal_spacer" - android:layout_width="@dimen/status_bar_wifi_signal_spacer_width" - android:layout_height="4dp" - android:visibility="gone" - /> - <ViewStub - android:id="@+id/connected_device_signals_stub" - android:layout="@layout/connected_device_signal" - android:layout_width="wrap_content" - android:layout_height="wrap_content" /> - <LinearLayout - android:id="@+id/mobile_signal_group" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - > - </LinearLayout> - <FrameLayout - android:id="@+id/no_sims_combo" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:contentDescription="@string/accessibility_no_sims"> - <com.android.systemui.statusbar.AlphaOptimizedImageView - android:theme="@style/DualToneLightTheme" - android:id="@+id/no_sims" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:src="@drawable/stat_sys_no_sims" - /> - <com.android.systemui.statusbar.AlphaOptimizedImageView - android:theme="@style/DualToneDarkTheme" - android:id="@+id/no_sims_dark" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:src="@drawable/stat_sys_no_sims" - android:alpha="0.0" - /> - </FrameLayout> - <View - android:id="@+id/wifi_airplane_spacer" - android:layout_width="@dimen/status_bar_airplane_spacer_width" - android:layout_height="4dp" - android:visibility="gone" - /> <ImageView android:id="@+id/airplane" android:layout_height="wrap_content" diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index eeb28c825ffa..33b1dd40e471 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1466,6 +1466,15 @@ <item quantity="other"><xliff:g id="channel_name_1">%1$s</xliff:g>, <xliff:g id="channel_name_2">%2$s</xliff:g>, and <xliff:g id="number">%3$d</xliff:g> others</item> </plurals> + <!-- Notification: Control panel: Accessibility description for expanded inline controls view, used + to control settings about notifications related to the current notification. --> + <string name="notification_channel_controls_opened_accessibility">Notification controls for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g> opened</string> + <!-- Notification: Control panel: Accessibility description for announcing the closing of the + inline controls view. --> + <string name="notification_channel_controls_closed_accessibility">Notification controls for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g> closed</string> + <!-- Notification: Control panel: Accessibility description for switch that is used to enable + or disable notifications from this channel --> + <string name="notification_channel_switch_accessibility">Allow notifications from this channel</string> <!-- Notification: Control panel: Label for button that launches notification settings. Used when this app has defined more than a single channel for notifications. --> <string name="notification_all_categories">All Categories</string> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index c9479b8b41f7..e5f04c6186b8 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -299,13 +299,13 @@ <style name="TextAppearance.Volume"> <item name="android:textStyle">normal</item> - <item name="android:textColor">#ffffffff</item> + <item name="android:textColor">?android:attr/textColorPrimary</item> <item name="android:fontFamily">sans-serif</item> </style> <style name="TextAppearance.Volume.Header"> <item name="android:textSize">12sp</item> - <item name="android:textColor">@color/volume_slider_inactive</item> + <item name="android:textColor">?android:attr/textColorSecondary</item> </style> <style name="TextAppearance.Volume.ZenSummary"> @@ -316,7 +316,7 @@ <style name="TextAppearance.Volume.ZenDetail"> <item name="android:textSize">14sp</item> <item name="android:fontFamily">sans-serif</item> - <item name="android:textColor">@*android:color/quaternary_device_default_settings</item> + <item name="android:textColor">?android:attr/textColorSecondary</item> </style> <style name="VolumeButtons" parent="@android:style/Widget.Material.Button.Borderless"> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index b447979be45d..616e5b9830ed 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -15,6 +15,7 @@ */ package com.android.keyguard; +import android.R.style; import android.app.Activity; import android.app.AlertDialog; import android.app.admin.DevicePolicyManager; @@ -23,6 +24,7 @@ import android.os.UserHandle; import android.util.AttributeSet; import android.util.Log; import android.util.Slog; +import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; @@ -73,7 +75,8 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe } public KeyguardSecurityContainer(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); + super(new ContextThemeWrapper(context, android.R.style.Theme_DeviceDefault), attrs, + defStyle); mSecurityModel = new KeyguardSecurityModel(context); mLockPatternUtils = new LockPatternUtils(context); mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java index 870d4d1c6a9d..90e1c0723945 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java @@ -145,6 +145,11 @@ public class DozeLog { log("screenOff why=" + why); } + public static void traceMissedTick(String delay) { + if (!ENABLED) return; + log("missedTick by=" + delay); + } + public static void traceKeyguard(boolean showing) { if (!ENABLED) return; log("keyguard " + showing); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java index 6098a20a0c64..03076cc4b7a8 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java @@ -20,6 +20,8 @@ import android.app.AlarmManager; import android.content.Context; import android.os.Handler; import android.os.SystemClock; +import android.text.format.Formatter; +import android.util.Log; import com.android.systemui.util.wakelock.WakeLock; @@ -31,6 +33,7 @@ import java.util.GregorianCalendar; */ public class DozeUi implements DozeMachine.Part { + private static final long TIME_TICK_DEADLINE_MILLIS = 90 * 1000; // 1.5min private final Context mContext; private final AlarmManager mAlarmManager; private final DozeHost mHost; @@ -40,6 +43,7 @@ public class DozeUi implements DozeMachine.Part { private final AlarmManager.OnAlarmListener mTimeTick; private boolean mTimeTickScheduled = false; + private long mLastTimeTickElapsed = 0; public DozeUi(Context context, AlarmManager alarmManager, DozeMachine machine, WakeLock wakeLock, DozeHost host, Handler handler) { @@ -103,15 +107,26 @@ public class DozeUi implements DozeMachine.Part { SystemClock.elapsedRealtime() + delta, "doze_time_tick", mTimeTick, mHandler); mTimeTickScheduled = true; + mLastTimeTickElapsed = SystemClock.elapsedRealtime(); } private void unscheduleTimeTick() { if (!mTimeTickScheduled) { return; } + verifyLastTimeTick(); mAlarmManager.cancel(mTimeTick); } + private void verifyLastTimeTick() { + long millisSinceLastTick = SystemClock.elapsedRealtime() - mLastTimeTickElapsed; + if (millisSinceLastTick > TIME_TICK_DEADLINE_MILLIS) { + String delay = Formatter.formatShortElapsedTime(mContext, millisSinceLastTick); + DozeLog.traceMissedTick(delay); + Log.e(DozeMachine.TAG, "Missed AOD time tick by " + delay); + } + } + private long roundToNextMinute(long timeInMillis) { Calendar calendar = GregorianCalendar.getInstance(); calendar.setTimeInMillis(timeInMillis); @@ -127,6 +142,7 @@ public class DozeUi implements DozeMachine.Part { // Alarm was canceled, but we still got the callback. Ignore. return; } + verifyLastTimeTick(); mHost.dozeTimeTick(); diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java index c5653733bac7..28bd23ce9825 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -143,10 +143,10 @@ public class PipManager implements BasePipManager { @Override public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, - Rect animatingBounds, boolean fromImeAdjustement) { + Rect animatingBounds, boolean fromImeAdjustement, int displayRotation) { mHandler.post(() -> { mTouchHandler.onMovementBoundsChanged(insetBounds, normalBounds, animatingBounds, - fromImeAdjustement); + fromImeAdjustement, displayRotation); }); } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java index ac0670348af2..982b8085b216 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java @@ -221,6 +221,13 @@ public class PipMenuActivity extends Activity { } @Override + protected void onStop() { + super.onStop(); + + cancelDelayedFinish(); + } + + @Override protected void onDestroy() { super.onDestroy(); diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java index 127296cd7f8e..67255d35590a 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java @@ -316,7 +316,8 @@ public class PipMotionHelper { * Animates the PiP from the expanded state to the normal state after the menu is hidden. */ void animateToUnexpandedState(Rect normalBounds, float savedSnapFraction, - Rect normalMovementBounds, Rect currentMovementBounds, boolean minimized) { + Rect normalMovementBounds, Rect currentMovementBounds, boolean minimized, + boolean immediate) { if (savedSnapFraction < 0f) { // If there are no saved snap fractions, then just use the current bounds savedSnapFraction = mSnapAlgorithm.getSnapFraction(new Rect(mBounds), @@ -326,7 +327,11 @@ public class PipMotionHelper { if (minimized) { normalBounds = getClosestMinimizedBounds(normalBounds, normalMovementBounds); } - resizeAndAnimatePipUnchecked(normalBounds, SHRINK_STACK_FROM_MENU_DURATION); + if (immediate) { + movePip(normalBounds); + } else { + resizeAndAnimatePipUnchecked(normalBounds, SHRINK_STACK_FROM_MENU_DURATION); + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java index a3280ea01306..fbf7ff21b0ce 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java @@ -90,6 +90,11 @@ public class PipTouchHandler implements TunerService.Tunable { private Rect mExpandedMovementBounds = new Rect(); private int mExpandedShortestEdgeSize; + // Used to workaround an issue where the WM rotation happens before we are notified, allowing + // us to send stale bounds + private int mDeferResizeToNormalBoundsUntilRotation = -1; + private int mDisplayRotation; + private Handler mHandler = new Handler(); private Runnable mShowDismissAffordance = new Runnable() { @Override @@ -256,7 +261,7 @@ public class PipTouchHandler implements TunerService.Tunable { } public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, Rect animatingBounds, - boolean fromImeAdjustement) { + boolean fromImeAdjustement, int displayRotation) { // Re-calculate the expanded bounds mNormalBounds = normalBounds; Rect normalMovementBounds = new Rect(); @@ -310,7 +315,17 @@ public class PipTouchHandler implements TunerService.Tunable { // above mNormalMovementBounds = normalMovementBounds; mExpandedMovementBounds = expandedMovementBounds; + mDisplayRotation = displayRotation; updateMovementBounds(mMenuState); + + // If we have a deferred resize, apply it now + if (mDeferResizeToNormalBoundsUntilRotation == displayRotation) { + mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction, + mNormalMovementBounds, mMovementBounds, mIsMinimized, + true /* immediate */); + mSavedSnapFraction = -1f; + mDeferResizeToNormalBoundsUntilRotation = -1; + } } private void onRegistrationChanged(boolean isRegistered) { @@ -480,11 +495,34 @@ public class PipTouchHandler implements TunerService.Tunable { // Try and restore the PiP to the closest edge, using the saved snap fraction // if possible if (resize) { - Rect normalBounds = new Rect(mNormalBounds); - mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction, - mNormalMovementBounds, mMovementBounds, mIsMinimized); + // This is a very special case: when the menu is expanded and visible, navigating to + // another activity can trigger auto-enter PiP, and if the revealed activity has a + // forced rotation set, then the controller will get updated with the new rotation + // of the display. However, at the same time, SystemUI will try to hide the menu by + // creating an animation to the normal bounds which are now stale. In such a case + // we defer the animation to the normal bounds until after the next + // onMovementBoundsChanged() call to get the bounds in the new orientation + if (mDeferResizeToNormalBoundsUntilRotation == -1) { + try { + int displayRotation = mPinnedStackController.getDisplayRotation(); + if (mDisplayRotation != displayRotation) { + mDeferResizeToNormalBoundsUntilRotation = displayRotation; + } + } catch (RemoteException e) { + Log.e(TAG, "Could not get display rotation from controller"); + } + } + + if (mDeferResizeToNormalBoundsUntilRotation == -1) { + Rect normalBounds = new Rect(mNormalBounds); + mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction, + mNormalMovementBounds, mMovementBounds, mIsMinimized, + false /* immediate */); + mSavedSnapFraction = -1f; + } + } else { + mSavedSnapFraction = -1f; } - mSavedSnapFraction = -1f; } mMenuState = menuState; updateMovementBounds(menuState); diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java index f2f0d7a5a86c..657f08be8b52 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java @@ -178,7 +178,7 @@ public class PipManager implements BasePipManager { @Override public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, - Rect animatingBounds, boolean fromImeAdjustement) { + Rect animatingBounds, boolean fromImeAdjustement, int displayRotation) { mHandler.post(() -> { mDefaultPipBounds.set(normalBounds); }); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java index d51fe8a2f690..53c36e69ef7e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java @@ -167,6 +167,9 @@ public class QSFooter extends LinearLayout implements if (mAlarmShowing) { builder.addFloat(mDate, "alpha", 1, 0) .addFloat(mDateTimeGroup, "translationX", 0, -mDate.getWidth()); + } else { + mDate.setAlpha(1); + mDateTimeGroup.setTranslationX(0); } mAnimator = builder.build(); setExpansion(mExpansionAmount); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java index 7518527a3093..e457d7247434 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java @@ -77,6 +77,9 @@ public class QuickStatusBarHeader extends RelativeLayout { BatteryMeterView battery = findViewById(R.id.battery); battery.setForceShowPercent(true); + // Don't show the Wi-Fi indicator here, because it is shown just below in the tile. + SignalClusterView signalCluster = findViewById(R.id.signal_cluster); + signalCluster.setForceBlockWifi(); mActivityStarter = Dependency.get(ActivityStarter.class); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java index 92ff17a1f029..d74e3ac656f7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java @@ -128,7 +128,7 @@ public class CellularTile extends QSTileImpl<SignalState> { state.value = mDataController.isMobileDataSupported() && mDataController.isMobileDataEnabled(); state.icon = ResourceIcon.get(R.drawable.ic_data_unavailable); - state.state = cb.airplaneModeEnabled || !cb.enabled ? Tile.STATE_UNAVAILABLE + state.state = cb.airplaneModeEnabled || !cb.enabled || cb.noSim ? Tile.STATE_UNAVAILABLE : state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; if (state.state == Tile.STATE_ACTIVE) { state.icon = ResourceIcon.get(R.drawable.ic_data_on); @@ -161,44 +161,27 @@ public class CellularTile extends QSTileImpl<SignalState> { private static final class CallbackInfo { boolean enabled; - boolean wifiEnabled; boolean airplaneModeEnabled; - String signalContentDescription; - int dataTypeIconId; - String dataContentDescription; boolean activityIn; boolean activityOut; - String enabledDesc; boolean noSim; - boolean isDataTypeIconWide; boolean roaming; } private final class CellSignalCallback implements SignalCallback { private final CallbackInfo mInfo = new CallbackInfo(); - @Override - public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon, - boolean activityIn, boolean activityOut, String description, boolean isTransient) { - mInfo.wifiEnabled = enabled; - refreshState(mInfo); - } @Override - public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType, - int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, - String description, boolean isWide, int subId, boolean roaming) { - if (qsIcon == null) { + public void setMobileDataIndicators(IconState statusIcon, int statusType, + boolean activityIn, boolean activityOut, String typeContentDescription, + int subId, boolean roaming, boolean isEmergency) { + if (statusIcon == null) { // Not data sim, don't display. return; } - mInfo.enabled = qsIcon.visible; - mInfo.signalContentDescription = qsIcon.contentDescription; - mInfo.dataTypeIconId = qsType; - mInfo.dataContentDescription = typeContentDescription; + mInfo.enabled = statusIcon.visible; mInfo.activityIn = activityIn; mInfo.activityOut = activityOut; - mInfo.enabledDesc = description; - mInfo.isDataTypeIconWide = qsType != 0 && isWide; mInfo.roaming = roaming; refreshState(mInfo); } @@ -206,15 +189,6 @@ public class CellularTile extends QSTileImpl<SignalState> { @Override public void setNoSims(boolean show) { mInfo.noSim = show; - if (mInfo.noSim) { - // Make sure signal gets cleared out when no sims. - mInfo.dataTypeIconId = 0; - // Show a No SIMs description to avoid emergency calls message. - mInfo.enabled = true; - mInfo.enabledDesc = mContext.getString( - R.string.keyguard_missing_sim_message_short); - mInfo.signalContentDescription = mInfo.enabledDesc; - } refreshState(mInfo); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index 677642e53d6e..cc9175382903 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -1115,6 +1115,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mNotificationInflater.setInflateExceptionHandler(inflateExceptionHandler); } + public void setNeedsRedaction(boolean needsRedaction) { + mNotificationInflater.setRedactAmbient(needsRedaction); + } + 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 8f160dc0384e..609856522e75 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java @@ -428,6 +428,9 @@ public class NotificationContentView extends FrameLayout { mAmbientChild.animate().cancel(); removeView(mAmbientChild); } + if (child == null) { + return; + } addView(child); mAmbientChild = child; mAmbientWrapper = NotificationViewWrapper.wrap(getContext(), child, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java index 2713f58272d0..0a99ee6c781f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java @@ -39,6 +39,7 @@ import android.util.Log; import android.view.View; import android.view.ViewAnimationUtils; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityEvent; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; @@ -255,6 +256,7 @@ public class NotificationGuts extends FrameLayout { } public void setExposed(boolean exposed, boolean needsFalsingProtection) { + final boolean wasExposed = mExposed; mExposed = exposed; mNeedsFalsingProtection = needsFalsingProtection; if (mExposed && mNeedsFalsingProtection) { @@ -262,6 +264,13 @@ public class NotificationGuts extends FrameLayout { } else { mHandler.removeCallbacks(mFalsingCheck); } + if (wasExposed != mExposed && mGutsContent != null) { + final View contentView = mGutsContent.getContentView(); + contentView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); + if (mExposed) { + contentView.requestAccessibilityFocus(); + } + } } public boolean willBeRemoved() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java index 7928575df4d4..89251897e25f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java @@ -35,6 +35,7 @@ import android.service.notification.StatusBarNotification; import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; +import android.view.accessibility.AccessibilityEvent; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Switch; @@ -57,6 +58,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G private INotificationManager mINotificationManager; private String mPkg; + private String mAppName; private int mAppUid; private List<NotificationChannel> mNotificationChannels; private NotificationChannel mSingleNotificationChannel; @@ -125,7 +127,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G } } - String appName = mPkg; + mAppName = mPkg; Drawable pkgicon = null; CharSequence channelNameText = ""; ApplicationInfo info = null; @@ -137,7 +139,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G | PackageManager.MATCH_DIRECT_BOOT_AWARE); if (info != null) { mAppUid = info.uid; - appName = String.valueOf(pm.getApplicationLabel(info)); + mAppName = String.valueOf(pm.getApplicationLabel(info)); pkgicon = pm.getApplicationIcon(info); } } catch (PackageManager.NameNotFoundException e) { @@ -189,7 +191,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G } else { channelNameText = mSingleNotificationChannel.getName(); } - ((TextView) findViewById(R.id.pkgname)).setText(appName); + ((TextView) findViewById(R.id.pkgname)).setText(mAppName); ((TextView) findViewById(R.id.channel_name)).setText(channelNameText); // Set group information if this channel has an associated group. @@ -309,6 +311,21 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G }); } + @Override + public void onInitializeAccessibilityEvent(AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(event); + if (mGutsContainer != null && + event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { + if (mGutsContainer.isExposed()) { + event.getText().add(mContext.getString( + R.string.notification_channel_controls_opened_accessibility, mAppName)); + } else { + event.getText().add(mContext.getString( + R.string.notification_channel_controls_closed_accessibility, mAppName)); + } + } + } + private void updateSecondaryText() { final boolean disabled = mSingleNotificationChannel != null && getSelectedImportance() == IMPORTANCE_NONE; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java index fee24b7b7645..802925a315eb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java @@ -227,6 +227,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl if (mShouldShowMenu && !NotificationStackScrollLayout.isPinnedHeadsUp(view) && !mParent.areGutsExposed() + && !mParent.isDark() && (mCheckForDrag == null || !mHandler.hasCallbacks(mCheckForDrag))) { // Only show the menu if we're not a heads up view and guts aren't exposed. mCheckForDrag = new CheckForDrag(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java index dc254f9fdc1e..b01d9cc07bf5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java @@ -24,8 +24,6 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.Rect; -import android.graphics.drawable.Animatable; -import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.telephony.SubscriptionInfo; @@ -120,6 +118,7 @@ public class SignalClusterView extends LinearLayout implements NetworkController private boolean mBlockWifi; private boolean mBlockEthernet; private boolean mActivityEnabled; + private boolean mForceBlockWifi; public SignalClusterView(Context context) { this(context, null); @@ -151,6 +150,16 @@ public class SignalClusterView extends LinearLayout implements NetworkController updateActivityEnabled(); } + public void setForceBlockWifi() { + mForceBlockWifi = true; + mBlockWifi = true; + if (isAttachedToWindow()) { + // Re-register to get new callbacks. + mNetworkController.removeCallback(this); + mNetworkController.addCallback(this); + } + } + @Override public void onTuningChanged(String key, String newValue) { if (!StatusBarIconController.ICON_BLACKLIST.equals(key)) { @@ -167,7 +176,7 @@ public class SignalClusterView extends LinearLayout implements NetworkController mBlockAirplane = blockAirplane; mBlockMobile = blockMobile; mBlockEthernet = blockEthernet; - mBlockWifi = blockWifi; + mBlockWifi = blockWifi || mForceBlockWifi; // Re-register to get new callbacks. mNetworkController.removeCallback(this); mNetworkController.addCallback(this); @@ -288,9 +297,9 @@ public class SignalClusterView extends LinearLayout implements NetworkController } @Override - public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType, - int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, - String description, boolean isWide, int subId, boolean roaming) { + public void setMobileDataIndicators(IconState statusIcon, int statusType, + boolean activityIn, boolean activityOut, String typeContentDescription, + int subId, boolean roaming, boolean isEmergency) { PhoneState state = getState(subId); if (state == null) { return; @@ -300,7 +309,6 @@ public class SignalClusterView extends LinearLayout implements NetworkController state.mMobileTypeId = statusType; state.mMobileDescription = statusIcon.contentDescription; state.mMobileTypeDescription = typeContentDescription; - state.mIsMobileTypeIconWide = statusType != 0 && isWide; state.mRoaming = roaming; state.mActivityIn = activityIn && mActivityEnabled; state.mActivityOut = activityOut && mActivityEnabled; @@ -525,7 +533,7 @@ public class SignalClusterView extends LinearLayout implements NetworkController mWifiAirplaneSpacer.setVisibility(View.GONE); } - if (((anyMobileVisible && firstMobileTypeId != 0) || mNoSimsVisible) && mWifiVisible) { + if (((anyMobileVisible && firstMobileTypeId == 0) || mNoSimsVisible) && mWifiVisible) { mWifiSignalSpacer.setVisibility(View.VISIBLE); } else { mWifiSignalSpacer.setVisibility(View.GONE); @@ -636,7 +644,6 @@ public class SignalClusterView extends LinearLayout implements NetworkController private int mMobileStrengthId = 0, mMobileTypeId = 0; private int mLastMobileStrengthId = -1; private int mLastMobileTypeId = -1; - private boolean mIsMobileTypeIconWide; private String mMobileDescription, mMobileTypeDescription; private ViewGroup mMobileGroup; @@ -692,12 +699,8 @@ public class SignalClusterView extends LinearLayout implements NetworkController // When this isn't next to wifi, give it some extra padding between the signals. mMobileGroup.setPaddingRelative(isSecondaryIcon ? mSecondaryTelephonyPadding : 0, 0, 0, 0); - mMobile.setPaddingRelative( - mIsMobileTypeIconWide ? mWideTypeIconStartPadding : mMobileDataIconStartPadding, - 0, 0, 0); - mMobileDark.setPaddingRelative( - mIsMobileTypeIconWide ? mWideTypeIconStartPadding : mMobileDataIconStartPadding, - 0, 0, 0); + mMobile.setPaddingRelative(mMobileDataIconStartPadding, 0, 0, 0); + mMobileDark.setPaddingRelative(mMobileDataIconStartPadding, 0, 0, 0); if (DEBUG) Log.d(TAG, String.format("mobile: %s sig=%d typ=%d", (mMobileVisible ? "VISIBLE" : "GONE"), mMobileStrengthId, mMobileTypeId)); 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 73eecbbf2728..2e34f2483a85 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java @@ -21,6 +21,8 @@ import android.content.Context; 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; @@ -49,6 +51,7 @@ public class NotificationInflater { private RemoteViews.OnClickHandler mRemoteViewClickHandler; private boolean mIsChildInGroup; private InflationExceptionHandler mInflateExceptionHandler; + private boolean mRedactAmbient; public NotificationInflater(ExpandableNotificationRow row) { mRow = row; @@ -92,6 +95,21 @@ public class NotificationInflater { mRemoteViewClickHandler = remoteViewClickHandler; } + public void setRedactAmbient(boolean redactAmbient) { + if (mRedactAmbient != redactAmbient) { + mRedactAmbient = redactAmbient; + if (mRow.getEntry() == null) { + return; + } + try { + inflateNotificationViews(FLAG_REINFLATE_AMBIENT_VIEW); + } catch (InflationException e) { + mInflateExceptionHandler.handleInflationException( + mRow.getStatusBarNotification(), e); + } + } + } + public void inflateNotificationViews() throws InflationException { inflateNotificationViews(FLAG_REINFLATE_ALL); } @@ -123,6 +141,8 @@ public class NotificationInflater { Notification.Builder builder, Context packageContext) { NotificationData.Entry entry = mRow.getEntry(); NotificationContentView privateLayout = mRow.getPrivateLayout(); + NotificationContentView publicLayout = mRow.getPublicLayout(); + boolean isLowPriority = mIsLowPriority && !mIsChildInGroup; if ((reInflateFlags & FLAG_REINFLATE_CONTENT_VIEW) != 0) { final RemoteViews newContentView = createContentView(builder, @@ -190,7 +210,6 @@ public class NotificationInflater { } if ((reInflateFlags & FLAG_REINFLATE_PUBLIC_VIEW) != 0) { - NotificationContentView publicLayout = mRow.getPublicLayout(); final RemoteViews newPublicNotification = builder.makePublicContentView(); if (!compareRemoteViews(newPublicNotification, entry.cachedPublicContentView)) { @@ -209,18 +228,24 @@ public class NotificationInflater { } if ((reInflateFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) { - final RemoteViews newAmbientNotification - = builder.makeAmbientNotification(); - if (!compareRemoteViews(newAmbientNotification, entry.cachedAmbientContentView)) { + final RemoteViews newAmbientNotification = mRedactAmbient + ? builder.makePublicAmbientNotification() + : builder.makeAmbientNotification(); + NotificationContentView newParent = mRedactAmbient ? publicLayout : privateLayout; + NotificationContentView otherParent = !mRedactAmbient ? publicLayout : privateLayout; + + if (newParent.getAmbientChild() == null || + !compareRemoteViews(newAmbientNotification, entry.cachedAmbientContentView)) { View ambientContentView = newAmbientNotification.apply( packageContext, - privateLayout, + newParent, mRemoteViewClickHandler); ambientContentView.setIsRootNamespace(true); - privateLayout.setAmbientChild(ambientContentView); + newParent.setAmbientChild(ambientContentView); + otherParent.setAmbientChild(null); } else { newAmbientNotification.reapply(packageContext, - privateLayout.getAmbientChild(), + newParent.getAmbientChild(), mRemoteViewClickHandler); } entry.cachedAmbientContentView = newAmbientNotification; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java index a9eb20ba3a57..6361eb6ccb89 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java @@ -57,12 +57,12 @@ public class SignalDrawable extends Drawable { private static final int LEVEL_MASK = 0xff; private static final int NUM_LEVEL_SHIFT = 8; private static final int NUM_LEVEL_MASK = 0xff << NUM_LEVEL_SHIFT; - private static final int STATE_SHIFT = 16; - private static final int STATE_MASK = 0xff << STATE_SHIFT; - private static final int STATE_NONE = 0; - private static final int STATE_EMPTY = 1; - private static final int STATE_CUT = 2; - private static final int STATE_CARRIER_CHANGE = 3; + public static final int STATE_SHIFT = 16; + public static final int STATE_MASK = 0xff << STATE_SHIFT; + public static final int STATE_NONE = 0; + public static final int STATE_EMPTY = 1; + public static final int STATE_CUT = 2; + public static final int STATE_CARRIER_CHANGE = 3; private static final long DOT_DELAY = 1000; 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 df814a090cc5..79191f3c2114 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -31,6 +31,7 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCE import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING; +import android.R.style; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.annotation.NonNull; @@ -48,10 +49,8 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentSender; -import android.content.pm.ActivityInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.database.ContentObserver; @@ -95,6 +94,7 @@ import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; +import android.view.ContextThemeWrapper; import android.view.Display; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -139,7 +139,6 @@ import com.android.systemui.doze.DozeLog; import com.android.systemui.fragments.FragmentHostManager; import com.android.systemui.fragments.PluginFragmentListener; import com.android.systemui.keyguard.KeyguardViewMediator; -import com.android.systemui.pip.phone.PipManager; import com.android.systemui.plugins.qs.QS; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption; @@ -1337,7 +1336,10 @@ public class StatusBar extends SystemUI implements DemoMode, } private void inflateDismissView() { - mDismissView = (DismissView) LayoutInflater.from(mContext).inflate( + // Always inflate with a dark theme, since this sits on the scrim. + ContextThemeWrapper themedContext = new ContextThemeWrapper(mContext, + style.Theme_DeviceDefault); + mDismissView = (DismissView) LayoutInflater.from(themedContext).inflate( R.layout.status_bar_notification_dismiss_all, mStackScroller, false); mDismissView.setOnButtonClickListener(new View.OnClickListener() { @Override @@ -1809,6 +1811,7 @@ public class StatusBar extends SystemUI implements DemoMode, updatePublicContentView(ent, ent.notification); } ent.row.setSensitive(sensitive, deviceSensitive); + ent.row.setNeedsRedaction(needsRedaction(ent)); if (mGroupManager.isChildInGroupWithSummary(ent.row.getStatusBarNotification())) { ExpandableNotificationRow summary = mGroupManager.getGroupSummary( ent.row.getStatusBarNotification()); @@ -1897,6 +1900,21 @@ public class StatusBar extends SystemUI implements DemoMode, mNotificationIconAreaController.updateNotificationIcons(mNotificationData); } + /** @return true if the entry needs redaction when on the lockscreen. */ + private boolean needsRedaction(Entry ent) { + int userId = ent.notification.getUserId(); + + boolean currentUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(mCurrentUserId); + boolean notiUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(userId); + boolean redactedLockscreen = currentUserWantsRedaction || notiUserWantsRedaction; + + boolean notificationRequestsRedaction = + ent.notification.getNotification().visibility == Notification.VISIBILITY_PRIVATE; + boolean userForcesRedaction = packageHasVisibilityOverride(ent.notification.getKey()); + + return userForcesRedaction || notificationRequestsRedaction && redactedLockscreen; + } + /** * Disable QS if device not provisioned. * If the user switcher is simple then disable QS during setup because @@ -5857,6 +5875,9 @@ public class StatusBar extends SystemUI implements DemoMode, } final ExpandableNotificationRow row = (ExpandableNotificationRow) v; + if (row.isDark()) { + return false; + } bindGuts(row, item); NotificationGuts guts = row.getGuts(); @@ -5904,8 +5925,10 @@ public class StatusBar extends SystemUI implements DemoMode, } }); a.start(); - guts.setExposed(true /* exposed */, - mState == StatusBarState.KEYGUARD /* needsFalsingProtection */); + final boolean needsFalsingProtection = + (mState == StatusBarState.KEYGUARD && + !mAccessibilityManager.isTouchExplorationEnabled()); + guts.setExposed(true /* exposed */, needsFalsingProtection); row.closeRemoteInput(); mStackScroller.onHeightChanged(row, true /* needsAnimation */); mNotificationGutsExposed = guts; @@ -6156,6 +6179,7 @@ public class StatusBar extends SystemUI implements DemoMode, } } + row.setNeedsRedaction(needsRedaction(entry)); boolean isLowPriority = mNotificationData.isAmbient(sbn.getKey()); row.setIsLowPriority(isLowPriority); // bind the click event to the content area @@ -6520,7 +6544,6 @@ public class StatusBar extends SystemUI implements DemoMode, NotificationData.Entry entry = new NotificationData.Entry(sbn); Dependency.get(LeakDetector.class).trackInstance(entry); entry.createIcons(mContext, sbn); - // Construct the expanded view. inflateViews(entry, mStackScroller); return entry; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java index a456786d712f..e98dc987aa5c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java @@ -110,30 +110,24 @@ public class CallbackHandler extends Handler implements EmergencyListener, Signa public void setWifiIndicators(final boolean enabled, final IconState statusIcon, final IconState qsIcon, final boolean activityIn, final boolean activityOut, final String description, boolean isTransient) { - post(new Runnable() { - @Override - public void run() { - for (SignalCallback callback : mSignalCallbacks) { - callback.setWifiIndicators(enabled, statusIcon, qsIcon, activityIn, activityOut, - description, isTransient); - } + post(() -> { + for (SignalCallback callback : mSignalCallbacks) { + callback.setWifiIndicators(enabled, statusIcon, qsIcon, activityIn, activityOut, + description, isTransient); } }); } @Override - public void setMobileDataIndicators(final IconState statusIcon, final IconState qsIcon, - final int statusType, final int qsType,final boolean activityIn, + public void setMobileDataIndicators(final IconState statusIcon, + final int statusType, final boolean activityIn, final boolean activityOut, final String typeContentDescription, - final String description, final boolean isWide, final int subId, boolean roaming) { - post(new Runnable() { - @Override - public void run() { - for (SignalCallback signalCluster : mSignalCallbacks) { - signalCluster.setMobileDataIndicators(statusIcon, qsIcon, statusType, qsType, - activityIn, activityOut, typeContentDescription, description, isWide, - subId, roaming); - } + final int subId, boolean roaming, boolean isEmergency) { + post(() -> { + for (SignalCallback signalCluster : mSignalCallbacks) { + signalCluster.setMobileDataIndicators(statusIcon, statusType, + activityIn, activityOut, typeContentDescription, + subId, roaming, isEmergency); } }); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index 67b5596e34c9..4421a6ab0cfd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -244,7 +244,8 @@ public class MobileSignalController extends SignalController< return SignalDrawable.getCarrierChangeState(getNumLevels()); } else if (mCurrentState.connected) { return SignalDrawable.getState(mCurrentState.level, getNumLevels(), - mCurrentState.inetCondition == 0); + mCurrentState.inetCondition == 0 || + (mCurrentState.dataDisabled && mCurrentState.userSetup)); } else if (mCurrentState.enabled) { return SignalDrawable.getEmptyState(getNumLevels()); } else { @@ -263,24 +264,14 @@ public class MobileSignalController extends SignalController< String contentDescription = getStringIfExists(getContentDescription()); String dataContentDescription = getStringIfExists(icons.mDataContentDescription); - final boolean dataDisabled = mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED + final boolean dataDisabled = mCurrentState.dataDisabled && mCurrentState.userSetup; // Show icon in QS when we are connected or data is disabled. - boolean showDataIcon = mCurrentState.dataConnected || dataDisabled; + boolean showDataIcon = mCurrentState.dataConnected; IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode, getCurrentIconId(), contentDescription); - int qsTypeIcon = 0; - IconState qsIcon = null; - String description = null; - // Only send data sim callbacks to QS. - if (mCurrentState.dataSim) { - qsTypeIcon = showDataIcon ? icons.mQsDataType : 0; - qsIcon = new IconState(mCurrentState.enabled - && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription); - description = mCurrentState.isEmergency ? null : mCurrentState.networkName; - } boolean activityIn = mCurrentState.dataConnected && !mCurrentState.carrierNetworkChangeMode && mCurrentState.activityIn; @@ -289,9 +280,10 @@ public class MobileSignalController extends SignalController< && mCurrentState.activityOut; showDataIcon &= mCurrentState.isDefault || dataDisabled; int typeIcon = showDataIcon ? icons.mDataType : 0; - callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon, - activityIn, activityOut, dataContentDescription, description, icons.mIsWide, - mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming); + callback.setMobileDataIndicators(statusIcon, typeIcon, + activityIn, activityOut, dataContentDescription, + mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming, + mCurrentState.isEmergency); } @Override @@ -438,14 +430,14 @@ public class MobileSignalController extends SignalController< } else { mCurrentState.iconGroup = mDefaultIcons; } + mCurrentState.dataDisabled = isDataDisabled(); mCurrentState.dataConnected = mCurrentState.connected - && mDataState == TelephonyManager.DATA_CONNECTED; + && mDataState == TelephonyManager.DATA_CONNECTED + && !mCurrentState.dataDisabled; mCurrentState.roaming = isRoaming(); if (isCarrierNetworkChangeActive()) { mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE; - } else if (isDataDisabled()) { - mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED; } if (isEmergencyOnly() != mCurrentState.isEmergency) { mCurrentState.isEmergency = isEmergencyOnly(); @@ -577,6 +569,7 @@ public class MobileSignalController extends SignalController< boolean isDefault; boolean userSetup; boolean roaming; + boolean dataDisabled; @Override public void copyFrom(State s) { @@ -592,6 +585,7 @@ public class MobileSignalController extends SignalController< carrierNetworkChangeMode = state.carrierNetworkChangeMode; userSetup = state.userSetup; roaming = state.roaming; + dataDisabled = state.dataDisabled; } @Override @@ -609,6 +603,7 @@ public class MobileSignalController extends SignalController< builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode) .append(','); builder.append("userSetup=").append(userSetup); + builder.append("dataDisabled=").append(dataDisabled); } @Override @@ -623,6 +618,7 @@ public class MobileSignalController extends SignalController< && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode && ((MobileState) o).userSetup == userSetup && ((MobileState) o).isDefault == isDefault + && ((MobileState) o).dataDisabled == dataDisabled && ((MobileState) o).roaming == roaming; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index c02ce0ea6335..ab4a8f21ba24 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -48,9 +48,9 @@ public interface NetworkController extends CallbackController<SignalCallback>, D default void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon, boolean activityIn, boolean activityOut, String description, boolean isTransient) {} - default void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType, - int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, - String description, boolean isWide, int subId, boolean roaming) {} + default void setMobileDataIndicators(IconState statusIcon, int statusType, + boolean activityIn, boolean activityOut, String typeContentDescription, + int subId, boolean roaming, boolean isEmergency) {} default void setSubs(List<SubscriptionInfo> subs) {} default void setNoSims(boolean show) {} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index c21f444d0bf3..60f4ab8ffe0e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -867,7 +867,6 @@ public class NetworkControllerImpl extends BroadcastReceiver datatype.equals("h") ? TelephonyIcons.H : datatype.equals("lte") ? TelephonyIcons.LTE : datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS : - datatype.equals("dis") ? TelephonyIcons.DATA_DISABLED : TelephonyIcons.UNKNOWN; } if (args.containsKey("roam")) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java index aaa0568a72cd..ec7e557fde81 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java @@ -44,10 +44,6 @@ class TelephonyIcons { static final int ICON_4G_PLUS = R.drawable.stat_sys_data_fully_connected_4g_plus; static final int ICON_1X = R.drawable.stat_sys_data_fully_connected_1x; - static final int ICON_DATA_DISABLED = R.drawable.stat_sys_data_disabled; - - static final int QS_ICON_DATA_DISABLED = R.drawable.ic_qs_data_disabled; - static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup( "CARRIER_NETWORK_CHANGE", null, @@ -221,20 +217,5 @@ class TelephonyIcons { true, TelephonyIcons.QS_DATA_LTE_PLUS ); - - static final MobileIconGroup DATA_DISABLED = new MobileIconGroup( - "DataDisabled", - null, - null, - AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, - 0, 0, - 0, - 0, - AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], - R.string.accessibility_cell_data_off, - TelephonyIcons.ICON_DATA_DISABLED, - false, - TelephonyIcons.QS_ICON_DATA_DISABLED - ); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java index 374408d3ec7a..dfc3591678ac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java @@ -47,6 +47,7 @@ public class WifiIcons { static final int QS_WIFI_NO_NETWORK = R.drawable.ic_qs_wifi_no_network; static final int WIFI_NO_NETWORK = R.drawable.stat_sys_wifi_signal_null; + static final int WIFI_DISCONNECTED = R.drawable.stat_sys_wifi_signal_disconnected; static final int WIFI_LEVEL_COUNT = WIFI_SIGNAL_STRENGTH[0].length; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java index 2104cb1421aa..a773acf317c9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java @@ -80,7 +80,7 @@ public class WifiSignalController extends AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH, WifiIcons.WIFI_NO_NETWORK, WifiIcons.QS_WIFI_NO_NETWORK, - WifiIcons.WIFI_NO_NETWORK, + WifiIcons.WIFI_DISCONNECTED, WifiIcons.QS_WIFI_NO_NETWORK, AccessibilityContentDescriptions.WIFI_NO_CONNECTION ); @@ -133,8 +133,7 @@ public class WifiSignalController extends @Override public void notifyListeners(SignalCallback callback) { // only show wifi in the cluster if connected or if wifi-only - boolean wifiVisible = mCurrentState.enabled - && (mCurrentState.connected || !mHasMobileData); + boolean wifiVisible = true; String wifiDesc = wifiVisible ? mCurrentState.ssid : null; boolean ssidPresent = wifiVisible && mCurrentState.ssid != null; String contentDescription = getStringIfExists(getContentDescription()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java index 3ed1681644f2..f6c75a8f0b84 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java @@ -114,33 +114,26 @@ public class CallbackHandlerTest { boolean wide = true; int subId = 5; boolean roaming = true; - mHandler.setMobileDataIndicators(status, qs, type, qsType, in, out, typeDescription, - description, wide, subId, roaming); + boolean isEmergency = true; + mHandler.setMobileDataIndicators(status, type, in, out, typeDescription, + subId, roaming, isEmergency); waitForCallbacks(); ArgumentCaptor<IconState> statusArg = ArgumentCaptor.forClass(IconState.class); - ArgumentCaptor<IconState> qsArg = ArgumentCaptor.forClass(IconState.class); ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<Integer> qsTypeIconArg = ArgumentCaptor.forClass(Integer.class); ArgumentCaptor<Boolean> inArg = ArgumentCaptor.forClass(Boolean.class); ArgumentCaptor<Boolean> outArg = ArgumentCaptor.forClass(Boolean.class); ArgumentCaptor<String> typeContentArg = ArgumentCaptor.forClass(String.class); - ArgumentCaptor<String> descArg = ArgumentCaptor.forClass(String.class); - ArgumentCaptor<Boolean> wideArg = ArgumentCaptor.forClass(Boolean.class); ArgumentCaptor<Integer> subIdArg = ArgumentCaptor.forClass(Integer.class); Mockito.verify(mSignalCallback).setMobileDataIndicators(statusArg.capture(), - qsArg.capture(), typeIconArg.capture(), qsTypeIconArg.capture(), inArg.capture(), - outArg.capture(), typeContentArg.capture(), descArg.capture(), wideArg.capture(), - subIdArg.capture(), eq(roaming)); + typeIconArg.capture(), inArg.capture(), + outArg.capture(), typeContentArg.capture(), + subIdArg.capture(), eq(roaming), eq(isEmergency)); assertEquals(status, statusArg.getValue()); - assertEquals(qs, qsArg.getValue()); assertEquals(type, (int) typeIconArg.getValue()); - assertEquals(qsType, (int) qsTypeIconArg.getValue()); assertEquals(in, (boolean) inArg.getValue()); assertEquals(out, (boolean) outArg.getValue()); assertEquals(typeDescription, typeContentArg.getValue()); - assertEquals(description, descArg.getValue()); - assertEquals(wide, (boolean) wideArg.getValue()); assertEquals(subId, (int) subIdArg.getValue()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java index 505e1d8346fd..b39171e9f720 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java @@ -29,6 +29,7 @@ import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.util.Log; + import com.android.internal.telephony.cdma.EriInfo; import com.android.settingslib.net.DataUsageController; import com.android.systemui.statusbar.phone.SignalDrawable; @@ -45,8 +46,6 @@ import org.junit.rules.TestWatcher; import org.junit.runner.Description; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; import java.io.PrintWriter; import java.io.StringWriter; @@ -70,7 +69,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { protected static final int DEFAULT_SIGNAL_STRENGTH = DEFAULT_LEVEL; protected static final int DEFAULT_QS_SIGNAL_STRENGTH = DEFAULT_LEVEL; protected static final int DEFAULT_ICON = TelephonyIcons.ICON_3G; - protected static final int DEFAULT_QS_ICON = TelephonyIcons.QS_DATA_3G; + protected static final int DEFAULT_QS_ICON = DEFAULT_ICON; protected NetworkControllerImpl mNetworkController; protected MobileSignalController mMobileSignalController; @@ -117,7 +116,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(true); when(mMockCm.getDefaultNetworkCapabilitiesForUser(0)).thenReturn( - new NetworkCapabilities[] { mNetCapabilities }); + new NetworkCapabilities[]{mNetCapabilities}); mSignalStrength = mock(SignalStrength.class); mServiceState = mock(ServiceState.class); @@ -175,17 +174,17 @@ public class NetworkControllerBaseTest extends SysuiTestCase { } protected NetworkControllerImpl setUpNoMobileData() { - when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false); - NetworkControllerImpl networkControllerNoMobile - = new NetworkControllerImpl(mContext, mMockCm, mMockNetworkScoreManager, mMockTm, - mMockWm, mMockSm, mConfig, mContext.getMainLooper(), mCallbackHandler, - mock(AccessPointControllerImpl.class), - mock(DataUsageController.class), mMockSubDefaults, - mock(DeviceProvisionedController.class)); + when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false); + NetworkControllerImpl networkControllerNoMobile + = new NetworkControllerImpl(mContext, mMockCm, mMockNetworkScoreManager, mMockTm, + mMockWm, mMockSm, mConfig, mContext.getMainLooper(), mCallbackHandler, + mock(AccessPointControllerImpl.class), + mock(DataUsageController.class), mMockSubDefaults, + mock(DeviceProvisionedController.class)); - setupNetworkController(); + setupNetworkController(); - return networkControllerNoMobile; + return networkControllerNoMobile; } @@ -308,11 +307,10 @@ public class NetworkControllerBaseTest extends SysuiTestCase { ArgumentCaptor<Boolean> dataOutArg = ArgumentCaptor.forClass(Boolean.class); Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators( - any(), - iconArg.capture(), - anyInt(), - typeIconArg.capture(), dataInArg.capture(), dataOutArg.capture(), - anyString(), anyString(), anyBoolean(), anyInt(), anyBoolean()); + iconArg.capture(), + typeIconArg.capture(), + dataInArg.capture(), dataOutArg.capture(), + anyString(), anyInt(), anyBoolean(), anyBoolean()); IconState iconState = iconArg.getValue(); int state = SignalDrawable.getState(icon, SignalStrength.NUM_SIGNAL_STRENGTH_BINS, false); @@ -335,17 +333,16 @@ public class NetworkControllerBaseTest extends SysuiTestCase { } protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon, - boolean roaming, boolean inet) { + boolean roaming, boolean inet) { ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class); ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class); // TODO: Verify all fields. Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators( iconArg.capture(), - any(), typeIconArg.capture(), - anyInt(), anyBoolean(), anyBoolean(), anyString(), anyString(), anyBoolean(), - anyInt(), eq(roaming)); + anyBoolean(), anyBoolean(), anyString(), + anyInt(), eq(roaming), anyBoolean()); IconState iconState = iconArg.getValue(); int state = icon == -1 ? 0 @@ -356,22 +353,18 @@ public class NetworkControllerBaseTest extends SysuiTestCase { } protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon, - boolean qsVisible, int qsIcon, int qsTypeIcon, boolean dataIn, boolean dataOut) { + boolean qsVisible, boolean dataIn, boolean dataOut) { ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class); ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<IconState> qsIconArg = ArgumentCaptor.forClass(IconState.class); - ArgumentCaptor<Integer> qsTypeIconArg = ArgumentCaptor.forClass(Integer.class); ArgumentCaptor<Boolean> dataInArg = ArgumentCaptor.forClass(Boolean.class); ArgumentCaptor<Boolean> dataOutArg = ArgumentCaptor.forClass(Boolean.class); Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators( iconArg.capture(), - qsIconArg.capture(), typeIconArg.capture(), - qsTypeIconArg.capture(), dataInArg.capture(), dataOutArg.capture(), - anyString(), anyString(), anyBoolean(), anyInt(), anyBoolean()); + anyString(), anyInt(), anyBoolean(), anyBoolean()); IconState iconState = iconArg.getValue(); @@ -381,17 +374,15 @@ public class NetworkControllerBaseTest extends SysuiTestCase { assertEquals("Signal icon in status bar", state, iconState.icon); assertEquals("Visibility in status bar", visible, iconState.visible); - iconState = qsIconArg.getValue(); assertEquals("Visibility in quick settings", qsVisible, iconState.visible); assertEquals("Signal icon in quick settings", state, iconState.icon); - assertEquals("Data icon in quick settings", qsTypeIcon, (int) qsTypeIconArg.getValue()); assertEquals("Data direction in in quick settings", dataIn, (boolean) dataInArg.getValue()); assertEquals("Data direction out in quick settings", dataOut, (boolean) dataOutArg.getValue()); } - protected void assertNetworkNameEquals(String expected) { - assertEquals("Network name", expected, mMobileSignalController.getState().networkName); - } + protected void assertNetworkNameEquals(String expected) { + assertEquals("Network name", expected, mMobileSignalController.getState().networkName); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java index dfe00f95fe4d..6470c117f406 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java @@ -1,5 +1,9 @@ package com.android.systemui.statusbar.policy; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -11,10 +15,14 @@ import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; import com.android.settingslib.net.DataUsageController; +import com.android.systemui.statusbar.phone.SignalDrawable; +import com.android.systemui.statusbar.policy.NetworkController.IconState; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; @SmallTest @RunWith(AndroidJUnit4.class) @@ -116,8 +124,11 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0); setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false); - verifyDataIndicators(TelephonyIcons.ICON_DATA_DISABLED, - TelephonyIcons.QS_ICON_DATA_DISABLED); + ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class); + Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators( + iconArg.capture(), anyInt(), anyBoolean(), anyBoolean(), any(), anyInt(), + anyBoolean(), anyBoolean()); + assertEquals(SignalDrawable.STATE_CUT, SignalDrawable.getState(iconArg.getValue().icon)); } @Test @@ -129,9 +140,14 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false); when(mMockProvisionController.isUserSetup(anyInt())).thenReturn(false); mUserCallback.onUserSetupChanged(); + waitForIdleSync(); // Don't show the X until the device is setup. - verifyDataIndicators(0, 0); + ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class); + Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators( + iconArg.capture(), anyInt(), anyBoolean(), anyBoolean(), any(), anyInt(), + anyBoolean(), anyBoolean()); + assertNotEquals(SignalDrawable.STATE_CUT, SignalDrawable.getState(iconArg.getValue().icon)); } @Test @@ -181,12 +197,12 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { updateDataActivity(direction); verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, DEFAULT_ICON, true, - DEFAULT_QS_SIGNAL_STRENGTH, DEFAULT_QS_ICON, in, out); + in, out); } private void verifyDataIndicators(int dataIcon, int qsDataIcon) { verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, dataIcon, - true, DEFAULT_QS_SIGNAL_STRENGTH, qsDataIcon, false, + true, false, false); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java index 1627925ae1bc..e542c371feda 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java @@ -214,7 +214,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { verifyLastQsMobileDataIndicators(true, testStrength, - TelephonyIcons.QS_DATA_1X, false, false); + TelephonyIcons.ICON_1X, false, false); } } @@ -434,7 +434,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { verifyLastQsMobileDataIndicators(true /* visible */, DEFAULT_LEVEL /* icon */, - DEFAULT_QS_ICON /* typeIcon */, + DEFAULT_ICON /* typeIcon */, false /* dataIn */, true /* dataOut */); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java index 73fa5aa180bf..edfa3261a7e8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java @@ -62,7 +62,7 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest { public void testWifiIcon() { String testSsid = "Test SSID"; setWifiEnabled(true); - verifyLastWifiIcon(false, WifiIcons.WIFI_NO_NETWORK); + verifyLastWifiIcon(true, WifiIcons.WIFI_DISCONNECTED); setWifiState(true, testSsid); verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[0][0]); diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 39bfedae69d8..8ad3d23648bf 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -49,6 +49,7 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; +import android.annotation.BinderThread; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -2146,6 +2147,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return mKeyguardManager != null && mKeyguardManager.isKeyguardLocked(); } + @BinderThread @SuppressWarnings("deprecation") @Override public void setImeWindowStatus(IBinder token, IBinder startInputToken, int vis, @@ -2161,9 +2163,23 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mBackDisposition = backDisposition; updateSystemUiLocked(token, vis, backDisposition); } + + final boolean dismissImeOnBackKeyPressed; + switch (backDisposition) { + case InputMethodService.BACK_DISPOSITION_WILL_DISMISS: + dismissImeOnBackKeyPressed = true; + break; + case InputMethodService.BACK_DISPOSITION_WILL_NOT_DISMISS: + dismissImeOnBackKeyPressed = false; + break; + default: + case InputMethodService.BACK_DISPOSITION_DEFAULT: + dismissImeOnBackKeyPressed = ((vis & InputMethodService.IME_VISIBLE) != 0); + break; + } mWindowManagerInternal.updateInputMethodWindowStatus(token, (vis & InputMethodService.IME_VISIBLE) != 0, - info != null ? info.mTargetWindow : null); + dismissImeOnBackKeyPressed, info != null ? info.mTargetWindow : null); } private void updateSystemUi(IBinder token, int vis, int backDisposition) { diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index d79609856c3f..452fe1d70ddc 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -3272,6 +3272,8 @@ class StorageManagerService extends IStorageManager.Stub try { return mContext.getSystemService(StorageStatsManager.class) .queryStatsForUid(volumeUuid, uid).getCacheBytes(); + } catch (IOException e) { + throw new ParcelableException(e); } finally { Binder.restoreCallingIdentity(token); } @@ -3312,6 +3314,8 @@ class StorageManagerService extends IStorageManager.Stub return Math.max(0, path.getUsableSpace() - storage.getStorageLowBytes(path)); } } + } catch (IOException e) { + throw new ParcelableException(e); } finally { Binder.restoreCallingIdentity(token); } @@ -3329,13 +3333,13 @@ class StorageManagerService extends IStorageManager.Stub + " because only " + allocatableBytes + " allocatable")); } - // Free up enough disk space to satisfy both the requested allocation - // and our low disk warning space. - final File path = storage.findPathForUuid(volumeUuid); - bytes += storage.getStorageLowBytes(path); - final long token = Binder.clearCallingIdentity(); try { + // Free up enough disk space to satisfy both the requested allocation + // and our low disk warning space. + final File path = storage.findPathForUuid(volumeUuid); + bytes += storage.getStorageLowBytes(path); + mPms.freeStorage(volumeUuid, bytes, flags); } catch (IOException e) { throw new ParcelableException(e); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 1c2a6aa2bbdf..946ba0d04e2d 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1230,6 +1230,20 @@ public class ActivityManagerService extends IActivityManager.Stub */ int[] mDeviceIdleTempWhitelist = new int[0]; + static final class PendingTempWhitelist { + final int targetUid; + final long duration; + final String tag; + + PendingTempWhitelist(int _targetUid, long _duration, String _tag) { + targetUid = _targetUid; + duration = _duration; + tag = _tag; + } + } + + final SparseArray<PendingTempWhitelist> mPendingTempWhitelist = new SparseArray<>(); + /** * Information about and control over application operations */ @@ -1688,6 +1702,7 @@ public class ActivityManagerService extends IActivityManager.Stub static final int NOTIFY_VR_SLEEPING_MSG = 65; static final int SERVICE_FOREGROUND_TIMEOUT_MSG = 66; static final int DISPATCH_PENDING_INTENT_CANCEL_MSG = 67; + static final int PUSH_TEMP_WHITELIST_UI_MSG = 68; static final int START_USER_SWITCH_FG_MSG = 712; static final int FIRST_ACTIVITY_STACK_MSG = 100; @@ -1921,6 +1936,9 @@ public class ActivityManagerService extends IActivityManager.Stub case DISPATCH_UIDS_CHANGED_UI_MSG: { dispatchUidsChanged(); } break; + case PUSH_TEMP_WHITELIST_UI_MSG: { + pushTempWhitelist(); + } break; } } } @@ -6493,7 +6511,8 @@ public class ActivityManagerService extends IActivityManager.Stub // This is the first appearance of the uid, report it now! if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, "Creating new process uid: " + uidRec); - if (Arrays.binarySearch(mDeviceIdleTempWhitelist, UserHandle.getAppId(proc.uid)) >= 0) { + if (Arrays.binarySearch(mDeviceIdleTempWhitelist, UserHandle.getAppId(proc.uid)) >= 0 + || mPendingTempWhitelist.indexOfKey(proc.uid) >= 0) { uidRec.setWhitelist = uidRec.curWhitelist = true; } uidRec.updateHasInternetPermission(); @@ -7487,43 +7506,6 @@ public class ActivityManagerService extends IActivityManager.Stub } } - /** - * Whitelists {@code targetUid} to temporarily bypass Power Save mode. - */ - void tempWhitelistAppForPowerSave(int callerPid, int callerUid, int targetUid, long duration) { - if (DEBUG_WHITELISTS) { - Slog.d(TAG, "tempWhitelistAppForPowerSave(" + callerPid + ", " + callerUid + ", " - + targetUid + ", " + duration + ")"); - } - - if (checkPermission(CHANGE_DEVICE_IDLE_TEMP_WHITELIST, callerPid, callerUid) - != PackageManager.PERMISSION_GRANTED) { - synchronized (mPidsSelfLocked) { - final ProcessRecord pr = mPidsSelfLocked.get(callerPid); - if (pr == null) { - Slog.w(TAG, "tempWhitelistAppForPowerSave() no ProcessRecord for pid " - + callerPid); - return; - } - if (!pr.whitelistManager) { - if (DEBUG_WHITELISTS) { - Slog.d(TAG, "tempWhitelistAppForPowerSave() for target " + targetUid - + ": pid " + callerPid + " is not allowed"); - } - return; - } - } - } - - final long token = Binder.clearCallingIdentity(); - try { - mLocalDeviceIdleController.addPowerSaveTempWhitelistAppDirect(targetUid, duration, - true, "pe from uid:" + callerUid); - } finally { - Binder.restoreCallingIdentity(token); - } - } - @Override public void cancelIntentSender(IIntentSender sender) { if (!(sender instanceof PendingIntentRecord)) { @@ -7863,7 +7845,14 @@ public class ActivityManagerService extends IActivityManager.Stub r.pictureInPictureArgs.copyOnlySet(args); final float aspectRatio = r.pictureInPictureArgs.getAspectRatio(); final List<RemoteAction> actions = r.pictureInPictureArgs.getActions(); - final Rect sourceBounds = r.pictureInPictureArgs.getSourceRectHint(); + // Adjust the source bounds by the insets for the transition down + final Rect sourceBounds = new Rect(r.pictureInPictureArgs.getSourceRectHint()); + final Rect insets = r.pictureInPictureArgs.getSourceRectHintInsets(); + if (insets != null) { + sourceBounds.offsetTo(Math.max(0, sourceBounds.left - insets.left), + Math.max(0, sourceBounds.top - insets.top)); + } + mStackSupervisor.moveActivityToPinnedStackLocked(r, sourceBounds, aspectRatio, true /* moveHomeStackToFront */, "enterPictureInPictureMode"); final PinnedActivityStack stack = mStackSupervisor.getStack(PINNED_STACK_ID); @@ -8412,7 +8401,8 @@ public class ActivityManagerService extends IActivityManager.Stub boolean isOnDeviceIdleWhitelistLocked(int uid) { final int appId = UserHandle.getAppId(uid); return Arrays.binarySearch(mDeviceIdleWhitelist, appId) >= 0 - || Arrays.binarySearch(mDeviceIdleTempWhitelist, appId) >= 0; + || Arrays.binarySearch(mDeviceIdleTempWhitelist, appId) >= 0 + || mPendingTempWhitelist.indexOfKey(uid) >= 0; } private ProviderInfo getProviderInfoLocked(String authority, int userHandle, int pmFlags) { @@ -15588,6 +15578,18 @@ public class ActivityManagerService extends IActivityManager.Stub } pw.println(" mDeviceIdleWhitelist=" + Arrays.toString(mDeviceIdleWhitelist)); pw.println(" mDeviceIdleTempWhitelist=" + Arrays.toString(mDeviceIdleTempWhitelist)); + if (mPendingTempWhitelist.size() > 0) { + pw.println(" mPendingTempWhitelist:"); + for (int i = 0; i < mPendingTempWhitelist.size(); i++) { + PendingTempWhitelist ptw = mPendingTempWhitelist.valueAt(i); + pw.print(" "); + UserHandle.formatUid(pw, ptw.targetUid); + pw.print(": "); + TimeUtils.formatDuration(ptw.duration, pw); + pw.print(" "); + pw.println(ptw.tag); + } + } } if (dumpPackage == null) { pw.println(" mWakefulness=" @@ -22700,6 +22702,80 @@ public class ActivityManagerService extends IActivityManager.Stub enqueueUidChangeLocked(uidRec, uid, UidRecord.CHANGE_IDLE); } + /** + * Whitelists {@code targetUid} to temporarily bypass Power Save mode. + */ + void tempWhitelistForPendingIntentLocked(int callerPid, int callerUid, int targetUid, + long duration, String tag) { + if (DEBUG_WHITELISTS) { + Slog.d(TAG, "tempWhitelistForPendingIntentLocked(" + callerPid + ", " + callerUid + ", " + + targetUid + ", " + duration + ")"); + } + + synchronized (mPidsSelfLocked) { + final ProcessRecord pr = mPidsSelfLocked.get(callerPid); + if (pr == null) { + Slog.w(TAG, "tempWhitelistForPendingIntentLocked() no ProcessRecord for pid " + + callerPid); + return; + } + if (!pr.whitelistManager) { + if (checkPermission(CHANGE_DEVICE_IDLE_TEMP_WHITELIST, callerPid, callerUid) + != PackageManager.PERMISSION_GRANTED) { + if (DEBUG_WHITELISTS) { + Slog.d(TAG, "tempWhitelistForPendingIntentLocked() for target " + targetUid + + ": pid " + callerPid + " is not allowed"); + } + return; + } + } + } + + tempWhitelistUidLocked(targetUid, duration, tag); + } + + /** + * Whitelists {@code targetUid} to temporarily bypass Power Save mode. + */ + void tempWhitelistUidLocked(int targetUid, long duration, String tag) { + mPendingTempWhitelist.put(targetUid, new PendingTempWhitelist(targetUid, duration, tag)); + setUidTempWhitelistStateLocked(targetUid, true); + mUiHandler.obtainMessage(PUSH_TEMP_WHITELIST_UI_MSG).sendToTarget(); + } + + void pushTempWhitelist() { + final int N; + final PendingTempWhitelist[] list; + + // First copy out the pending changes... we need to leave them in the map for now, + // in case someone needs to check what is coming up while we don't have the lock held. + synchronized(this) { + N = mPendingTempWhitelist.size(); + list = new PendingTempWhitelist[N]; + for (int i = 0; i < N; i++) { + list[i] = mPendingTempWhitelist.valueAt(i); + } + } + + // Now safely dispatch changes to device idle controller. + for (int i = 0; i < N; i++) { + PendingTempWhitelist ptw = list[i]; + mLocalDeviceIdleController.addPowerSaveTempWhitelistAppDirect(ptw.targetUid, + ptw.duration, true, ptw.tag); + } + + // And now we can safely remove them from the map. + synchronized(this) { + for (int i = 0; i < N; i++) { + PendingTempWhitelist ptw = list[i]; + int index = mPendingTempWhitelist.indexOfKey(ptw.targetUid); + if (index >= 0 && mPendingTempWhitelist.valueAt(index) == ptw) { + mPendingTempWhitelist.removeAt(index); + } + } + } + } + final void setAppIdTempWhitelistStateLocked(int appId, boolean onWhitelist) { boolean changed = false; for (int i=mActiveUids.size()-1; i>=0; i--) { @@ -22714,6 +22790,15 @@ public class ActivityManagerService extends IActivityManager.Stub } } + final void setUidTempWhitelistStateLocked(int uid, boolean onWhitelist) { + boolean changed = false; + final UidRecord uidRec = mActiveUids.get(uid); + if (uidRec != null && uidRec.curWhitelist != onWhitelist) { + uidRec.curWhitelist = onWhitelist; + updateOomAdjLocked(); + } + } + final void trimApplications() { synchronized (this) { int i; diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java index 28817878373b..494aaa766b94 100644 --- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java @@ -314,7 +314,8 @@ class ActivityMetricsLogger { builder.setPackageName(info.launchedActivity.packageName); builder.setType(type); builder.addTaggedData(FIELD_CLASS_NAME, info.launchedActivity.info.name); - if (info.launchedActivity.launchedFromPackage != null) { + final boolean isInstantApp = info.launchedActivity.info.applicationInfo.isInstantApp(); + if (isInstantApp && info.launchedActivity.launchedFromPackage != null) { builder.addTaggedData(APP_TRANSITION_CALLING_PACKAGE_NAME, info.launchedActivity.launchedFromPackage); } @@ -323,8 +324,7 @@ class ActivityMetricsLogger { info.launchedActivity.info.launchToken); info.launchedActivity.info.launchToken = null; } - builder.addTaggedData(APP_TRANSITION_IS_EPHEMERAL, - info.launchedActivity.info.applicationInfo.isInstantApp() ? 1 : 0); + builder.addTaggedData(APP_TRANSITION_IS_EPHEMERAL, isInstantApp ? 1 : 0); builder.addTaggedData(APP_TRANSITION_DEVICE_UPTIME_SECONDS, mCurrentTransitionDeviceUptime); builder.addTaggedData(APP_TRANSITION_DELAY_MS, mCurrentTransitionDelayMs); diff --git a/services/core/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java index 02ec07561f4f..c9c1d005a85a 100644 --- a/services/core/java/com/android/server/am/AppErrorDialog.java +++ b/services/core/java/com/android/server/am/AppErrorDialog.java @@ -148,18 +148,7 @@ final class AppErrorDialog extends BaseErrorDialog implements View.OnClickListen private final Handler mHandler = new Handler() { public void handleMessage(Message msg) { - final int result = msg.what; - - synchronized (mService) { - if (mProc != null && mProc.crashDialog == AppErrorDialog.this) { - mProc.crashDialog = null; - } - } - mResult.set(result); - - // Make sure we don't have time timeout still hanging around. - removeMessages(TIMEOUT); - + setResult(msg.what); dismiss(); } }; @@ -168,11 +157,23 @@ final class AppErrorDialog extends BaseErrorDialog implements View.OnClickListen public void dismiss() { if (!mResult.mHasResult) { // We are dismissing and the result has not been set...go ahead and set. - mResult.set(FORCE_QUIT); + setResult(FORCE_QUIT); } super.dismiss(); } + private void setResult(int result) { + synchronized (mService) { + if (mProc != null && mProc.crashDialog == AppErrorDialog.this) { + mProc.crashDialog = null; + } + } + mResult.set(result); + + // Make sure we don't have time timeout still hanging around. + mHandler.removeMessages(TIMEOUT); + } + @Override public void onClick(View v) { switch (v.getId()) { diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index baa71d708caa..349180fd28a9 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -155,8 +155,6 @@ public final class BroadcastQueue { static final int BROADCAST_INTENT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG; static final int BROADCAST_TIMEOUT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 1; - static final int SCHEDULE_TEMP_WHITELIST_MSG - = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 2; final BroadcastHandler mHandler; @@ -178,13 +176,6 @@ public final class BroadcastQueue { broadcastTimeoutLocked(true); } } break; - case SCHEDULE_TEMP_WHITELIST_MSG: { - DeviceIdleController.LocalService dic = mService.mLocalDeviceIdleController; - if (dic != null) { - dic.addPowerSaveTempWhitelistAppDirect(UserHandle.getAppId(msg.arg1), - msg.arg2, true, (String)msg.obj); - } - } break; } } } @@ -789,12 +780,11 @@ public final class BroadcastQueue { if (r.intent.getAction() != null) { b.append(r.intent.getAction()); } else if (r.intent.getComponent() != null) { - b.append(r.intent.getComponent().flattenToShortString()); + r.intent.getComponent().appendShortString(b); } else if (r.intent.getData() != null) { b.append(r.intent.getData()); } - mHandler.obtainMessage(SCHEDULE_TEMP_WHITELIST_MSG, uid, (int)duration, b.toString()) - .sendToTarget(); + mService.tempWhitelistUidLocked(uid, duration, b.toString()); } /** diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java index c697f2876c65..a580d4bdde5e 100644 --- a/services/core/java/com/android/server/am/PendingIntentRecord.java +++ b/services/core/java/com/android/server/am/PendingIntentRecord.java @@ -237,14 +237,6 @@ final class PendingIntentRecord extends IIntentSender.Stub { if (intent != null) intent.setDefusable(true); if (options != null) options.setDefusable(true); - if (whitelistDuration > 0 && !canceled) { - // Must call before acquiring the lock. It's possible the method return before sending - // the intent due to some validations inside the lock, in which case the UID shouldn't - // be whitelisted, but since the whitelist is temporary, that would be ok. - owner.tempWhitelistAppForPowerSave(Binder.getCallingPid(), Binder.getCallingUid(), uid, - whitelistDuration); - } - synchronized (owner) { final ActivityContainer activityContainer = (ActivityContainer)container; if (activityContainer != null && activityContainer.mParentActivity != null && @@ -279,6 +271,22 @@ final class PendingIntentRecord extends IIntentSender.Stub { resolvedType = key.requestResolvedType; } + if (whitelistDuration > 0) { + StringBuilder tag = new StringBuilder(64); + tag.append("pendingintent:"); + UserHandle.formatUid(tag, Binder.getCallingUid()); + tag.append(":"); + if (finalIntent.getAction() != null) { + tag.append(finalIntent.getAction()); + } else if (finalIntent.getComponent() != null) { + finalIntent.getComponent().appendShortString(tag); + } else if (finalIntent.getData() != null) { + tag.append(finalIntent.getData()); + } + owner.tempWhitelistForPendingIntentLocked(Binder.getCallingPid(), + Binder.getCallingUid(), uid, whitelistDuration, tag.toString()); + } + final long origId = Binder.clearCallingIdentity(); boolean sendFinish = finishedReceiver != null; diff --git a/services/core/java/com/android/server/job/GrantedUriPermissions.java b/services/core/java/com/android/server/job/GrantedUriPermissions.java new file mode 100644 index 000000000000..e413d8d1d8c0 --- /dev/null +++ b/services/core/java/com/android/server/job/GrantedUriPermissions.java @@ -0,0 +1,156 @@ +/* + * 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.job; + +import android.app.IActivityManager; +import android.content.ClipData; +import android.content.ContentProvider; +import android.content.Intent; +import android.net.Uri; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.UserHandle; +import android.util.Slog; + +import java.io.PrintWriter; +import java.util.ArrayList; + +public class GrantedUriPermissions { + private final int mGrantFlags; + private final int mSourceUserId; + private final String mTag; + private final IBinder mPermissionOwner; + private final ArrayList<Uri> mUris = new ArrayList<>(); + + private GrantedUriPermissions(IActivityManager am, int grantFlags, int uid, String tag) + throws RemoteException { + mGrantFlags = grantFlags; + mSourceUserId = UserHandle.getUserId(uid); + mTag = tag; + mPermissionOwner = am.newUriPermissionOwner("job: " + tag); + } + + public void revoke(IActivityManager am) { + for (int i = mUris.size()-1; i >= 0; i--) { + try { + am.revokeUriPermissionFromOwner(mPermissionOwner, mUris.get(i), + mGrantFlags, mSourceUserId); + } catch (RemoteException e) { + } + } + mUris.clear(); + } + + public static boolean checkGrantFlags(int grantFlags) { + return (grantFlags & (Intent.FLAG_GRANT_WRITE_URI_PERMISSION + |Intent.FLAG_GRANT_READ_URI_PERMISSION)) != 0; + } + + public static GrantedUriPermissions createFromIntent(IActivityManager am, Intent intent, + int sourceUid, String targetPackage, int targetUserId, String tag) { + int grantFlags = intent.getFlags(); + if (!checkGrantFlags(grantFlags)) { + return null; + } + + GrantedUriPermissions perms = null; + + Uri data = intent.getData(); + if (data != null) { + perms = grantUri(am, data, sourceUid, targetPackage, targetUserId, grantFlags, tag, + perms); + } + + ClipData clip = intent.getClipData(); + if (clip != null) { + perms = grantClip(am, clip, sourceUid, targetPackage, targetUserId, grantFlags, tag, + perms); + } + + return perms; + } + + public static GrantedUriPermissions createFromClip(IActivityManager am, ClipData clip, + int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag) { + if (!checkGrantFlags(grantFlags)) { + return null; + } + GrantedUriPermissions perms = null; + if (clip != null) { + perms = grantClip(am, clip, sourceUid, targetPackage, targetUserId, grantFlags, + tag, perms); + } + return perms; + } + + private static GrantedUriPermissions grantClip(IActivityManager am, ClipData clip, + int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag, + GrantedUriPermissions curPerms) { + final int N = clip.getItemCount(); + for (int i = 0; i < N; i++) { + curPerms = grantItem(am, clip.getItemAt(i), sourceUid, targetPackage, targetUserId, + grantFlags, tag, curPerms); + } + return curPerms; + } + + private static GrantedUriPermissions grantUri(IActivityManager am, Uri uri, + int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag, + GrantedUriPermissions curPerms) { + try { + int sourceUserId = ContentProvider.getUserIdFromUri(uri, + UserHandle.getUserId(sourceUid)); + uri = ContentProvider.getUriWithoutUserId(uri); + if (curPerms == null) { + curPerms = new GrantedUriPermissions(am, grantFlags, sourceUid, tag); + } + am.grantUriPermissionFromOwner(curPerms.mPermissionOwner, sourceUid, targetPackage, + uri, grantFlags, sourceUserId, targetUserId); + curPerms.mUris.add(uri); + } catch (RemoteException e) { + Slog.e("JobScheduler", "AM dead"); + } + return curPerms; + } + + private static GrantedUriPermissions grantItem(IActivityManager am, ClipData.Item item, + int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag, + GrantedUriPermissions curPerms) { + if (item.getUri() != null) { + curPerms = grantUri(am, item.getUri(), sourceUid, targetPackage, targetUserId, + grantFlags, tag, curPerms); + } + Intent intent = item.getIntent(); + if (intent != null && intent.getData() != null) { + curPerms = grantUri(am, intent.getData(), sourceUid, targetPackage, targetUserId, + grantFlags, tag, curPerms); + } + return curPerms; + } + + // Dumpsys infrastructure + public void dump(PrintWriter pw, String prefix) { + pw.print(prefix); pw.print("mGrantFlags=0x"); pw.print(Integer.toHexString(mGrantFlags)); + pw.print(" mSourceUserId="); pw.println(mSourceUserId); + pw.print(prefix); pw.print("mTag="); pw.println(mTag); + pw.print(prefix); pw.print("mPermissionOwner="); pw.println(mPermissionOwner); + for (int i = 0; i < mUris.size(); i++) { + pw.print(prefix); pw.print("#"); pw.print(i); pw.print(": "); + pw.println(mUris.get(i)); + } + } +} diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index d01de3c9157d..c8bfa345af10 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -601,7 +601,7 @@ public final class JobSchedulerService extends com.android.server.SystemService // Fast path: we are adding work to an existing job, and the JobInfo is not // changing. We can just directly enqueue this work in to the job. if (toCancel.getJob().equals(job)) { - toCancel.enqueueWorkLocked(work); + toCancel.enqueueWorkLocked(ActivityManager.getService(), work); return JobScheduler.RESULT_SUCCESS; } } @@ -625,7 +625,7 @@ public final class JobSchedulerService extends com.android.server.SystemService } if (work != null) { // If work has been supplied, enqueue it into the new job. - jobStatus.enqueueWorkLocked(work); + jobStatus.enqueueWorkLocked(ActivityManager.getService(), work); } startTrackingJobLocked(jobStatus, toCancel); mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget(); @@ -758,7 +758,7 @@ public final class JobSchedulerService extends com.android.server.SystemService final JobStatus executing = jsc.getRunningJob(); if (executing != null && (executing.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) == 0) { - jsc.cancelExecutingJob(JobParameters.REASON_DEVICE_IDLE); + jsc.cancelExecutingJobLocked(JobParameters.REASON_DEVICE_IDLE); } } } else { @@ -921,7 +921,7 @@ public final class JobSchedulerService extends com.android.server.SystemService private boolean stopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean writeBack) { // Deal with any remaining work items in the old job. - jobStatus.stopTrackingJobLocked(incomingJob); + jobStatus.stopTrackingJobLocked(ActivityManager.getService(), incomingJob); // Remove from store as well as controllers. final boolean removed = mJobs.remove(jobStatus, writeBack); @@ -939,7 +939,7 @@ public final class JobSchedulerService extends com.android.server.SystemService JobServiceContext jsc = mActiveServices.get(i); final JobStatus executing = jsc.getRunningJob(); if (executing != null && executing.matches(job.getUid(), job.getJobId())) { - jsc.cancelExecutingJob(reason); + jsc.cancelExecutingJobLocked(reason); return true; } } @@ -1071,9 +1071,16 @@ public final class JobSchedulerService extends com.android.server.SystemService if (DEBUG) { Slog.d(TAG, "Completed " + jobStatus + ", reschedule=" + needsReschedule); } + + // If the job wants to be rescheduled, we first need to make the next upcoming + // job so we can transfer any appropriate state over from the previous job when + // we stop it. + final JobStatus rescheduledJob = needsReschedule + ? getRescheduleJobForFailureLocked(jobStatus) : null; + // Do not write back immediately if this is a periodic job. The job may get lost if system // shuts down before it is added back. - if (!stopTrackingJobLocked(jobStatus, null, !jobStatus.getJob().isPeriodic())) { + if (!stopTrackingJobLocked(jobStatus, rescheduledJob, !jobStatus.getJob().isPeriodic())) { if (DEBUG) { Slog.d(TAG, "Could not find job to remove. Was job removed while executing?"); } @@ -1082,18 +1089,14 @@ public final class JobSchedulerService extends com.android.server.SystemService mHandler.obtainMessage(MSG_CHECK_JOB_GREEDY).sendToTarget(); return; } - // Note: there is a small window of time in here where, when rescheduling a job, - // we will stop monitoring its content providers. This should be fixed by stopping - // the old job after scheduling the new one, but since we have no lock held here - // that may cause ordering problems if the app removes jobStatus while in here. - if (needsReschedule) { - JobStatus rescheduled = getRescheduleJobForFailureLocked(jobStatus); + + if (rescheduledJob != null) { try { - rescheduled.prepareLocked(ActivityManager.getService()); + rescheduledJob.prepareLocked(ActivityManager.getService()); } catch (SecurityException e) { - Slog.w(TAG, "Unable to regrant job permissions for " + rescheduled); + Slog.w(TAG, "Unable to regrant job permissions for " + rescheduledJob); } - startTrackingJobLocked(rescheduled, jobStatus); + startTrackingJobLocked(rescheduledJob, jobStatus); } else if (jobStatus.getJob().isPeriodic()) { JobStatus rescheduledPeriodic = getRescheduleJobForPeriodic(jobStatus); try { @@ -1561,7 +1564,7 @@ public final class JobSchedulerService extends com.android.server.SystemService Slog.d(TAG, "preempting job: " + mActiveServices.get(i).getRunningJob()); } // preferredUid will be set to uid of currently running job. - mActiveServices.get(i).preemptExecutingJob(); + mActiveServices.get(i).preemptExecutingJobLocked(); preservePreferredUid = true; } else { final JobStatus pendingJob = contextIdToJobMap[i]; diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java index c7ef0e26971f..9144966da409 100644 --- a/services/core/java/com/android/server/job/JobServiceContext.java +++ b/services/core/java/com/android/server/job/JobServiceContext.java @@ -44,8 +44,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IBatteryStats; import com.android.server.job.controllers.JobStatus; -import java.util.concurrent.atomic.AtomicBoolean; - /** * Handles client binding and lifecycle of a job. Jobs execute one at a time on an instance of this * class. @@ -56,19 +54,15 @@ import java.util.concurrent.atomic.AtomicBoolean; * job lands, and again when it is complete. * - Cancelling is trickier, because there are also interactions from the client. It's possible * the {@link com.android.server.job.JobServiceContext.JobServiceHandler} tries to process a - * {@link #MSG_CANCEL} after the client has already finished. This is handled by having - * {@link com.android.server.job.JobServiceContext.JobServiceHandler#handleCancelH} check whether + * {@link #doCancelLocked(int)} after the client has already finished. This is handled by having + * {@link com.android.server.job.JobServiceContext.JobServiceHandler#handleCancelLocked} check whether * the context is still valid. - * To mitigate this, tearing down the context removes all messages from the handler, including any - * tardy {@link #MSG_CANCEL}s. Additionally, we avoid sending duplicate onStopJob() + * To mitigate this, we avoid sending duplicate onStopJob() * calls to the client after they've specified jobFinished(). */ public class JobServiceContext extends IJobCallback.Stub implements ServiceConnection { private static final boolean DEBUG = JobSchedulerService.DEBUG; private static final String TAG = "JobServiceContext"; - /** Define the maximum # of jobs allowed to run on a service at once. */ - private static final int defaultMaxActiveJobsPerService = - ActivityManager.isLowRamDeviceStatic() ? 1 : 3; /** Amount of time a job is allowed to execute for before being considered timed-out. */ private static final long EXECUTING_TIMESLICE_MILLIS = 10 * 60 * 1000; // 10mins. /** Amount of time the JobScheduler waits for the initial service launch+bind. */ @@ -90,14 +84,6 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne // Messages that result from interactions with the client service. /** System timed out waiting for a response. */ private static final int MSG_TIMEOUT = 0; - /** Received a callback from client. */ - private static final int MSG_CALLBACK = 1; - /** Run through list and start any ready jobs.*/ - private static final int MSG_SERVICE_BOUND = 2; - /** Cancel a job. */ - private static final int MSG_CANCEL = 3; - /** Shutdown the job. Used when the client crashes and we can't die gracefully.*/ - private static final int MSG_SHUTDOWN_EXECUTION = 4; public static final int NO_PREFERRED_UID = -1; @@ -115,7 +101,7 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne private JobParameters mParams; @VisibleForTesting int mVerb; - private AtomicBoolean mCancelled = new AtomicBoolean(); + private boolean mCancelled; /** * All the information maintained about the job currently being executed. @@ -245,14 +231,12 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne } /** Called externally when a job that was scheduled for execution should be cancelled. */ - void cancelExecutingJob(int reason) { - mCallbackHandler.obtainMessage(MSG_CANCEL, reason, 0 /* unused */).sendToTarget(); + void cancelExecutingJobLocked(int reason) { + doCancelLocked(reason); } - void preemptExecutingJob() { - Message m = mCallbackHandler.obtainMessage(MSG_CANCEL); - m.arg1 = JobParameters.REASON_PREEMPT; - m.sendToTarget(); + void preemptExecutingJobLocked() { + doCancelLocked(JobParameters.REASON_PREEMPT); } int getPreferredUid() { @@ -273,59 +257,54 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne @Override public void jobFinished(int jobId, boolean reschedule) { - if (!verifyCallingUid()) { - return; - } - mCallbackHandler.obtainMessage(MSG_CALLBACK, jobId, reschedule ? 1 : 0) - .sendToTarget(); + doCallback(reschedule); } @Override public void acknowledgeStopMessage(int jobId, boolean reschedule) { - if (!verifyCallingUid()) { - return; - } - mCallbackHandler.obtainMessage(MSG_CALLBACK, jobId, reschedule ? 1 : 0) - .sendToTarget(); + doCallback(reschedule); } @Override public void acknowledgeStartMessage(int jobId, boolean ongoing) { - if (!verifyCallingUid()) { - return; - } - mCallbackHandler.obtainMessage(MSG_CALLBACK, jobId, ongoing ? 1 : 0).sendToTarget(); + doCallback(ongoing); } @Override public JobWorkItem dequeueWork(int jobId) { - if (!verifyCallingUid()) { - throw new SecurityException("Bad calling uid: " + Binder.getCallingUid()); - } - JobWorkItem work = null; - boolean stillWorking = false; - synchronized (mLock) { - if (mRunningJob != null) { - work = mRunningJob.dequeueWorkLocked(); - stillWorking = mRunningJob.hasExecutingWorkLocked(); + final int callingUid = Binder.getCallingUid(); + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + if (!verifyCallingUidLocked(callingUid)) { + throw new SecurityException("Bad calling uid: " + callingUid); + } + + final JobWorkItem work = mRunningJob.dequeueWorkLocked(); + if (work == null && !mRunningJob.hasExecutingWorkLocked()) { + // This will finish the job. + doCallbackLocked(false); + } + return work; } + } finally { + Binder.restoreCallingIdentity(ident); } - if (work == null && !stillWorking) { - jobFinished(jobId, false); - } - return work; } @Override public boolean completeWork(int jobId, int workId) { - if (!verifyCallingUid()) { - throw new SecurityException("Bad calling uid: " + Binder.getCallingUid()); - } - synchronized (mLock) { - if (mRunningJob != null) { - return mRunningJob.completeWorkLocked(workId); + final int callingUid = Binder.getCallingUid(); + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + if (!verifyCallingUidLocked(callingUid)) { + throw new SecurityException("Bad calling uid: " + callingUid); + } + return mRunningJob.completeWorkLocked(ActivityManager.getService(), workId); } - return false; + } finally { + Binder.restoreCallingIdentity(ident); } } @@ -344,20 +323,20 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne // looper and at this point we can't get any binder callbacks from the client. Better // safe than sorry. runningJob = mRunningJob; - } - if (runningJob == null || !name.equals(runningJob.getServiceComponent())) { - mCallbackHandler.obtainMessage(MSG_SHUTDOWN_EXECUTION).sendToTarget(); - return; - } - this.service = IJobService.Stub.asInterface(service); - final PowerManager pm = - (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); - PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, - runningJob.getTag()); - wl.setWorkSource(new WorkSource(runningJob.getSourceUid())); - wl.setReferenceCounted(false); - wl.acquire(); - synchronized (mLock) { + + if (runningJob == null || !name.equals(runningJob.getServiceComponent())) { + closeAndCleanupJobLocked(true /* needsReschedule */); + return; + } + this.service = IJobService.Stub.asInterface(service); + final PowerManager pm = + (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, + runningJob.getTag()); + wl.setWorkSource(new WorkSource(runningJob.getSourceUid())); + wl.setReferenceCounted(false); + wl.acquire(); + // We use a new wakelock instance per job. In rare cases there is a race between // teardown following job completion/cancellation and new job service spin-up // such that if we simply assign mWakeLock to be the new instance, we orphan @@ -369,14 +348,16 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne mWakeLock.release(); } mWakeLock = wl; + doServiceBoundLocked(); } - mCallbackHandler.obtainMessage(MSG_SERVICE_BOUND).sendToTarget(); } /** If the client service crashes we reschedule this job and clean up. */ @Override public void onServiceDisconnected(ComponentName name) { - mCallbackHandler.obtainMessage(MSG_SHUTDOWN_EXECUTION).sendToTarget(); + synchronized (mLock) { + closeAndCleanupJobLocked(true /* needsReschedule */); + } } /** @@ -384,22 +365,18 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne * whether the client exercising the callback is the client we expect. * @return True if the binder calling is coming from the client we expect. */ - private boolean verifyCallingUid() { - synchronized (mLock) { - if (mRunningJob == null || Binder.getCallingUid() != mRunningJob.getUid()) { - if (DEBUG) { - Slog.d(TAG, "Stale callback received, ignoring."); - } - return false; + private boolean verifyCallingUidLocked(final int callingUid) { + if (mRunningJob == null || callingUid != mRunningJob.getUid()) { + if (DEBUG) { + Slog.d(TAG, "Stale callback received, ignoring."); } - return true; + return false; } + return true; } /** - * Handles the lifecycle of the JobService binding/callbacks, etc. The convention within this - * class is to append 'H' to each function name that can only be called on this handler. This - * isn't strictly necessary because all of these functions are private, but helps clarity. + * Scheduling of async messages (basically timeouts at this point). */ private class JobServiceHandler extends Handler { JobServiceHandler(Looper looper) { @@ -409,293 +386,277 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne @Override public void handleMessage(Message message) { switch (message.what) { - case MSG_SERVICE_BOUND: - doServiceBound(); - break; - case MSG_CALLBACK: - doCallback(message.arg2); - break; - case MSG_CANCEL: - doCancel(message.arg1); - break; case MSG_TIMEOUT: synchronized (mLock) { - handleOpTimeoutH(); + handleOpTimeoutLocked(); } break; - case MSG_SHUTDOWN_EXECUTION: - closeAndCleanupJobH(true /* needsReschedule */); - break; default: Slog.e(TAG, "Unrecognised message: " + message); } } + } - void doServiceBound() { + void doServiceBoundLocked() { + removeOpTimeOutLocked(); + handleServiceBoundLocked(); + } + + void doCallback(boolean reschedule) { + final int callingUid = Binder.getCallingUid(); + final long ident = Binder.clearCallingIdentity(); + try { synchronized (mLock) { - removeOpTimeOutLocked(); - handleServiceBoundH(); + if (!verifyCallingUidLocked(callingUid)) { + return; + } + doCallbackLocked(reschedule); } + } finally { + Binder.restoreCallingIdentity(ident); } + } - void doCallback(int arg2) { - synchronized (mLock) { - if (DEBUG) { - Slog.d(TAG, "MSG_CALLBACK of : " + mRunningJob - + " v:" + VERB_STRINGS[mVerb]); - } - removeOpTimeOutLocked(); + void doCallbackLocked(boolean reschedule) { + if (DEBUG) { + Slog.d(TAG, "doCallback of : " + mRunningJob + + " v:" + VERB_STRINGS[mVerb]); + } + removeOpTimeOutLocked(); - if (mVerb == VERB_STARTING) { - final boolean workOngoing = arg2 == 1; - handleStartedH(workOngoing); - } else if (mVerb == VERB_EXECUTING || - mVerb == VERB_STOPPING) { - final boolean reschedule = arg2 == 1; - handleFinishedH(reschedule); - } else { - if (DEBUG) { - Slog.d(TAG, "Unrecognised callback: " + mRunningJob); - } - } + if (mVerb == VERB_STARTING) { + handleStartedLocked(reschedule); + } else if (mVerb == VERB_EXECUTING || + mVerb == VERB_STOPPING) { + handleFinishedLocked(reschedule); + } else { + if (DEBUG) { + Slog.d(TAG, "Unrecognised callback: " + mRunningJob); } } + } - void doCancel(int arg1) { - synchronized (mLock) { - if (mVerb == VERB_FINISHED) { - if (DEBUG) { - Slog.d(TAG, - "Trying to process cancel for torn-down context, ignoring."); - } - return; - } - mParams.setStopReason(arg1); - if (arg1 == JobParameters.REASON_PREEMPT) { - mPreferredUid = mRunningJob != null ? mRunningJob.getUid() : - NO_PREFERRED_UID; - } - handleCancelH(); + void doCancelLocked(int arg1) { + if (mVerb == VERB_FINISHED) { + if (DEBUG) { + Slog.d(TAG, + "Trying to process cancel for torn-down context, ignoring."); } - + return; + } + mParams.setStopReason(arg1); + if (arg1 == JobParameters.REASON_PREEMPT) { + mPreferredUid = mRunningJob != null ? mRunningJob.getUid() : + NO_PREFERRED_UID; } + handleCancelLocked(); + } - /** Start the job on the service. */ - private void handleServiceBoundH() { + /** Start the job on the service. */ + private void handleServiceBoundLocked() { + if (DEBUG) { + Slog.d(TAG, "handleServiceBound for " + mRunningJob.toShortString()); + } + if (mVerb != VERB_BINDING) { + Slog.e(TAG, "Sending onStartJob for a job that isn't pending. " + + VERB_STRINGS[mVerb]); + closeAndCleanupJobLocked(false /* reschedule */); + return; + } + if (mCancelled) { if (DEBUG) { - Slog.d(TAG, "MSG_SERVICE_BOUND for " + mRunningJob.toShortString()); - } - if (mVerb != VERB_BINDING) { - Slog.e(TAG, "Sending onStartJob for a job that isn't pending. " - + VERB_STRINGS[mVerb]); - closeAndCleanupJobH(false /* reschedule */); - return; - } - if (mCancelled.get()) { - if (DEBUG) { - Slog.d(TAG, "Job cancelled while waiting for bind to complete. " - + mRunningJob); - } - closeAndCleanupJobH(true /* reschedule */); - return; - } - try { - mVerb = VERB_STARTING; - scheduleOpTimeOutLocked(); - service.startJob(mParams); - } catch (Exception e) { - // We catch 'Exception' because client-app malice or bugs might induce a wide - // range of possible exception-throw outcomes from startJob() and its handling - // of the client's ParcelableBundle extras. - Slog.e(TAG, "Error sending onStart message to '" + - mRunningJob.getServiceComponent().getShortClassName() + "' ", e); + Slog.d(TAG, "Job cancelled while waiting for bind to complete. " + + mRunningJob); } + closeAndCleanupJobLocked(true /* reschedule */); + return; } + try { + mVerb = VERB_STARTING; + scheduleOpTimeOutLocked(); + service.startJob(mParams); + } catch (Exception e) { + // We catch 'Exception' because client-app malice or bugs might induce a wide + // range of possible exception-throw outcomes from startJob() and its handling + // of the client's ParcelableBundle extras. + Slog.e(TAG, "Error sending onStart message to '" + + mRunningJob.getServiceComponent().getShortClassName() + "' ", e); + } + } - /** - * State behaviours. - * VERB_STARTING -> Successful start, change job to VERB_EXECUTING and post timeout. - * _PENDING -> Error - * _EXECUTING -> Error - * _STOPPING -> Error - */ - private void handleStartedH(boolean workOngoing) { - switch (mVerb) { - case VERB_STARTING: - mVerb = VERB_EXECUTING; - if (!workOngoing) { - // Job is finished already so fast-forward to handleFinished. - handleFinishedH(false); - return; - } - if (mCancelled.get()) { - if (DEBUG) { - Slog.d(TAG, "Job cancelled while waiting for onStartJob to complete."); - } - // Cancelled *while* waiting for acknowledgeStartMessage from client. - handleCancelH(); - return; + /** + * State behaviours. + * VERB_STARTING -> Successful start, change job to VERB_EXECUTING and post timeout. + * _PENDING -> Error + * _EXECUTING -> Error + * _STOPPING -> Error + */ + private void handleStartedLocked(boolean workOngoing) { + switch (mVerb) { + case VERB_STARTING: + mVerb = VERB_EXECUTING; + if (!workOngoing) { + // Job is finished already so fast-forward to handleFinished. + handleFinishedLocked(false); + return; + } + if (mCancelled) { + if (DEBUG) { + Slog.d(TAG, "Job cancelled while waiting for onStartJob to complete."); } - scheduleOpTimeOutLocked(); - break; - default: - Slog.e(TAG, "Handling started job but job wasn't starting! Was " - + VERB_STRINGS[mVerb] + "."); + // Cancelled *while* waiting for acknowledgeStartMessage from client. + handleCancelLocked(); return; - } + } + scheduleOpTimeOutLocked(); + break; + default: + Slog.e(TAG, "Handling started job but job wasn't starting! Was " + + VERB_STRINGS[mVerb] + "."); + return; } + } - /** - * VERB_EXECUTING -> Client called jobFinished(), clean up and notify done. - * _STOPPING -> Successful finish, clean up and notify done. - * _STARTING -> Error - * _PENDING -> Error - */ - private void handleFinishedH(boolean reschedule) { - switch (mVerb) { - case VERB_EXECUTING: - case VERB_STOPPING: - closeAndCleanupJobH(reschedule); - break; - default: - Slog.e(TAG, "Got an execution complete message for a job that wasn't being" + - "executed. Was " + VERB_STRINGS[mVerb] + "."); - } + /** + * VERB_EXECUTING -> Client called jobFinished(), clean up and notify done. + * _STOPPING -> Successful finish, clean up and notify done. + * _STARTING -> Error + * _PENDING -> Error + */ + private void handleFinishedLocked(boolean reschedule) { + switch (mVerb) { + case VERB_EXECUTING: + case VERB_STOPPING: + closeAndCleanupJobLocked(reschedule); + break; + default: + Slog.e(TAG, "Got an execution complete message for a job that wasn't being" + + "executed. Was " + VERB_STRINGS[mVerb] + "."); } + } - /** - * A job can be in various states when a cancel request comes in: - * VERB_BINDING -> Cancelled before bind completed. Mark as cancelled and wait for - * {@link #onServiceConnected(android.content.ComponentName, android.os.IBinder)} - * _STARTING -> Mark as cancelled and wait for - * {@link JobServiceContext#acknowledgeStartMessage(int, boolean)} - * _EXECUTING -> call {@link #sendStopMessageH}}, but only if there are no callbacks - * in the message queue. - * _ENDING -> No point in doing anything here, so we ignore. - */ - private void handleCancelH() { - if (JobSchedulerService.DEBUG) { - Slog.d(TAG, "Handling cancel for: " + mRunningJob.getJobId() + " " - + VERB_STRINGS[mVerb]); - } - switch (mVerb) { - case VERB_BINDING: - case VERB_STARTING: - mCancelled.set(true); - break; - case VERB_EXECUTING: - if (hasMessages(MSG_CALLBACK)) { - // If the client has called jobFinished, ignore this cancel. - return; - } - sendStopMessageH(); - break; - case VERB_STOPPING: - // Nada. - break; - default: - Slog.e(TAG, "Cancelling a job without a valid verb: " + mVerb); - break; - } + /** + * A job can be in various states when a cancel request comes in: + * VERB_BINDING -> Cancelled before bind completed. Mark as cancelled and wait for + * {@link #onServiceConnected(android.content.ComponentName, android.os.IBinder)} + * _STARTING -> Mark as cancelled and wait for + * {@link JobServiceContext#acknowledgeStartMessage(int, boolean)} + * _EXECUTING -> call {@link #sendStopMessageLocked}}, but only if there are no callbacks + * in the message queue. + * _ENDING -> No point in doing anything here, so we ignore. + */ + private void handleCancelLocked() { + if (JobSchedulerService.DEBUG) { + Slog.d(TAG, "Handling cancel for: " + mRunningJob.getJobId() + " " + + VERB_STRINGS[mVerb]); } + switch (mVerb) { + case VERB_BINDING: + case VERB_STARTING: + mCancelled = true; + break; + case VERB_EXECUTING: + sendStopMessageLocked(); + break; + case VERB_STOPPING: + // Nada. + break; + default: + Slog.e(TAG, "Cancelling a job without a valid verb: " + mVerb); + break; + } + } - /** Process MSG_TIMEOUT here. */ - private void handleOpTimeoutH() { - switch (mVerb) { - case VERB_BINDING: - Slog.e(TAG, "Time-out while trying to bind " + mRunningJob.toShortString() + - ", dropping."); - closeAndCleanupJobH(false /* needsReschedule */); - break; - case VERB_STARTING: - // Client unresponsive - wedged or failed to respond in time. We don't really - // know what happened so let's log it and notify the JobScheduler - // FINISHED/NO-RETRY. - Slog.e(TAG, "No response from client for onStartJob '" + - mRunningJob.toShortString()); - closeAndCleanupJobH(false /* needsReschedule */); - break; - case VERB_STOPPING: - // At least we got somewhere, so fail but ask the JobScheduler to reschedule. - Slog.e(TAG, "No response from client for onStopJob, '" + - mRunningJob.toShortString()); - closeAndCleanupJobH(true /* needsReschedule */); - break; - case VERB_EXECUTING: - // Not an error - client ran out of time. - Slog.i(TAG, "Client timed out while executing (no jobFinished received)." + - " sending onStop. " + mRunningJob.toShortString()); - mParams.setStopReason(JobParameters.REASON_TIMEOUT); - sendStopMessageH(); - break; - default: - Slog.e(TAG, "Handling timeout for an invalid job state: " + - mRunningJob.toShortString() + ", dropping."); - closeAndCleanupJobH(false /* needsReschedule */); - } + /** Process MSG_TIMEOUT here. */ + private void handleOpTimeoutLocked() { + switch (mVerb) { + case VERB_BINDING: + Slog.e(TAG, "Time-out while trying to bind " + mRunningJob.toShortString() + + ", dropping."); + closeAndCleanupJobLocked(false /* needsReschedule */); + break; + case VERB_STARTING: + // Client unresponsive - wedged or failed to respond in time. We don't really + // know what happened so let's log it and notify the JobScheduler + // FINISHED/NO-RETRY. + Slog.e(TAG, "No response from client for onStartJob '" + + mRunningJob.toShortString()); + closeAndCleanupJobLocked(false /* needsReschedule */); + break; + case VERB_STOPPING: + // At least we got somewhere, so fail but ask the JobScheduler to reschedule. + Slog.e(TAG, "No response from client for onStopJob, '" + + mRunningJob.toShortString()); + closeAndCleanupJobLocked(true /* needsReschedule */); + break; + case VERB_EXECUTING: + // Not an error - client ran out of time. + Slog.i(TAG, "Client timed out while executing (no jobFinished received)." + + " sending onStop. " + mRunningJob.toShortString()); + mParams.setStopReason(JobParameters.REASON_TIMEOUT); + sendStopMessageLocked(); + break; + default: + Slog.e(TAG, "Handling timeout for an invalid job state: " + + mRunningJob.toShortString() + ", dropping."); + closeAndCleanupJobLocked(false /* needsReschedule */); } + } - /** - * Already running, need to stop. Will switch {@link #mVerb} from VERB_EXECUTING -> - * VERB_STOPPING. - */ - private void sendStopMessageH() { - removeOpTimeOutLocked(); - if (mVerb != VERB_EXECUTING) { - Slog.e(TAG, "Sending onStopJob for a job that isn't started. " + mRunningJob); - closeAndCleanupJobH(false /* reschedule */); - return; - } - try { - mVerb = VERB_STOPPING; - scheduleOpTimeOutLocked(); - service.stopJob(mParams); - } catch (RemoteException e) { - Slog.e(TAG, "Error sending onStopJob to client.", e); - // The job's host app apparently crashed during the job, so we should reschedule. - closeAndCleanupJobH(true /* reschedule */); - } + /** + * Already running, need to stop. Will switch {@link #mVerb} from VERB_EXECUTING -> + * VERB_STOPPING. + */ + private void sendStopMessageLocked() { + removeOpTimeOutLocked(); + if (mVerb != VERB_EXECUTING) { + Slog.e(TAG, "Sending onStopJob for a job that isn't started. " + mRunningJob); + closeAndCleanupJobLocked(false /* reschedule */); + return; + } + try { + mVerb = VERB_STOPPING; + scheduleOpTimeOutLocked(); + service.stopJob(mParams); + } catch (RemoteException e) { + Slog.e(TAG, "Error sending onStopJob to client.", e); + // The job's host app apparently crashed during the job, so we should reschedule. + closeAndCleanupJobLocked(true /* reschedule */); } + } - /** - * The provided job has finished, either by calling - * {@link android.app.job.JobService#jobFinished(android.app.job.JobParameters, boolean)} - * or from acknowledging the stop message we sent. Either way, we're done tracking it and - * we want to clean up internally. - */ - private void closeAndCleanupJobH(boolean reschedule) { - final JobStatus completedJob; - synchronized (mLock) { - if (mVerb == VERB_FINISHED) { - return; - } - completedJob = mRunningJob; - mJobPackageTracker.noteInactive(completedJob); - try { - mBatteryStats.noteJobFinish(mRunningJob.getBatteryName(), - mRunningJob.getSourceUid()); - } catch (RemoteException e) { - // Whatever. - } - if (mWakeLock != null) { - mWakeLock.release(); - } - mContext.unbindService(JobServiceContext.this); - mWakeLock = null; - mRunningJob = null; - mParams = null; - mVerb = VERB_FINISHED; - mCancelled.set(false); - service = null; - mAvailable = true; - removeOpTimeOutLocked(); - removeMessages(MSG_CALLBACK); - removeMessages(MSG_SERVICE_BOUND); - removeMessages(MSG_CANCEL); - removeMessages(MSG_SHUTDOWN_EXECUTION); - mCompletedListener.onJobCompletedLocked(completedJob, reschedule); - } + /** + * The provided job has finished, either by calling + * {@link android.app.job.JobService#jobFinished(android.app.job.JobParameters, boolean)} + * or from acknowledging the stop message we sent. Either way, we're done tracking it and + * we want to clean up internally. + */ + private void closeAndCleanupJobLocked(boolean reschedule) { + final JobStatus completedJob; + if (mVerb == VERB_FINISHED) { + return; } + completedJob = mRunningJob; + mJobPackageTracker.noteInactive(completedJob); + try { + mBatteryStats.noteJobFinish(mRunningJob.getBatteryName(), + mRunningJob.getSourceUid()); + } catch (RemoteException e) { + // Whatever. + } + if (mWakeLock != null) { + mWakeLock.release(); + } + mContext.unbindService(JobServiceContext.this); + mWakeLock = null; + mRunningJob = null; + mParams = null; + mVerb = VERB_FINISHED; + mCancelled = false; + service = null; + mAvailable = true; + removeOpTimeOutLocked(); + mCompletedListener.onJobCompletedLocked(completedJob, reschedule); } /** diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java index e8cc078b7eb1..1ab66b9abb7f 100644 --- a/services/core/java/com/android/server/job/controllers/JobStatus.java +++ b/services/core/java/com/android/server/job/controllers/JobStatus.java @@ -26,7 +26,6 @@ import android.content.ContentProvider; import android.content.Intent; import android.net.Uri; import android.os.Binder; -import android.os.IBinder; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; @@ -35,6 +34,8 @@ import android.util.ArraySet; import android.util.Slog; import android.util.TimeUtils; +import com.android.server.job.GrantedUriPermissions; + import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; @@ -103,7 +104,7 @@ public final class JobStatus { final String tag; - private IBinder permissionOwner; + private GrantedUriPermissions uriPerms; private boolean prepared; /** @@ -284,12 +285,17 @@ public final class JobStatus { earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis); } - public void enqueueWorkLocked(JobWorkItem work) { + public void enqueueWorkLocked(IActivityManager am, JobWorkItem work) { if (pendingWork == null) { pendingWork = new ArrayList<>(); } work.setWorkId(nextPendingWorkId); nextPendingWorkId++; + if (work.getIntent() != null + && GrantedUriPermissions.checkGrantFlags(work.getIntent().getFlags())) { + work.setGrants(GrantedUriPermissions.createFromIntent(am, work.getIntent(), sourceUid, + sourcePackageName, sourceUserId, toShortString())); + } pendingWork.add(work); } @@ -311,12 +317,20 @@ public final class JobStatus { return executingWork != null && executingWork.size() > 0; } - public boolean completeWorkLocked(int workId) { + private static void ungrantWorkItem(IActivityManager am, JobWorkItem work) { + if (work.getGrants() != null) { + ((GrantedUriPermissions)work.getGrants()).revoke(am); + } + } + + public boolean completeWorkLocked(IActivityManager am, int workId) { if (executingWork != null) { final int N = executingWork.size(); for (int i = 0; i < N; i++) { - if (executingWork.get(i).getWorkId() == workId) { + JobWorkItem work = executingWork.get(i); + if (work.getWorkId() == workId) { executingWork.remove(i); + ungrantWorkItem(am, work); return true; } } @@ -324,15 +338,36 @@ public final class JobStatus { return false; } - public void stopTrackingJobLocked(JobStatus incomingJob) { + private static void ungrantWorkList(IActivityManager am, ArrayList<JobWorkItem> list) { + if (list != null) { + final int N = list.size(); + for (int i = 0; i < N; i++) { + ungrantWorkItem(am, list.get(i)); + } + } + } + + public void stopTrackingJobLocked(IActivityManager am, JobStatus incomingJob) { if (incomingJob != null) { - // We are replacing with a new job -- transfer the work! - incomingJob.pendingWork = pendingWork; + // We are replacing with a new job -- transfer the work! We do any executing + // work first, since that was originally at the front of the pending work. + if (executingWork != null && executingWork.size() > 0) { + incomingJob.pendingWork = executingWork; + } + if (incomingJob.pendingWork == null) { + incomingJob.pendingWork = pendingWork; + } else if (pendingWork != null && pendingWork.size() > 0) { + incomingJob.pendingWork.addAll(pendingWork); + } pendingWork = null; + executingWork = null; incomingJob.nextPendingWorkId = nextPendingWorkId; } else { // We are completely stopping the job... need to clean up work. - // XXX remove perms when that is impl. + ungrantWorkList(am, pendingWork); + pendingWork = null; + ungrantWorkList(am, executingWork); + executingWork = null; } } @@ -344,10 +379,8 @@ public final class JobStatus { prepared = true; final ClipData clip = job.getClipData(); if (clip != null) { - final int N = clip.getItemCount(); - for (int i = 0; i < N; i++) { - grantItemLocked(am, clip.getItemAt(i), sourceUid, sourcePackageName, sourceUserId); - } + uriPerms = GrantedUriPermissions.createFromClip(am, clip, sourceUid, sourcePackageName, + sourceUserId, job.getClipGrantFlags(), toShortString()); } } @@ -357,14 +390,9 @@ public final class JobStatus { return; } prepared = false; - if (permissionOwner != null) { - final ClipData clip = job.getClipData(); - if (clip != null) { - final int N = clip.getItemCount(); - for (int i = 0; i < N; i++) { - revokeItemLocked(am, clip.getItemAt(i)); - } - } + if (uriPerms != null) { + uriPerms.revoke(am); + uriPerms = null; } } @@ -372,57 +400,6 @@ public final class JobStatus { return prepared; } - private final void grantUriLocked(IActivityManager am, Uri uri, int sourceUid, - String targetPackage, int targetUserId) { - try { - int sourceUserId = ContentProvider.getUserIdFromUri(uri, - UserHandle.getUserId(sourceUid)); - uri = ContentProvider.getUriWithoutUserId(uri); - if (permissionOwner == null) { - permissionOwner = am.newUriPermissionOwner("job: " + toShortString()); - } - am.grantUriPermissionFromOwner(permissionOwner, sourceUid, targetPackage, - uri, job.getClipGrantFlags(), sourceUserId, targetUserId); - } catch (RemoteException e) { - Slog.e("JobScheduler", "AM dead"); - } - } - - private final void grantItemLocked(IActivityManager am, ClipData.Item item, int sourceUid, - String targetPackage, int targetUserId) { - if (item.getUri() != null) { - grantUriLocked(am, item.getUri(), sourceUid, targetPackage, targetUserId); - } - Intent intent = item.getIntent(); - if (intent != null && intent.getData() != null) { - grantUriLocked(am, intent.getData(), sourceUid, targetPackage, targetUserId); - } - } - - private final void revokeUriLocked(IActivityManager am, Uri uri) { - int userId = ContentProvider.getUserIdFromUri(uri, - UserHandle.getUserId(Binder.getCallingUid())); - long ident = Binder.clearCallingIdentity(); - try { - uri = ContentProvider.getUriWithoutUserId(uri); - am.revokeUriPermissionFromOwner(permissionOwner, uri, - job.getClipGrantFlags(), userId); - } catch (RemoteException e) { - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - private final void revokeItemLocked(IActivityManager am, ClipData.Item item) { - if (item.getUri() != null) { - revokeUriLocked(am, item.getUri()); - } - Intent intent = item.getIntent(); - if (intent != null && intent.getData() != null) { - revokeUriLocked(am, intent.getData()); - } - } - public JobInfo getJob() { return job; } @@ -833,6 +810,15 @@ public final class JobStatus { } } + private void dumpJobWorkItem(PrintWriter pw, String prefix, JobWorkItem work, int index) { + pw.print(prefix); pw.print(" #"); pw.print(index); pw.print(": #"); + pw.print(work.getWorkId()); pw.print(" "); pw.println(work.getIntent()); + if (work.getGrants() != null) { + pw.print(prefix); pw.println(" URI grants:"); + ((GrantedUriPermissions)work.getGrants()).dump(pw, prefix + " "); + } + } + // Dumpsys infrastructure public void dump(PrintWriter pw, String prefix, boolean full) { pw.print(prefix); UserHandle.formatUid(pw, callingUid); @@ -898,6 +884,10 @@ public final class JobStatus { job.getClipData().toShortString(b); pw.println(b); } + if (uriPerms != null) { + pw.print(prefix); pw.println(" Granted URI permissions:"); + uriPerms.dump(pw, prefix + " "); + } if (job.getNetworkType() != JobInfo.NETWORK_TYPE_NONE) { pw.print(prefix); pw.print(" Network type: "); pw.println(job.getNetworkType()); } @@ -950,17 +940,13 @@ public final class JobStatus { if (pendingWork != null && pendingWork.size() > 0) { pw.print(prefix); pw.println("Pending work:"); for (int i = 0; i < pendingWork.size(); i++) { - JobWorkItem work = pendingWork.get(i); - pw.print(prefix); pw.print(" #"); pw.print(i); pw.print(": #"); - pw.print(work.getWorkId()); pw.print(" "); pw.println(work.getIntent()); + dumpJobWorkItem(pw, prefix, pendingWork.get(i), i); } } if (executingWork != null && executingWork.size() > 0) { pw.print(prefix); pw.println("Executing work:"); for (int i = 0; i < executingWork.size(); i++) { - JobWorkItem work = executingWork.get(i); - pw.print(prefix); pw.print(" #"); pw.print(i); pw.print(": #"); - pw.print(work.getWorkId()); pw.print(" "); pw.println(work.getIntent()); + dumpJobWorkItem(pw, prefix, executingWork.get(i), i); } } pw.print(prefix); pw.print("Earliest run time: "); diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index 53a8092fa558..ee348cf71c88 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -101,8 +101,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { private ParceledListSlice mQueue; private CharSequence mQueueTitle; private int mRatingType; - private int mRepeatMode; - private boolean mShuffleModeEnabled; // End TransportPerformer fields // Volume handling fields @@ -622,47 +620,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } } - private void pushRepeatModeUpdate() { - synchronized (mLock) { - if (mDestroyed) { - return; - } - for (int i = mControllerCallbackHolders.size() - 1; i >= 0; i--) { - ISessionControllerCallbackHolder holder = mControllerCallbackHolders.get(i); - try { - holder.mCallback.onRepeatModeChanged(mRepeatMode); - } catch (DeadObjectException e) { - mControllerCallbackHolders.remove(i); - logCallbackException("Removed dead callback in pushRepeatModeUpdate", - holder, e); - } catch (RemoteException e) { - logCallbackException("unexpected exception in pushRepeatModeUpdate", holder, e); - } - } - } - } - - private void pushShuffleModeUpdate() { - synchronized (mLock) { - if (mDestroyed) { - return; - } - for (int i = mControllerCallbackHolders.size() - 1; i >= 0; i--) { - ISessionControllerCallbackHolder holder = mControllerCallbackHolders.get(i); - try { - holder.mCallback.onShuffleModeChanged(mShuffleModeEnabled); - } catch (DeadObjectException e) { - mControllerCallbackHolders.remove(i); - logCallbackException("Removed dead callback in pushShuffleModeUpdate", - holder, e); - } catch (RemoteException e) { - logCallbackException("unexpected exception in pushShuffleModeUpdate", - holder, e); - } - } - } - } - private void pushSessionDestroyed() { synchronized (mLock) { // This is the only method that may be (and can only be) called @@ -887,30 +844,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } @Override - public void setRepeatMode(int repeatMode) { - boolean changed; - synchronized (mLock) { - changed = mRepeatMode != repeatMode; - mRepeatMode = repeatMode; - } - if (changed) { - mHandler.post(MessageHandler.MSG_UPDATE_REPEAT_MODE); - } - } - - @Override - public void setShuffleModeEnabled(boolean enabled) { - boolean changed; - synchronized (mLock) { - changed = mShuffleModeEnabled != enabled; - mShuffleModeEnabled = enabled; - } - if (changed) { - mHandler.post(MessageHandler.MSG_UPDATE_SHUFFLE_MODE); - } - } - - @Override public void setCurrentVolume(int volume) { mCurrentVolume = volume; mHandler.post(MessageHandler.MSG_UPDATE_VOLUME); @@ -1126,54 +1059,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } } - public void repeatMode(int repeatMode) { - try { - mCb.onRepeatMode(repeatMode); - } catch (RemoteException e) { - Slog.e(TAG, "Remote failure in repeatMode.", e); - } - } - - public void shuffleMode(boolean enabled) { - try { - mCb.onShuffleMode(enabled); - } catch (RemoteException e) { - Slog.e(TAG, "Remote failure in shuffleMode.", e); - } - } - - public void addQueueItem(MediaDescription description) { - try { - mCb.onAddQueueItem(description); - } catch (RemoteException e) { - Slog.e(TAG, "Remote failure in addQueueItem.", e); - } - } - - public void addQueueItemAt(MediaDescription description, int index) { - try { - mCb.onAddQueueItemAt(description, index); - } catch (RemoteException e) { - Slog.e(TAG, "Remote failure in addQueueItemAt.", e); - } - } - - public void removeQueueItem(MediaDescription description) { - try { - mCb.onRemoveQueueItem(description); - } catch (RemoteException e) { - Slog.e(TAG, "Remote failure in removeQueueItem.", e); - } - } - - public void removeQueueItemAt(int index) { - try { - mCb.onRemoveQueueItemAt(index); - } catch (RemoteException e) { - Slog.e(TAG, "Remote failure in removeQueueItem.", e); - } - } - public void adjustVolume(int direction) { try { mCb.onAdjustVolume(direction); @@ -1410,25 +1295,13 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } @Override - public void repeatMode(int repeatMode) { - updateCallingPackage(); - mSessionCb.repeatMode(repeatMode); - } - - @Override - public void shuffleMode(boolean enabled) throws RemoteException { - updateCallingPackage(); - mSessionCb.shuffleMode(enabled); - } - - - @Override public void sendCustomAction(String action, Bundle args) throws RemoteException { updateCallingPackage(); mSessionCb.sendCustomAction(action, args); } + @Override public MediaMetadata getMetadata() { synchronized (mLock) { @@ -1449,30 +1322,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } @Override - public void addQueueItem(MediaDescription description) { - updateCallingPackage(); - mSessionCb.addQueueItem(description); - } - - @Override - public void addQueueItemAt(MediaDescription description, int index) { - updateCallingPackage(); - mSessionCb.addQueueItemAt(description, index); - } - - @Override - public void removeQueueItem(MediaDescription description) { - updateCallingPackage(); - mSessionCb.removeQueueItem(description); - } - - @Override - public void removeQueueItemAt(int index) { - updateCallingPackage(); - mSessionCb.removeQueueItemAt(index); - } - - @Override public CharSequence getQueueTitle() { return mQueueTitle; } @@ -1490,16 +1339,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } @Override - public int getRepeatMode() { - return mRepeatMode; - } - - @Override - public boolean isShuffleModeEnabled() { - return mShuffleModeEnabled; - } - - @Override public boolean isTransportControlEnabled() { return MediaSessionRecord.this.isTransportControlEnabled(); } @@ -1524,9 +1363,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { private static final int MSG_SEND_EVENT = 6; private static final int MSG_UPDATE_SESSION_STATE = 7; private static final int MSG_UPDATE_VOLUME = 8; - private static final int MSG_UPDATE_REPEAT_MODE = 9; - private static final int MSG_UPDATE_SHUFFLE_MODE = 10; - private static final int MSG_DESTROYED = 11; + private static final int MSG_DESTROYED = 9; public MessageHandler(Looper looper) { super(looper); @@ -1558,12 +1395,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { case MSG_UPDATE_VOLUME: pushVolumeUpdate(); break; - case MSG_UPDATE_REPEAT_MODE: - pushRepeatModeUpdate(); - break; - case MSG_UPDATE_SHUFFLE_MODE: - pushShuffleModeUpdate(); - break; case MSG_DESTROYED: pushSessionDestroyed(); } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index bac487eb9fba..cc3948ed1a59 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -97,6 +97,7 @@ import android.media.AudioManagerInternal; import android.media.IRingtonePlayer; import android.net.Uri; import android.os.Binder; +import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; @@ -3185,16 +3186,16 @@ public class NotificationManagerService extends SystemService { // STOPSHIP TODO: should throw instead of logging or toasting. // throw new IllegalArgumentException(noChannelStr); Log.e(TAG, noChannelStr); - - final String noChannelToastStr = - "Developer warning for package \"" + pkg + "\"\n" + + doDebugOnlyToast("Developer warning for package \"" + pkg + "\"\n" + "Failed to post notification on channel \"" + channelId + "\"\n" + - "See log for more details"; - Toast noChannelToast = - Toast.makeText(getContext(), noChannelToastStr, Toast.LENGTH_LONG); - noChannelToast.show(); + "See log for more details"); return; + } else if (channelId == null && shouldWarnUseChannels(pkg, notificationUid)) { + // STOPSHIP TODO: remove once default channel is removed for all apps that target O. + doDebugOnlyToast("Developer warning for package \"" + pkg + "\"\n" + + "Posted notification should specify a channel"); } + final StatusBarNotification n = new StatusBarNotification( pkg, opPkg, id, tag, notificationUid, callingPid, notification, user, null, System.currentTimeMillis()); @@ -3226,6 +3227,26 @@ public class NotificationManagerService extends SystemService { idOut[0] = id; } + private void doDebugOnlyToast(CharSequence toastText) { + if (Build.IS_DEBUGGABLE) { + Toast toast = Toast.makeText(getContext(), toastText, Toast.LENGTH_LONG); + toast.show(); + } + } + + // STOPSHIP - Remove once RankingHelper deletes default channel for all apps targeting O. + private boolean shouldWarnUseChannels(String pkg, int uid) { + try { + final int userId = UserHandle.getUserId(uid); + final ApplicationInfo applicationInfo = + mPackageManagerClient.getApplicationInfoAsUser(pkg, 0, userId); + return applicationInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1; + } catch (NameNotFoundException e) { + Slog.e(TAG, e.toString()); + return false; + } + } + private int resolveNotificationUid(String opPackageName, int callingUid, int userId) { // The system can post notifications on behalf of any package it wants if (isCallerSystem() && opPackageName != null && !"android".equals(opPackageName)) { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index e79f46b4f3be..95b4903e49d7 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -364,7 +364,8 @@ import java.util.concurrent.atomic.AtomicInteger; * $ cts-tradefed run commandAndExit cts -m CtsAppSecurityHostTestCases * </pre> */ -public class PackageManagerService extends IPackageManager.Stub { +public class PackageManagerService extends IPackageManager.Stub + implements PackageSender { static final String TAG = "PackageManager"; static final boolean DEBUG_SETTINGS = false; static final boolean DEBUG_PREFERRED = false; @@ -13083,7 +13084,7 @@ public class PackageManagerService extends IPackageManager.Stub { } }; - final void sendPackageBroadcast(final String action, final String pkg, final Bundle extras, + public void sendPackageBroadcast(final String action, final String pkg, final Bundle extras, final int flags, final String targetPkg, final IIntentReceiver finishedReceiver, final int[] userIds) { mHandler.post(new Runnable() { @@ -13386,8 +13387,7 @@ public class PackageManagerService extends IPackageManager.Stub { sendPackageAddedForNewUsers(packageName, isSystem, pkgSetting.appId, userId); } - private void sendPackageAddedForNewUsers(String packageName, boolean isSystem, - int appId, int... userIds) { + public void sendPackageAddedForNewUsers(String packageName, boolean isSystem, int appId, int... userIds) { if (ArrayUtils.isEmpty(userIds)) { return; } @@ -13514,7 +13514,7 @@ public class PackageManagerService extends IPackageManager.Stub { private void sendApplicationHiddenForUser(String packageName, PackageSetting pkgSetting, int userId) { - final PackageRemovedInfo info = new PackageRemovedInfo(); + final PackageRemovedInfo info = new PackageRemovedInfo(this); info.removedPackage = packageName; info.removedUsers = new int[] {userId}; info.broadcastUsers = new int[] {userId}; @@ -16150,7 +16150,7 @@ public class PackageManagerService extends IPackageManager.Stub { } // Update what is removed - res.removedInfo = new PackageRemovedInfo(); + res.removedInfo = new PackageRemovedInfo(this); res.removedInfo.uid = oldPackage.applicationInfo.uid; res.removedInfo.removedPackage = oldPackage.packageName; res.removedInfo.isStaticSharedLib = pkg.staticSharedLibName != null; @@ -16180,7 +16180,7 @@ public class PackageManagerService extends IPackageManager.Stub { } } if (!childPackageUpdated) { - PackageRemovedInfo childRemovedRes = new PackageRemovedInfo(); + PackageRemovedInfo childRemovedRes = new PackageRemovedInfo(this); childRemovedRes.removedPackage = childPkg.packageName; childRemovedRes.isUpdate = false; childRemovedRes.dataRemoved = true; @@ -16870,7 +16870,7 @@ public class PackageManagerService extends IPackageManager.Stub { sUserManager.getUserIds(), true); } if ((mPackages.containsKey(childPkg.packageName))) { - childRes.removedInfo = new PackageRemovedInfo(); + childRes.removedInfo = new PackageRemovedInfo(this); childRes.removedInfo.removedPackage = childPkg.packageName; } if (res.addedChildPackages == null) { @@ -17716,7 +17716,7 @@ public class PackageManagerService extends IPackageManager.Stub { * sending a broadcast if necessary */ private int deletePackageX(String packageName, int versionCode, int userId, int deleteFlags) { - final PackageRemovedInfo info = new PackageRemovedInfo(); + final PackageRemovedInfo info = new PackageRemovedInfo(this); final boolean res; final int removeUser = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0 @@ -17816,7 +17816,8 @@ public class PackageManagerService extends IPackageManager.Stub { return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR; } - class PackageRemovedInfo { + static class PackageRemovedInfo { + final PackageSender packageSender; String removedPackage; int uid = -1; int removedAppId = -1; @@ -17834,6 +17835,10 @@ public class PackageManagerService extends IPackageManager.Stub { ArrayMap<String, PackageRemovedInfo> removedChildPackages; ArrayMap<String, PackageInstalledInfo> appearedChildPackages; + PackageRemovedInfo(PackageSender packageSender) { + this.packageSender = packageSender; + } + void sendPackageRemovedBroadcasts(boolean killApp) { sendPackageRemovedBroadcastInternal(killApp); final int childCount = removedChildPackages != null ? removedChildPackages.size() : 0; @@ -17862,8 +17867,9 @@ public class PackageManagerService extends IPackageManager.Stub { ? appearedChildPackages.size() : 0; for (int i = 0; i < packageCount; i++) { PackageInstalledInfo installedInfo = appearedChildPackages.valueAt(i); - sendPackageAddedForNewUsers(installedInfo.name, true, - UserHandle.getAppId(installedInfo.uid), installedInfo.newUsers); + packageSender.sendPackageAddedForNewUsers(installedInfo.name, + true, UserHandle.getAppId(installedInfo.uid), + installedInfo.newUsers); } } @@ -17871,12 +17877,12 @@ public class PackageManagerService extends IPackageManager.Stub { Bundle extras = new Bundle(2); extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid); extras.putBoolean(Intent.EXTRA_REPLACING, true); - sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, removedPackage, - extras, 0, null, null, null); - sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, removedPackage, - extras, 0, null, null, null); - sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null, - null, 0, removedPackage, null, null); + packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, + removedPackage, extras, 0, null, null, null); + packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, + removedPackage, extras, 0, null, null, null); + packageSender.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, + null, null, 0, removedPackage, null, null); } private void sendPackageRemovedBroadcastInternal(boolean killApp) { @@ -17895,19 +17901,37 @@ public class PackageManagerService extends IPackageManager.Stub { } extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, removedForAllUsers); if (removedPackage != null) { - sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, - extras, 0, null, null, broadcastUsers); + packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, + removedPackage, extras, 0, null, null, broadcastUsers); if (dataRemoved && !isRemovedPackageSystemUpdate) { - sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED, - removedPackage, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, - null, null, broadcastUsers); + packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED, + removedPackage, extras, + Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, + null, null, broadcastUsers); } } if (removedAppId >= 0) { - sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, + packageSender.sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, null, null, broadcastUsers); } } + + void populateUsers(int[] userIds, PackageSetting deletedPackageSetting) { + removedUsers = userIds; + if (removedUsers == null) { + broadcastUsers = null; + return; + } + + broadcastUsers = EMPTY_INT_ARRAY; + for (int i = userIds.length - 1; i >= 0; --i) { + final int userId = userIds[i]; + if (deletedPackageSetting.getInstantApp(userId)) { + continue; + } + broadcastUsers = ArrayUtils.appendInt(broadcastUsers, userId); + } + } } /* @@ -17931,23 +17955,8 @@ public class PackageManagerService extends IPackageManager.Stub { outInfo.removedPackage = packageName; outInfo.isStaticSharedLib = deletedPkg != null && deletedPkg.staticSharedLibName != null; - outInfo.removedUsers = deletedPs != null - ? deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true) - : null; - if (outInfo.removedUsers == null) { - outInfo.broadcastUsers = null; - } else { - outInfo.broadcastUsers = EMPTY_INT_ARRAY; - int[] allUsers = outInfo.removedUsers; - for (int i = allUsers.length - 1; i >= 0; --i) { - final int userId = allUsers[i]; - if (deletedPs.getInstantApp(userId)) { - continue; - } - outInfo.broadcastUsers = - ArrayUtils.appendInt(outInfo.broadcastUsers, userId); - } - } + outInfo.populateUsers(deletedPs == null ? null + : deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true), deletedPs); } } @@ -18430,7 +18439,7 @@ public class PackageManagerService extends IPackageManager.Stub { outInfo.removedChildPackages = new ArrayMap<>(childCount); for (int i = 0; i < childCount; i++) { String childPackageName = ps.childPackageNames.get(i); - PackageRemovedInfo childInfo = new PackageRemovedInfo(); + PackageRemovedInfo childInfo = new PackageRemovedInfo(this); childInfo.removedPackage = childPackageName; outInfo.removedChildPackages.put(childPackageName, childInfo); PackageSetting childPs = mSettings.getPackageLPr(childPackageName); @@ -21692,7 +21701,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to unload pkg : " + pkgName); // Delete package internally - PackageRemovedInfo outInfo = new PackageRemovedInfo(); + PackageRemovedInfo outInfo = new PackageRemovedInfo(this); synchronized (mInstallLock) { final int deleteFlags = PackageManager.DELETE_KEEP_DATA; final boolean res; @@ -21859,7 +21868,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); final ApplicationInfo info = ps.pkg.applicationInfo; final int deleteFlags = PackageManager.DELETE_KEEP_DATA; - final PackageRemovedInfo outInfo = new PackageRemovedInfo(); + final PackageRemovedInfo outInfo = new PackageRemovedInfo(this); try (PackageFreezer freezer = freezePackageForDelete(ps.name, deleteFlags, "unloadPrivatePackagesInner")) { @@ -23643,3 +23652,11 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); ? null : mInstantAppInstallerActivity.getComponentName(); } } + +interface PackageSender { + void sendPackageBroadcast(final String action, final String pkg, + final Bundle extras, final int flags, final String targetPkg, + final IIntentReceiver finishedReceiver, final int[] userIds); + void sendPackageAddedForNewUsers(String packageName, boolean isSystem, + int appId, int... userIds); +} diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 4f29bfa2829e..bcb4121a6d2f 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -222,9 +222,10 @@ import android.view.accessibility.AccessibilityManager; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.AnimationUtils; +import android.view.inputmethod.InputMethodManagerInternal; import android.widget.ImageView; - import com.android.internal.R; +import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.internal.policy.IKeyguardDismissCallback; import com.android.internal.policy.IShortcutService; @@ -279,6 +280,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2; static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3; static final int SHORT_PRESS_POWER_GO_HOME = 4; + static final int SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME = 5; static final int LONG_PRESS_POWER_NOTHING = 0; static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1; @@ -407,6 +409,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { PowerManager mPowerManager; ActivityManagerInternal mActivityManagerInternal; InputManagerInternal mInputManagerInternal; + InputMethodManagerInternal mInputMethodManagerInternal; DreamManagerInternal mDreamManagerInternal; PowerManagerInternal mPowerManagerInternal; IStatusBarService mStatusBarService; @@ -494,6 +497,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { WindowState mLastInputMethodWindow = null; WindowState mLastInputMethodTargetWindow = null; + @GuardedBy("mLock") + private boolean mDismissImeOnBackKeyPressed; + // FIXME This state is shared between the input reader and handler thread. // Technically it's broken and buggy but it has been like this for many years // and we have not yet seen any problems. Someday we'll rewrite this logic @@ -1396,6 +1402,27 @@ public class PhoneWindowManager implements WindowManagerPolicy { case SHORT_PRESS_POWER_GO_HOME: launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/); break; + case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME: { + final boolean dismissImeOnBackKeyPressed; + // We can be here on both the main thread (via mHandler) and native callback + // thread (from interceptPowerKeyUp via WindowManagerCallbacks). + synchronized (mLock) { + dismissImeOnBackKeyPressed = mDismissImeOnBackKeyPressed; + } + if (dismissImeOnBackKeyPressed) { + if (mInputMethodManagerInternal == null) { + mInputMethodManagerInternal = + LocalServices.getService(InputMethodManagerInternal.class); + } + if (mInputMethodManagerInternal != null) { + mInputMethodManagerInternal.hideCurrentInputMethod(); + } + } else { + launchHomeFromHotKey(true /* awakenFromDreams */, + false /*respectKeyguard*/); + } + break; + } } } } @@ -7955,6 +7982,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { } @Override + public void setDismissImeOnBackKeyPressed(boolean newValue) { + synchronized (mLock) { + mDismissImeOnBackKeyPressed = newValue; + } + } + + @Override public int getInputMethodWindowVisibleHeightLw() { return mDockBottom - mCurBottom; } @@ -8170,6 +8204,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(prefix); pw.print("mLastInputMethodTargetWindow="); pw.println(mLastInputMethodTargetWindow); } + pw.print(prefix); pw.print("mDismissImeOnBackKeyPressed="); + pw.println(mDismissImeOnBackKeyPressed); if (mStatusBar != null) { pw.print(prefix); pw.print("mStatusBar="); pw.print(mStatusBar); pw.print(" isStatusBarKeyguard="); diff --git a/services/core/java/com/android/server/storage/AppCollector.java b/services/core/java/com/android/server/storage/AppCollector.java index a77d33f8514b..03b754f777b3 100644 --- a/services/core/java/com/android/server/storage/AppCollector.java +++ b/services/core/java/com/android/server/storage/AppCollector.java @@ -21,22 +21,21 @@ import android.app.usage.StorageStats; import android.app.usage.StorageStatsManager; import android.content.Context; import android.content.pm.ApplicationInfo; -import android.content.pm.IPackageStatsObserver; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageStats; import android.content.pm.UserInfo; import android.os.Handler; -import android.os.HandlerThread; import android.os.Looper; import android.os.Message; -import android.os.Process; -import android.os.RemoteException; import android.os.UserManager; import android.os.storage.VolumeInfo; import android.util.Log; + import com.android.internal.os.BackgroundThread; import com.android.internal.util.Preconditions; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -44,7 +43,6 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicInteger; /** * AppCollector asynchronously collects package sizes. @@ -132,7 +130,7 @@ public class AppCollector { try { StorageStats storageStats = - mStorageStatsManager.queryStatsForPackage(app.volumeUuid, + mStorageStatsManager.queryStatsForPackage(app.storageUuid, app.packageName, user.getUserHandle()); PackageStats packageStats = new PackageStats(app.packageName, user.id); @@ -140,7 +138,7 @@ public class AppCollector { packageStats.codeSize = storageStats.getCodeBytes(); packageStats.dataSize = storageStats.getDataBytes(); stats.add(packageStats); - } catch (IllegalStateException e) { + } catch (NameNotFoundException | IOException e) { Log.e(TAG, "An exception occurred while fetching app size", e); } } diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java index 16848780fe47..82416ec513c4 100644 --- a/services/core/java/com/android/server/wm/PinnedStackController.java +++ b/services/core/java/com/android/server/wm/PinnedStackController.java @@ -26,7 +26,6 @@ import android.app.RemoteAction; import android.content.pm.ParceledListSlice; import android.content.res.Resources; import android.graphics.Point; -import android.graphics.PointF; import android.graphics.Rect; import android.os.Handler; import android.os.IBinder; @@ -123,6 +122,13 @@ class PinnedStackController { mSnapAlgorithm.setMinimized(isMinimized); }); } + + @Override + public int getDisplayRotation() { + synchronized (mService.mWindowMap) { + return mDisplayInfo.rotation; + } + } } /** @@ -221,22 +227,26 @@ class PinnedStackController { * @return the size of the PIP based on the given {@param aspectRatio}. */ Size getSize(float aspectRatio) { - return mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, mMinSize, - mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); + synchronized (mService.mWindowMap) { + return mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, mMinSize, + mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); + } } /** * @return the default bounds to show the PIP when there is no active PIP. */ Rect getDefaultBounds() { - final Rect insetBounds = new Rect(); - getInsetBounds(insetBounds); - - final Rect defaultBounds = new Rect(); - final Size size = getSize(mDefaultAspectRatio); - Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds, - 0, mIsImeShowing ? mImeHeight : 0, defaultBounds); - return defaultBounds; + synchronized (mService.mWindowMap) { + final Rect insetBounds = new Rect(); + getInsetBounds(insetBounds); + + final Rect defaultBounds = new Rect(); + final Size size = getSize(mDefaultAspectRatio); + Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds, + 0, mIsImeShowing ? mImeHeight : 0, defaultBounds); + return defaultBounds; + } } /** @@ -254,42 +264,44 @@ class PinnedStackController { * new orientation of the device if necessary. */ boolean onTaskStackBoundsChanged(Rect targetBounds, Rect outBounds) { - final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo(); - if (mDisplayInfo.equals(displayInfo)) { - // We are already in the right orientation, ignore - outBounds.setEmpty(); - return false; - } else if (targetBounds.isEmpty()) { - // The stack is null, we are just initializing the stack, so just store the display info - // and ignore + synchronized (mService.mWindowMap) { + final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo(); + if (mDisplayInfo.equals(displayInfo)) { + // We are already in the right orientation, ignore + outBounds.setEmpty(); + return false; + } else if (targetBounds.isEmpty()) { + // The stack is null, we are just initializing the stack, so just store the display + // info and ignore + mDisplayInfo.copyFrom(displayInfo); + outBounds.setEmpty(); + return false; + } + + mTmpRect.set(targetBounds); + final Rect postChangeStackBounds = mTmpRect; + + // Calculate the snap fraction of the current stack along the old movement bounds + final Rect preChangeMovementBounds = getMovementBounds(postChangeStackBounds); + final float snapFraction = mSnapAlgorithm.getSnapFraction(postChangeStackBounds, + preChangeMovementBounds); mDisplayInfo.copyFrom(displayInfo); - outBounds.setEmpty(); - return false; - } - mTmpRect.set(targetBounds); - final Rect postChangeStackBounds = mTmpRect; - - // Calculate the snap fraction of the current stack along the old movement bounds - final Rect preChangeMovementBounds = getMovementBounds(postChangeStackBounds); - final float snapFraction = mSnapAlgorithm.getSnapFraction(postChangeStackBounds, - preChangeMovementBounds); - mDisplayInfo.copyFrom(displayInfo); - - // Calculate the stack bounds in the new orientation to the same same fraction along the - // rotated movement bounds. - final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds, - false /* adjustForIme */); - mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds, - snapFraction); - if (mIsMinimized) { - applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds); - } + // Calculate the stack bounds in the new orientation to the same same fraction along the + // rotated movement bounds. + final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds, + false /* adjustForIme */); + mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds, + snapFraction); + if (mIsMinimized) { + applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds); + } - notifyMovementBoundsChanged(false /* fromImeAdjustment */); + notifyMovementBoundsChanged(false /* fromImeAdjustment */); - outBounds.set(postChangeStackBounds); - return true; + outBounds.set(postChangeStackBounds); + return true; + } } /** @@ -378,25 +390,27 @@ class PinnedStackController { * Notifies listeners that the PIP movement bounds have changed. */ private void notifyMovementBoundsChanged(boolean fromImeAdjustement) { - if (mPinnedStackListener != null) { - try { - final Rect insetBounds = new Rect(); - getInsetBounds(insetBounds); - final Rect normalBounds = getDefaultBounds(); - if (isValidPictureInPictureAspectRatio(mAspectRatio)) { - transformBoundsToAspectRatio(normalBounds, mAspectRatio); - } - final Rect animatingBounds = mTmpAnimatingBoundsRect; - final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID); - if (pinnedStack != null) { - pinnedStack.getAnimationOrCurrentBounds(animatingBounds); - } else { - animatingBounds.set(normalBounds); + synchronized (mService.mWindowMap) { + if (mPinnedStackListener != null) { + try { + final Rect insetBounds = new Rect(); + getInsetBounds(insetBounds); + final Rect normalBounds = getDefaultBounds(); + if (isValidPictureInPictureAspectRatio(mAspectRatio)) { + transformBoundsToAspectRatio(normalBounds, mAspectRatio); + } + final Rect animatingBounds = mTmpAnimatingBoundsRect; + final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID); + if (pinnedStack != null) { + pinnedStack.getAnimationOrCurrentBounds(animatingBounds); + } else { + animatingBounds.set(normalBounds); + } + mPinnedStackListener.onMovementBoundsChanged(insetBounds, normalBounds, + animatingBounds, fromImeAdjustement, mDisplayInfo.rotation); + } catch (RemoteException e) { + Slog.e(TAG_WM, "Error delivering actions changed event.", e); } - mPinnedStackListener.onMovementBoundsChanged(insetBounds, normalBounds, - animatingBounds, fromImeAdjustement); - } catch (RemoteException e) { - Slog.e(TAG_WM, "Error delivering actions changed event.", e); } } } @@ -405,11 +419,13 @@ class PinnedStackController { * @return the bounds on the screen that the PIP can be visible in. */ private void getInsetBounds(Rect outRect) { - mService.mPolicy.getStableInsetsLw(mDisplayInfo.rotation, mDisplayInfo.logicalWidth, - mDisplayInfo.logicalHeight, mTmpInsets); - outRect.set(mTmpInsets.left + mScreenEdgeInsets.x, mTmpInsets.top + mScreenEdgeInsets.y, - mDisplayInfo.logicalWidth - mTmpInsets.right - mScreenEdgeInsets.x, - mDisplayInfo.logicalHeight - mTmpInsets.bottom - mScreenEdgeInsets.y); + synchronized (mService.mWindowMap) { + mService.mPolicy.getStableInsetsLw(mDisplayInfo.rotation, mDisplayInfo.logicalWidth, + mDisplayInfo.logicalHeight, mTmpInsets); + outRect.set(mTmpInsets.left + mScreenEdgeInsets.x, mTmpInsets.top + mScreenEdgeInsets.y, + mDisplayInfo.logicalWidth - mTmpInsets.right - mScreenEdgeInsets.x, + mDisplayInfo.logicalHeight - mTmpInsets.bottom - mScreenEdgeInsets.y); + } } /** @@ -417,7 +433,9 @@ class PinnedStackController { * controller. */ private Rect getMovementBounds(Rect stackBounds) { - return getMovementBounds(stackBounds, true /* adjustForIme */); + synchronized (mService.mWindowMap) { + return getMovementBounds(stackBounds, true /* adjustForIme */); + } } /** @@ -425,23 +443,27 @@ class PinnedStackController { * controller. */ private Rect getMovementBounds(Rect stackBounds, boolean adjustForIme) { - final Rect movementBounds = new Rect(); - getInsetBounds(movementBounds); - - // Apply the movement bounds adjustments based on the current state - mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds, - (adjustForIme && mIsImeShowing) ? mImeHeight : 0); - return movementBounds; + synchronized (mService.mWindowMap) { + final Rect movementBounds = new Rect(); + getInsetBounds(movementBounds); + + // Apply the movement bounds adjustments based on the current state + mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds, + (adjustForIme && mIsImeShowing) ? mImeHeight : 0); + return movementBounds; + } } /** * Applies the minimized offsets to the given stack bounds. */ private void applyMinimizedOffset(Rect stackBounds, Rect movementBounds) { - mTmpDisplaySize.set(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); - mService.getStableInsetsLocked(mDisplayContent.getDisplayId(), mStableInsets); - mSnapAlgorithm.applyMinimizedOffset(stackBounds, movementBounds, mTmpDisplaySize, - mStableInsets); + synchronized (mService.mWindowMap) { + mTmpDisplaySize.set(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); + mService.getStableInsetsLocked(mDisplayContent.getDisplayId(), mStableInsets); + mSnapAlgorithm.applyMinimizedOffset(stackBounds, movementBounds, mTmpDisplaySize, + mStableInsets); + } } /** diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 0049585f5c52..252b4d4e0473 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -7267,13 +7267,16 @@ public class WindowManagerService extends IWindowManager.Stub @Override public void updateInputMethodWindowStatus(@NonNull IBinder imeToken, - boolean imeWindowVisible, @Nullable IBinder targetWindowToken) { + boolean imeWindowVisible, boolean dismissImeOnBackKeyPressed, + @Nullable IBinder targetWindowToken) { // TODO (b/34628091): Use this method to address the window animation issue. if (DEBUG_INPUT_METHOD) { Slog.w(TAG_WM, "updateInputMethodWindowStatus: imeToken=" + imeToken + + " dismissImeOnBackKeyPressed=" + dismissImeOnBackKeyPressed + " imeWindowVisible=" + imeWindowVisible + " targetWindowToken=" + targetWindowToken); } + mPolicy.setDismissImeOnBackKeyPressed(dismissImeOnBackKeyPressed); } @Override diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp index 86662b94302e..74ecd11d13f4 100644 --- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp @@ -68,12 +68,15 @@ static JavaVM* sJvm; using android::OK; using android::sp; +using android::wp; using android::status_t; using android::String16; using android::hardware::Return; using android::hardware::Void; using android::hardware::hidl_vec; +using android::hardware::hidl_death_recipient; +using android::hidl::base::V1_0::IBase; using android::hardware::gnss::V1_0::IAGnss; using android::hardware::gnss::V1_0::IAGnssCallback; @@ -97,7 +100,18 @@ using android::hardware::gnss::V1_0::IGnssNiCallback; using android::hardware::gnss::V1_0::IGnssXtra; using android::hardware::gnss::V1_0::IGnssXtraCallback; +struct GnssDeathRecipient : virtual public hidl_death_recipient +{ + // hidl_death_recipient interface + virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override { + // TODO(gomo): implement a better death recovery mechanism without + // crashing system server process as described in go//treble-gnss-death + LOG_ALWAYS_FATAL("Abort due to IGNSS hidl service failure," + " restarting system server"); + } +}; +sp<GnssDeathRecipient> gnssHalDeathRecipient = nullptr; sp<IGnss> gnssHal = nullptr; sp<IGnssXtra> gnssXtraIface = nullptr; sp<IAGnssRil> agnssRilIface = nullptr; @@ -1038,6 +1052,18 @@ static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, // TODO(b/31632518) gnssHal = IGnss::getService(); if (gnssHal != nullptr) { + gnssHalDeathRecipient = new GnssDeathRecipient(); + hardware::Return<bool> linked = gnssHal->linkToDeath( + gnssHalDeathRecipient, /*cookie*/ 0); + if (!linked.isOk()) { + ALOGE("Transaction error in linking to GnssHAL death: %s", + linked.description().c_str()); + } else if (!linked) { + ALOGW("Unable to link to GnssHal death notifications"); + } else { + ALOGD("Link to death notification successful"); + } + auto gnssXtra = gnssHal->getExtensionXtra(); if (!gnssXtra.isOk()) { ALOGD("Unable to get a handle to Xtra"); diff --git a/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java b/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java new file mode 100644 index 000000000000..243c1b379608 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java @@ -0,0 +1,76 @@ +/* + * 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.am; + +import android.content.Context; +import android.os.Handler; +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.server.AppOpsService; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; + +/** + * runtest -c com.android.server.am.AppErrorDialogTest frameworks-services + */ +@RunWith(AndroidJUnit4.class) +@SmallTest +public class AppErrorDialogTest { + + private Context mContext; + private ActivityManagerService mService; + + @Before + public void setUp() throws Exception { + mContext = InstrumentationRegistry.getTargetContext(); + mService = new ActivityManagerService(new ActivityManagerService.Injector() { + @Override + public AppOpsService getAppOpsService(File file, Handler handler) { + return null; + } + + @Override + public Handler getUiHandler(ActivityManagerService service) { + return null; + } + + @Override + public boolean isNetworkRestrictedForUid(int uid) { + return false; + } + }); + } + + @Test + @UiThreadTest + public void testCreateWorks() throws Exception { + AppErrorDialog.Data data = new AppErrorDialog.Data(); + data.proc = new ProcessRecord(null, mContext.getApplicationInfo(), "name", 12345); + data.result = new AppErrorResult(); + + AppErrorDialog dialog = new AppErrorDialog(mContext, mService, data); + + dialog.create(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java new file mode 100644 index 000000000000..8f2f34ee77d9 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import android.content.IIntentReceiver; + +import android.os.Bundle; + +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; + +import java.io.File; + +// runtest -c com.android.server.pm.PackageManagerServiceTest frameworks-services + +@SmallTest +public class PackageManagerServiceTest extends AndroidTestCase { + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testPackageRemoval() throws Exception { + class PackageSenderImpl implements PackageSender { + public void sendPackageBroadcast(final String action, final String pkg, + final Bundle extras, final int flags, final String targetPkg, + final IIntentReceiver finishedReceiver, final int[] userIds) { + } + + public void sendPackageAddedForNewUsers(String packageName, + boolean isSystem, int appId, int... userIds) { + } + } + + PackageSenderImpl sender = new PackageSenderImpl(); + PackageSetting setting = null; + PackageManagerService.PackageRemovedInfo pri = + new PackageManagerService.PackageRemovedInfo(sender); + + // Initial conditions: nothing there + assertNull(pri.removedUsers); + assertNull(pri.broadcastUsers); + + // populateUsers with nothing leaves nothing + pri.populateUsers(null, setting); + assertNull(pri.broadcastUsers); + + // Create a real (non-null) PackageSetting and confirm that the removed + // users are copied properly + setting = new PackageSetting("name", "realName", new File("codePath"), + new File("resourcePath"), "legacyNativeLibraryPathString", + "primaryCpuAbiString", "secondaryCpuAbiString", + "cpuAbiOverrideString", 0, 0, 0, "parentPackageName", null, 0, + null, null); + pri.populateUsers(new int[] {1, 2, 3, 4, 5}, setting); + assertNotNull(pri.broadcastUsers); + assertEquals(5, pri.broadcastUsers.length); + + // Exclude a user + pri.broadcastUsers = null; + final int EXCLUDED_USER_ID = 4; + setting.setInstantApp(true, EXCLUDED_USER_ID); + pri.populateUsers(new int[] {1, 2, 3, EXCLUDED_USER_ID, 5}, setting); + assertNotNull(pri.broadcastUsers); + assertEquals(5 - 1, pri.broadcastUsers.length); + + // TODO: test that sendApplicationHiddenForUser() actually fills in + // broadcastUsers + } +} diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java index 5ad7f8042c01..094c7bd89ba0 100644 --- a/services/usage/java/com/android/server/usage/StorageStatsService.java +++ b/services/usage/java/com/android/server/usage/StorageStatsService.java @@ -35,6 +35,7 @@ import android.os.FileUtils; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.ParcelableException; import android.os.StatFs; import android.os.SystemProperties; import android.os.UserHandle; @@ -150,7 +151,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub { try { return mInstaller.isQuotaSupported(volumeUuid); } catch (InstallerException e) { - throw new IllegalStateException(e); + throw new ParcelableException(new IOException(e.getMessage())); } } @@ -163,7 +164,8 @@ public class StorageStatsService extends IStorageStatsManager.Stub { } else { final VolumeInfo vol = mStorage.findVolumeByUuid(volumeUuid); if (vol == null) { - throw new IllegalStateException("Volume was unexpected null"); + throw new ParcelableException( + new IOException("Failed to find storage device for UUID " + volumeUuid)); } return FileUtils.roundStorageSize(vol.disk.size); } @@ -189,7 +191,8 @@ public class StorageStatsService extends IStorageStatsManager.Stub { } else { final VolumeInfo vol = mStorage.findVolumeByUuid(volumeUuid); if (vol == null) { - throw new IllegalStateException("Volume was unexpected null"); + throw new ParcelableException( + new IOException("Failed to find storage device for UUID " + volumeUuid)); } return vol.getPath().getUsableSpace() + cacheBytes; } @@ -221,7 +224,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub { appInfo = mPackage.getApplicationInfoAsUser(packageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); } catch (NameNotFoundException e) { - throw new IllegalStateException(e); + throw new ParcelableException(e); } if (mPackage.getPackagesForUid(appInfo.uid).length == 1) { @@ -239,7 +242,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub { mInstaller.getAppSize(volumeUuid, packageNames, userId, 0, appId, ceDataInodes, codePaths, stats); } catch (InstallerException e) { - throw new IllegalStateException(e); + throw new ParcelableException(new IOException(e.getMessage())); } return translate(stats); } @@ -265,7 +268,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub { codePaths[i] = mPackage.getApplicationInfoAsUser(packageNames[i], PackageManager.MATCH_UNINSTALLED_PACKAGES, userId).getCodePath(); } catch (NameNotFoundException e) { - throw new IllegalStateException(e); + throw new ParcelableException(e); } } @@ -281,7 +284,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub { checkEquals("UID " + uid, manualStats, stats); } } catch (InstallerException e) { - throw new IllegalStateException(e); + throw new ParcelableException(new IOException(e.getMessage())); } return translate(stats); } @@ -313,7 +316,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub { checkEquals("User " + userId, manualStats, stats); } } catch (InstallerException e) { - throw new IllegalStateException(e); + throw new ParcelableException(new IOException(e.getMessage())); } return translate(stats); } @@ -336,7 +339,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub { checkEquals("External " + userId, manualStats, stats); } } catch (InstallerException e) { - throw new IllegalStateException(e); + throw new ParcelableException(new IOException(e.getMessage())); } final ExternalStorageStats res = new ExternalStorageStats(); |