Merge "Turn down the preliminary foreground service API" into oc-dev
diff --git a/api/current.txt b/api/current.txt
index f448aa6..4fc4bfc 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6889,7 +6889,7 @@
}
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);
@@ -6993,12 +6993,12 @@
}
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 {
@@ -10216,12 +10216,12 @@
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 {
@@ -24010,7 +24010,6 @@
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);
@@ -24046,12 +24045,6 @@
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>);
@@ -24260,8 +24253,6 @@
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();
@@ -24273,15 +24264,11 @@
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);
@@ -24295,10 +24282,8 @@
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 {
@@ -24327,8 +24312,6 @@
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);
@@ -24355,18 +24338,13 @@
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();
@@ -24380,13 +24358,9 @@
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);
@@ -24447,17 +24421,12 @@
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
@@ -30801,6 +30770,7 @@
method public android.util.SizeF getSizeF(java.lang.String);
method public <T extends android.os.Parcelable> android.util.SparseArray<T> getSparseParcelableArray(java.lang.String);
method public java.util.ArrayList<java.lang.String> getStringArrayList(java.lang.String);
+ method public java.util.UUID getUuid(java.lang.String);
method public boolean hasFileDescriptors();
method public void putAll(android.os.Bundle);
method public void putBinder(java.lang.String, android.os.IBinder);
@@ -30825,6 +30795,7 @@
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);
@@ -31354,6 +31325,7 @@
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);
@@ -31399,6 +31371,7 @@
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;
}
@@ -32029,15 +32002,16 @@
}
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);
@@ -32049,7 +32023,10 @@
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 {
@@ -37351,7 +37328,6 @@
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";
}
@@ -37431,16 +37407,16 @@
method public final int getCurrentInterruptionFilter();
method public final int getCurrentListenerHints();
method public android.service.notification.NotificationListenerService.RankingMap getCurrentRanking();
- method public final java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups(java.lang.String);
- method public final java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String);
+ method public final java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups(java.lang.String, android.os.UserHandle);
+ method public final java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String, android.os.UserHandle);
method public final android.service.notification.StatusBarNotification[] getSnoozedNotifications();
method public android.os.IBinder onBind(android.content.Intent);
method public void onInterruptionFilterChanged(int);
method public void onListenerConnected();
method public void onListenerDisconnected();
method public void onListenerHintsChanged(int);
- method public void onNotificationChannelGroupModified(java.lang.String, android.app.NotificationChannelGroup, int);
- method public void onNotificationChannelModified(java.lang.String, android.app.NotificationChannel, int);
+ method public void onNotificationChannelGroupModified(java.lang.String, android.os.UserHandle, android.app.NotificationChannelGroup, int);
+ method public void onNotificationChannelModified(java.lang.String, android.os.UserHandle, android.app.NotificationChannel, int);
method public void onNotificationPosted(android.service.notification.StatusBarNotification);
method public void onNotificationPosted(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
method public void onNotificationRankingUpdate(android.service.notification.NotificationListenerService.RankingMap);
@@ -37453,7 +37429,7 @@
method public final void requestUnbind();
method public final void setNotificationsShown(java.lang.String[]);
method public final void snoozeNotification(java.lang.String, long);
- method public final void updateNotificationChannel(java.lang.String, android.app.NotificationChannel);
+ method public final void updateNotificationChannel(java.lang.String, android.os.UserHandle, android.app.NotificationChannel);
field public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4
field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
field public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 2; // 0x2
diff --git a/api/removed.txt b/api/removed.txt
index 1e8370e..0f5b81a 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -22,6 +22,20 @@
}
+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.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.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 cb77c57..db3792b 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -7325,7 +7325,7 @@
}
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);
@@ -7458,12 +7458,12 @@
}
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 {
@@ -10791,12 +10791,12 @@
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 {
@@ -25932,7 +25932,6 @@
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);
@@ -25968,12 +25967,6 @@
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>);
@@ -26182,8 +26175,6 @@
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();
@@ -26195,15 +26186,11 @@
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);
@@ -26217,10 +26204,8 @@
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 {
@@ -26249,8 +26234,6 @@
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);
@@ -26277,18 +26260,13 @@
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();
@@ -26302,13 +26280,9 @@
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);
@@ -26379,17 +26353,12 @@
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
@@ -33560,6 +33529,7 @@
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);
@@ -33584,6 +33554,7 @@
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);
@@ -34143,6 +34114,7 @@
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);
@@ -34188,6 +34160,7 @@
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;
}
@@ -34923,15 +34896,16 @@
}
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);
@@ -34943,7 +34917,10 @@
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 {
@@ -40463,7 +40440,6 @@
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";
}
@@ -40571,16 +40547,16 @@
method public final int getCurrentInterruptionFilter();
method public final int getCurrentListenerHints();
method public android.service.notification.NotificationListenerService.RankingMap getCurrentRanking();
- method public final java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups(java.lang.String);
- method public final java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String);
+ method public final java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups(java.lang.String, android.os.UserHandle);
+ method public final java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String, android.os.UserHandle);
method public final android.service.notification.StatusBarNotification[] getSnoozedNotifications();
method public android.os.IBinder onBind(android.content.Intent);
method public void onInterruptionFilterChanged(int);
method public void onListenerConnected();
method public void onListenerDisconnected();
method public void onListenerHintsChanged(int);
- method public void onNotificationChannelGroupModified(java.lang.String, android.app.NotificationChannelGroup, int);
- method public void onNotificationChannelModified(java.lang.String, android.app.NotificationChannel, int);
+ method public void onNotificationChannelGroupModified(java.lang.String, android.os.UserHandle, android.app.NotificationChannelGroup, int);
+ method public void onNotificationChannelModified(java.lang.String, android.os.UserHandle, android.app.NotificationChannel, int);
method public void onNotificationPosted(android.service.notification.StatusBarNotification);
method public void onNotificationPosted(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
method public void onNotificationRankingUpdate(android.service.notification.NotificationListenerService.RankingMap);
@@ -40597,7 +40573,7 @@
method public final void snoozeNotification(java.lang.String, java.lang.String);
method public final void snoozeNotification(java.lang.String, long);
method public void unregisterAsSystemService() throws android.os.RemoteException;
- method public final void updateNotificationChannel(java.lang.String, android.app.NotificationChannel);
+ method public final void updateNotificationChannel(java.lang.String, android.os.UserHandle, android.app.NotificationChannel);
field public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4
field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
field public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 2; // 0x2
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 7bdb957..823d88f 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -20,6 +20,20 @@
}
+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.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.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 85f9e9b..f8a04d2 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -6919,7 +6919,7 @@
}
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);
@@ -7023,13 +7023,13 @@
}
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 {
@@ -10252,12 +10252,12 @@
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 {
@@ -24117,7 +24117,6 @@
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);
@@ -24153,12 +24152,6 @@
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>);
@@ -24367,8 +24360,6 @@
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();
@@ -24380,15 +24371,11 @@
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);
@@ -24402,10 +24389,8 @@
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 {
@@ -24434,8 +24419,6 @@
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);
@@ -24462,18 +24445,13 @@
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();
@@ -24487,13 +24465,9 @@
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);
@@ -24554,17 +24528,12 @@
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
@@ -30908,6 +30877,7 @@
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);
@@ -30932,6 +30902,7 @@
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);
@@ -31482,6 +31453,7 @@
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);
@@ -31527,6 +31499,7 @@
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;
}
@@ -32161,15 +32134,16 @@
}
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);
@@ -32181,7 +32155,10 @@
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 {
@@ -37504,7 +37481,6 @@
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";
}
@@ -37610,16 +37586,16 @@
method public final int getCurrentInterruptionFilter();
method public final int getCurrentListenerHints();
method public android.service.notification.NotificationListenerService.RankingMap getCurrentRanking();
- method public final java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups(java.lang.String);
- method public final java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String);
+ method public final java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups(java.lang.String, android.os.UserHandle);
+ method public final java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String, android.os.UserHandle);
method public final android.service.notification.StatusBarNotification[] getSnoozedNotifications();
method public android.os.IBinder onBind(android.content.Intent);
method public void onInterruptionFilterChanged(int);
method public void onListenerConnected();
method public void onListenerDisconnected();
method public void onListenerHintsChanged(int);
- method public void onNotificationChannelGroupModified(java.lang.String, android.app.NotificationChannelGroup, int);
- method public void onNotificationChannelModified(java.lang.String, android.app.NotificationChannel, int);
+ method public void onNotificationChannelGroupModified(java.lang.String, android.os.UserHandle, android.app.NotificationChannelGroup, int);
+ method public void onNotificationChannelModified(java.lang.String, android.os.UserHandle, android.app.NotificationChannel, int);
method public void onNotificationPosted(android.service.notification.StatusBarNotification);
method public void onNotificationPosted(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
method public void onNotificationRankingUpdate(android.service.notification.NotificationListenerService.RankingMap);
@@ -37633,7 +37609,7 @@
method public final void setNotificationsShown(java.lang.String[]);
method public final void snoozeNotification(java.lang.String, java.lang.String);
method public final void snoozeNotification(java.lang.String, long);
- method public final void updateNotificationChannel(java.lang.String, android.app.NotificationChannel);
+ method public final void updateNotificationChannel(java.lang.String, android.os.UserHandle, android.app.NotificationChannel);
field public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4
field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
field public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 2; // 0x2
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 1e8370e..0f5b81a 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -22,6 +22,20 @@
}
+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.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.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 4be4654..9df229c 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 @@
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 169dcb0..c4b7ed7 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2070,6 +2070,7 @@
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 @@
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/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index f4e8f3f..cd9c095 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -27,6 +27,7 @@
import android.content.pm.ParceledListSlice;
import android.net.Uri;
import android.os.Bundle;
+import android.os.UserHandle;
import android.service.notification.Adjustment;
import android.service.notification.Condition;
import android.service.notification.IConditionListener;
@@ -101,9 +102,9 @@
void setOnNotificationPostedTrimFromListener(in INotificationListener token, int trim);
void setInterruptionFilter(String pkg, int interruptionFilter);
- void updateNotificationChannelFromPrivilegedListener(in INotificationListener token, String pkg, in NotificationChannel channel);
- ParceledListSlice getNotificationChannelsFromPrivilegedListener(in INotificationListener token, String pkg);
- ParceledListSlice getNotificationChannelGroupsFromPrivilegedListener(in INotificationListener token, String pkg);
+ void updateNotificationChannelFromPrivilegedListener(in INotificationListener token, String pkg, in UserHandle user, in NotificationChannel channel);
+ ParceledListSlice getNotificationChannelsFromPrivilegedListener(in INotificationListener token, String pkg, in UserHandle user);
+ ParceledListSlice getNotificationChannelGroupsFromPrivilegedListener(in INotificationListener token, String pkg, in UserHandle user);
void applyEnqueuedAdjustmentFromAssistant(in INotificationListener token, in Adjustment adjustment);
void applyAdjustmentFromAssistant(in INotificationListener token, in Adjustment adjustment);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 8ed52a1..cab2114 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4202,9 +4202,22 @@
* @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 @@
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 0ce5eeb..2fa6360 100644
--- a/core/java/android/app/PictureInPictureArgs.java
+++ b/core/java/android/app/PictureInPictureArgs.java
@@ -49,6 +49,13 @@
@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 @@
if (in.readInt() != 0) {
mSourceRectHint = Rect.CREATOR.createFromParcel(in);
}
+ if (in.readInt() != 0) {
+ mSourceRectHintInsets = Rect.CREATOR.createFromParcel(in);
+ }
}
/**
@@ -94,6 +104,9 @@
if (otherArgs.hasSourceBoundsHint()) {
mSourceRectHint = new Rect(otherArgs.getSourceRectHint());
}
+ if (otherArgs.hasSourceBoundsHintInsets()) {
+ mSourceRectHintInsets = new Rect(otherArgs.getSourceRectHintInsets());
+ }
}
/**
@@ -167,7 +180,19 @@
}
/**
- * @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 @@
}
/**
+ * @return the source rect hint insets.
+ * @hide
+ */
+ public Rect getSourceRectHintInsets() {
+ return mSourceRectHintInsets;
+ }
+
+ /**
* @return whether there are launch bounds set
* @hide
*/
@@ -182,12 +215,23 @@
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 @@
} 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 016a0fa..673d1b8 100644
--- a/core/java/android/app/job/JobParameters.java
+++ b/core/java/android/app/job/JobParameters.java
@@ -164,6 +164,20 @@
* 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 879212e..a628619 100644
--- a/core/java/android/app/job/JobServiceEngine.java
+++ b/core/java/android/app/job/JobServiceEngine.java
@@ -54,7 +54,7 @@
/**
* Context we are running in.
*/
- private final Context mContext;
+ private final Service mService;
private final IJobService mBinder;
@@ -182,12 +182,12 @@
/**
* 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 4bb057e..05687ee 100644
--- a/core/java/android/app/job/JobWorkItem.java
+++ b/core/java/android/app/job/JobWorkItem.java
@@ -27,6 +27,7 @@
final public class JobWorkItem implements Parcelable {
final Intent mIntent;
int mWorkId;
+ Object mGrants;
/**
* Create a new piece of work.
@@ -57,6 +58,20 @@
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 6fc4f5c..4b6479a 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 @@
/** {@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 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* 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 23e54ba..d64f018 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -1787,7 +1787,7 @@
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 5f53e27..8b2809a 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -29,6 +29,7 @@
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.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 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 @@
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 @@
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 @@
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 d6bc6a1..1f78bff 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -67,6 +67,7 @@
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.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 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 9b5ff29..167c46d 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -25,6 +25,7 @@
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 @@
}
/**
+ * 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 @@
* 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 c3836a3..c1647c7 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.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.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 @@
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 @@
}
/**
+ * 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 @@
} 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 @@
}
/**
+ * 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 @@
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 b5af766..3942531 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -66,6 +66,7 @@
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.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 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 @@
}
}
- /** {@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 @@
/**
* 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 @@
* 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 @@
* 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 @@
/** @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 @@
* 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 @@
/**
* 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 @@
}
}
+ /** @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 @@
}
}
+ /** @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 @@
*
* @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 @@
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/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index dc1a70d..ed44f25 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -18,6 +18,7 @@
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
+import android.os.UserHandle;
import android.service.notification.IStatusBarNotificationHolder;
import android.service.notification.StatusBarNotification;
import android.service.notification.NotificationRankingUpdate;
@@ -36,8 +37,8 @@
void onInterruptionFilterChanged(int interruptionFilter);
// companion device managers only
- void onNotificationChannelModification(String pkgName, in NotificationChannel channel, int modificationType);
- void onNotificationChannelGroupModification(String pkgName, in NotificationChannelGroup group, int modificationType);
+ void onNotificationChannelModification(String pkgName, in UserHandle user, in NotificationChannel channel, int modificationType);
+ void onNotificationChannelGroupModification(String pkgName, in UserHandle user, in NotificationChannelGroup group, int modificationType);
// rankers only
void onNotificationEnqueued(in IStatusBarNotificationHolder notificationHolder);
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 4833be3..00bd304 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -49,6 +49,7 @@
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
@@ -231,25 +232,25 @@
/**
* Channel or group modification reason provided to
- * {@link #onNotificationChannelModified(String, NotificationChannel, int)} or
- * {@link #onNotificationChannelGroupModified(String, NotificationChannelGroup, int)}- the
- * provided object was created.
+ * {@link #onNotificationChannelModified(String, UserHandle,NotificationChannel, int)} or
+ * {@link #onNotificationChannelGroupModified(String, UserHandle, NotificationChannelGroup,
+ * int)}- the provided object was created.
*/
public static final int NOTIFICATION_CHANNEL_OR_GROUP_ADDED = 1;
/**
* Channel or group modification reason provided to
- * {@link #onNotificationChannelModified(String, NotificationChannel, int)} or
- * {@link #onNotificationChannelGroupModified(String, NotificationChannelGroup, int)}- the
- * provided object was updated.
+ * {@link #onNotificationChannelModified(String, UserHandle, NotificationChannel, int)} or
+ * {@link #onNotificationChannelGroupModified(String, UserHandle,NotificationChannelGroup, int)}
+ * - the provided object was updated.
*/
public static final int NOTIFICATION_CHANNEL_OR_GROUP_UPDATED = 2;
/**
* Channel or group modification reason provided to
- * {@link #onNotificationChannelModified(String, NotificationChannel, int)} or
- * {@link #onNotificationChannelGroupModified(String, NotificationChannelGroup, int)}- the
- * provided object was deleted.
+ * {@link #onNotificationChannelModified(String, UserHandle, NotificationChannel, int)} or
+ * {@link #onNotificationChannelGroupModified(String, UserHandle, NotificationChannelGroup,
+ * int)}- the provided object was deleted.
*/
public static final int NOTIFICATION_CHANNEL_OR_GROUP_DELETED = 3;
@@ -432,13 +433,14 @@
* device} in order to receive this callback.
*
* @param pkg The package the channel belongs to.
+ * @param user The user on which the change was made.
* @param channel The channel that has changed.
* @param modificationType One of {@link #NOTIFICATION_CHANNEL_OR_GROUP_ADDED},
* {@link #NOTIFICATION_CHANNEL_OR_GROUP_UPDATED},
* {@link #NOTIFICATION_CHANNEL_OR_GROUP_DELETED}.
*/
- public void onNotificationChannelModified(String pkg, NotificationChannel channel,
- @ChannelOrGroupModificationTypes int modificationType) {
+ public void onNotificationChannelModified(String pkg, UserHandle user,
+ NotificationChannel channel, @ChannelOrGroupModificationTypes int modificationType) {
// optional
}
@@ -449,13 +451,14 @@
* device} in order to receive this callback.
*
* @param pkg The package the group belongs to.
+ * @param user The user on which the change was made.
* @param group The group that has changed.
* @param modificationType One of {@link #NOTIFICATION_CHANNEL_OR_GROUP_ADDED},
* {@link #NOTIFICATION_CHANNEL_OR_GROUP_UPDATED},
* {@link #NOTIFICATION_CHANNEL_OR_GROUP_DELETED}.
*/
- public void onNotificationChannelGroupModified(String pkg, NotificationChannelGroup group,
- @ChannelOrGroupModificationTypes int modificationType) {
+ public void onNotificationChannelGroupModified(String pkg, UserHandle user,
+ NotificationChannelGroup group, @ChannelOrGroupModificationTypes int modificationType) {
// optional
}
@@ -661,21 +664,24 @@
/**
- * Updates a notification channel for a given package. This should only be used to reflect
- * changes a user has made to the channel via the listener's user interface.
+ * Updates a notification channel for a given package for a given user. This should only be used
+ * to reflect changes a user has made to the channel via the listener's user interface.
*
+ * <p>This method will throw a security exception if you don't have access to notifications
+ * for the given user.</p>
* <p>The caller must have {@link CompanionDeviceManager#getAssociations() an associated
* device} in order to use this method.
*
* @param pkg The package the channel belongs to.
+ * @param user The user the channel belongs to.
* @param channel the channel to update.
*/
- public final void updateNotificationChannel(@NonNull String pkg,
+ public final void updateNotificationChannel(@NonNull String pkg, @NonNull UserHandle user,
@NonNull NotificationChannel channel) {
if (!isBound()) return;
try {
getNotificationInterface().updateNotificationChannelFromPrivilegedListener(
- mWrapper, pkg, channel);
+ mWrapper, pkg, user, channel);
} catch (RemoteException e) {
Log.v(TAG, "Unable to contact notification manager", e);
throw e.rethrowFromSystemServer();
@@ -683,19 +689,22 @@
}
/**
- * Returns all notification channels belonging to the given package.
+ * Returns all notification channels belonging to the given package for a given user.
*
+ * <p>This method will throw a security exception if you don't have access to notifications
+ * for the given user.</p>
* <p>The caller must have {@link CompanionDeviceManager#getAssociations() an associated
* device} in order to use this method.
*
* @param pkg The package to retrieve channels for.
*/
- public final List<NotificationChannel> getNotificationChannels(@NonNull String pkg) {
+ public final List<NotificationChannel> getNotificationChannels(@NonNull String pkg,
+ @NonNull UserHandle user) {
if (!isBound()) return null;
try {
return getNotificationInterface().getNotificationChannelsFromPrivilegedListener(
- mWrapper, pkg).getList();
+ mWrapper, pkg, user).getList();
} catch (RemoteException e) {
Log.v(TAG, "Unable to contact notification manager", e);
throw e.rethrowFromSystemServer();
@@ -703,19 +712,22 @@
}
/**
- * Returns all notification channel groups belonging to the given package.
+ * Returns all notification channel groups belonging to the given package for a given user.
*
+ * <p>This method will throw a security exception if you don't have access to notifications
+ * for the given user.</p>
* <p>The caller must have {@link CompanionDeviceManager#getAssociations() an associated
* device} in order to use this method.
*
* @param pkg The package to retrieve channel groups for.
*/
- public final List<NotificationChannelGroup> getNotificationChannelGroups(@NonNull String pkg) {
+ public final List<NotificationChannelGroup> getNotificationChannelGroups(@NonNull String pkg,
+ @NonNull UserHandle user) {
if (!isBound()) return null;
try {
return getNotificationInterface().getNotificationChannelGroupsFromPrivilegedListener(
- mWrapper, pkg).getList();
+ mWrapper, pkg, user).getList();
} catch (RemoteException e) {
Log.v(TAG, "Unable to contact notification manager", e);
throw e.rethrowFromSystemServer();
@@ -1252,24 +1264,27 @@
}
@Override
- public void onNotificationChannelModification(String pkgName, NotificationChannel channel,
+ public void onNotificationChannelModification(String pkgName, UserHandle user,
+ NotificationChannel channel,
@ChannelOrGroupModificationTypes int modificationType) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = pkgName;
- args.arg2 = channel;
- args.arg3 = modificationType;
+ args.arg2 = user;
+ args.arg3 = channel;
+ args.arg4 = modificationType;
mHandler.obtainMessage(
MyHandler.MSG_ON_NOTIFICATION_CHANNEL_MODIFIED, args).sendToTarget();
}
@Override
- public void onNotificationChannelGroupModification(String pkgName,
+ public void onNotificationChannelGroupModification(String pkgName, UserHandle user,
NotificationChannelGroup group,
@ChannelOrGroupModificationTypes int modificationType) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = pkgName;
- args.arg2 = group;
- args.arg3 = modificationType;
+ args.arg2 = user;
+ args.arg3 = group;
+ args.arg4 = modificationType;
mHandler.obtainMessage(
MyHandler.MSG_ON_NOTIFICATION_CHANNEL_GROUP_MODIFIED, args).sendToTarget();
}
@@ -1841,17 +1856,19 @@
case MSG_ON_NOTIFICATION_CHANNEL_MODIFIED: {
SomeArgs args = (SomeArgs) msg.obj;
String pkgName = (String) args.arg1;
- NotificationChannel channel = (NotificationChannel) args.arg2;
- int modificationType = (int) args.arg3;
- onNotificationChannelModified(pkgName, channel, modificationType);
+ UserHandle user= (UserHandle) args.arg2;
+ NotificationChannel channel = (NotificationChannel) args.arg3;
+ int modificationType = (int) args.arg4;
+ onNotificationChannelModified(pkgName, user, channel, modificationType);
} break;
case MSG_ON_NOTIFICATION_CHANNEL_GROUP_MODIFIED: {
SomeArgs args = (SomeArgs) msg.obj;
String pkgName = (String) args.arg1;
- NotificationChannelGroup group = (NotificationChannelGroup) args.arg2;
- int modificationType = (int) args.arg3;
- onNotificationChannelGroupModified(pkgName, group, modificationType);
+ UserHandle user = (UserHandle) args.arg2;
+ NotificationChannelGroup group = (NotificationChannelGroup) args.arg3;
+ int modificationType = (int) args.arg4;
+ onNotificationChannelGroupModified(pkgName, user, group, modificationType);
} break;
}
}
diff --git a/core/java/android/view/IPinnedStackController.aidl b/core/java/android/view/IPinnedStackController.aidl
index 2fe98c0..dbeb747 100644
--- a/core/java/android/view/IPinnedStackController.aidl
+++ b/core/java/android/view/IPinnedStackController.aidl
@@ -28,4 +28,9 @@
* 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 782f349..9382741 100644
--- a/core/java/android/view/IPinnedStackListener.aidl
+++ b/core/java/android/view/IPinnedStackListener.aidl
@@ -41,9 +41,13 @@
* 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 a7ececf..080ffeb 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1561,6 +1561,16 @@
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 6dbc09c..bf0e10f 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -303,13 +303,16 @@
* 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 bb6e0ee..030c78b 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -1537,6 +1537,18 @@
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 baf6db9..80b6b08 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -82,6 +82,7 @@
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 @@
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 520302e..2c7174d 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 45dccb6..6a31e16 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 ee20236..773a7ea 100644
--- a/libs/hwui/tests/unit/FontRendererTests.cpp
+++ b/libs/hwui/tests/unit/FontRendererTests.cpp
@@ -28,7 +28,7 @@
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 8312bda..5383e57 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 5bf205e..789d5e0 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -365,7 +365,7 @@
* @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 @@
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 @@
}
}
- /**
- * 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 @@
* @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 @@
}
/**
- * 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 4f3314c..3affee5c0 100644
--- a/media/java/android/media/session/ISession.aidl
+++ b/media/java/android/media/session/ISession.aidl
@@ -45,8 +45,6 @@
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 a146c62..893bd3c 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 @@
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 7b5233a..249bcdc 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -18,7 +18,6 @@
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 @@
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 @@
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 9517c08..cf31767 100644
--- a/media/java/android/media/session/ISessionControllerCallback.aidl
+++ b/media/java/android/media/session/ISessionControllerCallback.aidl
@@ -36,6 +36,4 @@
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 bab2af2..622900f 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -23,7 +23,6 @@
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.view.KeyEvent;
import java.lang.ref.WeakReference;
-import java.lang.UnsupportedOperationException;
import java.util.ArrayList;
import java.util.List;
@@ -65,9 +63,7 @@
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 @@
}
/**
- * 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
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 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 @@
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 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 @@
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 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 @@
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 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 @@
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 @@
try {
mSessionBinder.pause();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling pause", e);
+ Log.wtf(TAG, "Error calling pause.", e);
}
}
@@ -925,7 +783,7 @@
try {
mSessionBinder.stop();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling stop", e);
+ Log.wtf(TAG, "Error calling stop.", e);
}
}
@@ -938,7 +796,7 @@
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 @@
try {
mSessionBinder.fastForward();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling fastForward", e);
+ Log.wtf(TAG, "Error calling fastForward.", e);
}
}
@@ -961,7 +819,7 @@
try {
mSessionBinder.next();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling next", e);
+ Log.wtf(TAG, "Error calling next.", e);
}
}
@@ -973,7 +831,7 @@
try {
mSessionBinder.rewind();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling rewind", e);
+ Log.wtf(TAG, "Error calling rewind.", e);
}
}
@@ -984,7 +842,7 @@
try {
mSessionBinder.previous();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling previous", e);
+ Log.wtf(TAG, "Error calling previous.", e);
}
}
@@ -999,36 +857,7 @@
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 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 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 @@
}
}
- @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 @@
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 f10f442..dfd2bb3 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -93,12 +93,6 @@
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 @@
@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 @@
}
/**
- * 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 @@
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 @@
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 @@
}
/**
- * 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 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 @@
}
@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 @@
}
@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 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 @@
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 @@
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 @@
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 1ea6109..8283c8b 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -45,8 +45,7 @@
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 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 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 @@
* <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 @@
* <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 1b55380..71f9ba2 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -436,6 +436,14 @@
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 e95154f..84f41f6 100644
--- a/media/java/android/service/media/IMediaBrowserService.aidl
+++ b/media/java/android/service/media/IMediaBrowserService.aidl
@@ -19,10 +19,8 @@
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 d372efb..b52906d 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -89,15 +89,8 @@
*/
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 @@
/** @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 @@
*
* @see #onLoadChildren
* @see #onLoadItem
- * @see #onSearch
*/
public class Result<T> {
private Object mDebug;
@@ -330,23 +322,6 @@
}
});
}
-
- @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 @@
}
/**
- * 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 @@
* 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 @@
}
}
- 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 ae16949..8e58210 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/accessibility/AccessibilityButtonHelper.java b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityButtonHelper.java
new file mode 100644
index 0000000..972ea34
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityButtonHelper.java
@@ -0,0 +1,62 @@
+/*
+ * 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.settingslib.accessibility;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.Context;
+import android.content.res.Resources;
+import android.provider.Settings;
+import android.view.accessibility.AccessibilityManager;
+
+import java.util.List;
+
+/**
+ * A helper class to assist determining the state of the accessibility button that can appear
+ * within the software-rendered navigation area.
+ */
+public class AccessibilityButtonHelper {
+ public static boolean isRequestedByMagnification(Context ctx) {
+ return Settings.Secure.getInt(ctx.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 0) == 1;
+ }
+
+ public static boolean isRequestedByAccessibilityService(Context ctx) {
+ final AccessibilityManager accessibilityManager = ctx.getSystemService(
+ AccessibilityManager.class);
+ List<AccessibilityServiceInfo> services =
+ accessibilityManager.getEnabledAccessibilityServiceList(
+ AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
+ if (services != null) {
+ for (int i = 0, size = services.size(); i < size; i++) {
+ if ((services.get(i).flags
+ & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON)
+ != 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public static boolean isRequested(Context ctx) {
+ return isRequestedByMagnification(ctx) || isRequestedByAccessibilityService(ctx);
+ }
+
+ public static boolean isDeviceSupported(Resources res) {
+ return res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 8a86c13..10f3b63 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.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.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.HashMap;
import java.util.List;
import java.util.Objects;
+import java.util.UUID;
import java.util.regex.Pattern;
/**
@@ -114,7 +117,7 @@
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 @@
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 @@
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 @@
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 2183573..34fdc9d 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 @@
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 @@
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 88f133c..ccf7a0b 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.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 @@
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 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 11060e6..b57b6cc 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.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
+import java.io.IOException;
import java.util.List;
/**
@@ -49,12 +50,12 @@
}
@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 60e10a1..ea28fe6 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.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 @@
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 @@
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 @@
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 e5d85d1..4c45413 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 @@
import android.app.usage.StorageStatsManager;
import android.os.storage.VolumeInfo;
+import java.io.IOException;
import java.util.List;
/**
@@ -46,12 +47,12 @@
*
* @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 d6bde81..9d09737 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 @@
"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 537cbb8..d4f0181 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 17ecf21..e658e68 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 4875974..0515b35 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 5aeceba..169cc71 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 236fdac..5e7cd97 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 @@
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 c510972..0dca1db 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 @@
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 b243dc7c..755c917 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 d7463a4..be9a7e2 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 @@
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 6309b6d..fd7a658 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 @@
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 4067ae5..02c4ab6 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 @@
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 3cdd3e1..daf4061 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 acaa9b1..cd0cc65 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 @@
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 7985237..92ed49c 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 @@
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 fda8761..ca61b6f 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 @@
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 c08ff20..add96b4 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 @@
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 db18fad..8811d2f 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 4baa472..363e231 100644
--- a/packages/SystemUI/res/drawable/stat_sys_roaming.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_roaming.xml
@@ -14,10 +14,10 @@
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 0000000..f4e8af4
--- /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 5169de4..c1856fa 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 @@
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 33effba..6d4365c 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 ff22ffb..0c9858d 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 da7e4d7..5766dc1 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 eeb28c8..33b1dd4 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 c9479b8..e5f04c6 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 b447979..616e5b9 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.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 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 870d4d1..90e1c07 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 @@
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 6098a20..03076cc 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.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 @@
*/
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 @@
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 @@
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 @@
// 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 c565373..28bd23c 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 @@
@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 ac06703..982b808 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 @@
}
@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 127296cd..67255d3 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 @@
* 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 @@
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 3f26fdd..fbf7ff2 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -78,6 +78,7 @@
private final PipDismissViewController mDismissViewController;
private final PipSnapAlgorithm mSnapAlgorithm;
private final AccessibilityManager mAccessibilityManager;
+ private boolean mShowPipMenuOnAnimationEnd = false;
// The current movement bounds
private Rect mMovementBounds = new Rect();
@@ -89,6 +90,11 @@
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
@@ -216,13 +222,18 @@
setMinimizedStateInternal(false);
}
mDismissViewController.destroyDismissTarget();
- mMenuController.showMenu(MENU_STATE_CLOSE, mMotionHelper.getBounds(),
- mMovementBounds, true /* allowMenuTimeout */);
+ mShowPipMenuOnAnimationEnd = true;
}
public void onPinnedStackAnimationEnded() {
// Always synchronize the motion helper bounds once PiP animations finish
mMotionHelper.synchronizePinnedStackBounds();
+
+ if (mShowPipMenuOnAnimationEnd) {
+ mMenuController.showMenu(MENU_STATE_CLOSE, mMotionHelper.getBounds(),
+ mMovementBounds, true /* allowMenuTimeout */);
+ mShowPipMenuOnAnimationEnd = false;
+ }
}
@Override
@@ -250,7 +261,7 @@
}
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();
@@ -304,7 +315,17 @@
// 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) {
@@ -474,11 +495,34 @@
// 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 f2f0d7a..657f08b 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 @@
@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 d51fe8a..53c36e6 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 @@
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 7518527..e457d72 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 @@
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 92ff17a1..d74e3ac 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 @@
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 @@
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 @@
@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 677642e..cc91753 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 @@
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 8f160dc..6098565 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 @@
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 2713f58..0a99ee6 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.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 void setExposed(boolean exposed, boolean needsFalsingProtection) {
+ final boolean wasExposed = mExposed;
mExposed = exposed;
mNeedsFalsingProtection = needsFalsingProtection;
if (mExposed && mNeedsFalsingProtection) {
@@ -262,6 +264,13 @@
} 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 7928575..8925189 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.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 @@
private INotificationManager mINotificationManager;
private String mPkg;
+ private String mAppName;
private int mAppUid;
private List<NotificationChannel> mNotificationChannels;
private NotificationChannel mSingleNotificationChannel;
@@ -125,7 +127,7 @@
}
}
- String appName = mPkg;
+ mAppName = mPkg;
Drawable pkgicon = null;
CharSequence channelNameText = "";
ApplicationInfo info = null;
@@ -137,7 +139,7 @@
| 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 @@
} 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 @@
});
}
+ @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 fee24b7..802925a 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 @@
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 dc254f9..b01d9cc 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.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 @@
private boolean mBlockWifi;
private boolean mBlockEthernet;
private boolean mActivityEnabled;
+ private boolean mForceBlockWifi;
public SignalClusterView(Context context) {
this(context, null);
@@ -151,6 +150,16 @@
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 @@
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 @@
}
@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 @@
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 @@
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 @@
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 @@
// 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 73eecbb..2e34f24 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.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 @@
private RemoteViews.OnClickHandler mRemoteViewClickHandler;
private boolean mIsChildInGroup;
private InflationExceptionHandler mInflateExceptionHandler;
+ private boolean mRedactAmbient;
public NotificationInflater(ExpandableNotificationRow row) {
mRow = row;
@@ -92,6 +95,21 @@
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 @@
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 @@
}
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 @@
}
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 a9eb20b..6361eb6 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 @@
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 df814a0..79191f3 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_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.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.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.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 @@
}
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 @@
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 @@
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 @@
}
final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+ if (row.isDark()) {
+ return false;
+ }
bindGuts(row, item);
NotificationGuts guts = row.getGuts();
@@ -5904,8 +5925,10 @@
}
});
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 @@
}
}
+ 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 @@
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 a456786..e98dc98 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 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 67b5596..4421a6a 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 @@
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 @@
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 @@
&& 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 @@
} 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 @@
boolean isDefault;
boolean userSetup;
boolean roaming;
+ boolean dataDisabled;
@Override
public void copyFrom(State s) {
@@ -592,6 +585,7 @@
carrierNetworkChangeMode = state.carrierNetworkChangeMode;
userSetup = state.userSetup;
roaming = state.roaming;
+ dataDisabled = state.dataDisabled;
}
@Override
@@ -609,6 +603,7 @@
builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode)
.append(',');
builder.append("userSetup=").append(userSetup);
+ builder.append("dataDisabled=").append(dataDisabled);
}
@Override
@@ -623,6 +618,7 @@
&& ((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 c02ce0e..ab4a8f2 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 @@
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 c21f444..60f4ab8 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 @@
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 aaa0568..ec7e557 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 @@
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 @@
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 374408d..dfc3591 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 @@
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 2104cb1..a773acf 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 @@
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 @@
@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 3ed1681..f6c75a8 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 @@
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 505e1d8..b39171e 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.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.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 @@
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 @@
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 @@
}
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 @@
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 @@
}
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 @@
}
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 @@
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 dfe00f9..6470c11 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.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 @@
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 @@
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 @@
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 1627925..e542c37 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 @@
verifyLastQsMobileDataIndicators(true,
testStrength,
- TelephonyIcons.QS_DATA_1X, false, false);
+ TelephonyIcons.ICON_1X, false, false);
}
}
@@ -434,7 +434,7 @@
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 73fa5aa1..edfa326 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 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 39bfeda..8ad3d23 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.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 @@
return mKeyguardManager != null && mKeyguardManager.isKeyguardLocked();
}
+ @BinderThread
@SuppressWarnings("deprecation")
@Override
public void setImeWindowStatus(IBinder token, IBinder startInputToken, int vis,
@@ -2161,9 +2163,23 @@
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 d796098..452fe1d 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3272,6 +3272,8 @@
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 @@
return Math.max(0, path.getUsableSpace() - storage.getStorageLowBytes(path));
}
}
+ } catch (IOException e) {
+ throw new ParcelableException(e);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -3329,13 +3333,13 @@
+ " 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 024aabd..d43fa01 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 @@
*/
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 @@
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 @@
case DISPATCH_UIDS_CHANGED_UI_MSG: {
dispatchUidsChanged();
} break;
+ case PUSH_TEMP_WHITELIST_UI_MSG: {
+ pushTempWhitelist();
+ } break;
}
}
}
@@ -6493,7 +6511,8 @@
// 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 @@
}
}
- /**
- * 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 @@
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 @@
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 @@
}
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="
@@ -22699,6 +22701,80 @@
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--) {
@@ -22713,6 +22789,15 @@
}
}
+ 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 2881787..494aaa7 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 @@
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 @@
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 02ec075..c9c1d00 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 @@
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 @@
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 baa71d7..349180f 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 @@
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 @@
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 @@
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 c697f28..a580d4b 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 @@
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 @@
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/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 2687242..e7617f5 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -929,11 +929,8 @@
synchronized (VolumeStreamState.class) {
int numStreamTypes = AudioSystem.getNumStreamTypes();
for (int streamType = 0; streamType < numStreamTypes; streamType++) {
- if (streamType != mStreamVolumeAlias[streamType]) {
- mStreamStates[streamType].
- setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]],
- TAG);
- }
+ mStreamStates[streamType]
+ .setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]], TAG);
// apply stream volume
if (!mStreamStates[streamType].mIsMuted) {
mStreamStates[streamType].applyAllVolumes();
@@ -1022,20 +1019,21 @@
}
mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias;
- final int oldStreamA11yAlias = mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY];
- if (oldStreamA11yAlias != a11yStreamAlias) {
- mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY] = a11yStreamAlias;
- mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].mVolumeIndexSettingName =
- System.VOLUME_SETTINGS_INT[a11yStreamAlias];
- // restore the value from the settings when the alias changes
- mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].readSettings();
- }
+ mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY] = a11yStreamAlias;
if (updateVolumes) {
mStreamStates[AudioSystem.STREAM_DTMF].setAllIndexes(mStreamStates[dtmfStreamAlias],
caller);
+
+ mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].mVolumeIndexSettingName =
+ System.VOLUME_SETTINGS_INT[a11yStreamAlias];
mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setAllIndexes(
mStreamStates[a11yStreamAlias], caller);
+ if (sIndependentA11yVolume) {
+ // restore the a11y values from the settings
+ mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].readSettings();
+ }
+
// apply stream mute states according to new value of mRingerModeAffectedStreams
setRingerModeInt(getRingerModeInternal(), false);
sendMsg(mAudioHandler,
@@ -4228,7 +4226,17 @@
return mIndexMin;
}
+ /**
+ * Copies all device/index pairs from the given VolumeStreamState after initializing
+ * them with the volume for DEVICE_OUT_DEFAULT. No-op if the source VolumeStreamState
+ * has the same stream type as this instance.
+ * @param srcStream
+ * @param caller
+ */
public void setAllIndexes(VolumeStreamState srcStream, String caller) {
+ if (mStreamType == srcStream.mStreamType) {
+ return;
+ }
synchronized (VolumeStreamState.class) {
int srcStreamType = srcStream.getStreamType();
// apply default device volume from source stream to all devices first in case
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 0000000..e413d8d
--- /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 d01de3c..c8bfa34 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 @@
// 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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 c7ef0e2..9144966 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.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 @@
* 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 @@
// 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 @@
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 @@
}
/** 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 @@
@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 @@
// 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 @@
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 @@
* 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,296 +386,280 @@
@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();
- }
- }
-
- void doCallback(int arg2) {
- synchronized (mLock) {
- if (DEBUG) {
- Slog.d(TAG, "MSG_CALLBACK 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);
- }
- }
- }
- }
-
- void doCancel(int arg1) {
- synchronized (mLock) {
- if (mVerb == VERB_FINISHED) {
- if (DEBUG) {
- Slog.d(TAG,
- "Trying to process cancel for torn-down context, ignoring.");
- }
+ if (!verifyCallingUidLocked(callingUid)) {
return;
}
- mParams.setStopReason(arg1);
- if (arg1 == JobParameters.REASON_PREEMPT) {
- mPreferredUid = mRunningJob != null ? mRunningJob.getUid() :
- NO_PREFERRED_UID;
- }
- handleCancelH();
+ doCallbackLocked(reschedule);
}
-
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
+ }
- /** Start the job on the service. */
- private void handleServiceBoundH() {
+ void doCallbackLocked(boolean reschedule) {
+ if (DEBUG) {
+ Slog.d(TAG, "doCallback of : " + mRunningJob
+ + " v:" + VERB_STRINGS[mVerb]);
+ }
+ removeOpTimeOutLocked();
+
+ if (mVerb == VERB_STARTING) {
+ handleStartedLocked(reschedule);
+ } else if (mVerb == VERB_EXECUTING ||
+ mVerb == VERB_STOPPING) {
+ handleFinishedLocked(reschedule);
+ } else {
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, "Unrecognised callback: " + mRunningJob);
}
}
+ }
- /**
- * 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;
- }
- scheduleOpTimeOutLocked();
- break;
- default:
- Slog.e(TAG, "Handling started job but job wasn't starting! Was "
- + VERB_STRINGS[mVerb] + ".");
- return;
+ void doCancelLocked(int arg1) {
+ if (mVerb == VERB_FINISHED) {
+ if (DEBUG) {
+ Slog.d(TAG,
+ "Trying to process cancel for torn-down context, ignoring.");
}
+ 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] + ".");
- }
+ mParams.setStopReason(arg1);
+ if (arg1 == JobParameters.REASON_PREEMPT) {
+ mPreferredUid = mRunningJob != null ? mRunningJob.getUid() :
+ NO_PREFERRED_UID;
}
+ handleCancelLocked();
+ }
- /**
- * 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;
- }
+ /** Start the job on the service. */
+ private void handleServiceBoundLocked() {
+ if (DEBUG) {
+ Slog.d(TAG, "handleServiceBound for " + mRunningJob.toShortString());
}
-
- /** 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 */);
- }
+ if (mVerb != VERB_BINDING) {
+ Slog.e(TAG, "Sending onStartJob for a job that isn't pending. "
+ + VERB_STRINGS[mVerb]);
+ closeAndCleanupJobLocked(false /* reschedule */);
+ return;
}
-
- /**
- * 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;
+ if (mCancelled) {
+ if (DEBUG) {
+ Slog.d(TAG, "Job cancelled while waiting for bind to complete. "
+ + mRunningJob);
}
- 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 */);
- }
+ 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);
+ }
+ }
- /**
- * 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) {
+ /**
+ * 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;
}
- completedJob = mRunningJob;
- mJobPackageTracker.noteInactive(completedJob);
- try {
- mBatteryStats.noteJobFinish(mRunningJob.getBatteryName(),
- mRunningJob.getSourceUid());
- } catch (RemoteException e) {
- // Whatever.
+ if (mCancelled) {
+ if (DEBUG) {
+ Slog.d(TAG, "Job cancelled while waiting for onStartJob to complete.");
+ }
+ // Cancelled *while* waiting for acknowledgeStartMessage from client.
+ handleCancelLocked();
+ return;
}
- 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);
- }
+ 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 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 #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 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 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 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);
+ }
+
+ /**
* Called when sending a message to the client, over whose execution we have no control. If
* we haven't received a response in a certain amount of time, we want to give up and carry
* on with life.
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 e8cc078..1ab66b9 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.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.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 @@
final String tag;
- private IBinder permissionOwner;
+ private GrantedUriPermissions uriPerms;
private boolean prepared;
/**
@@ -284,12 +285,17 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
}
+ 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 @@
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 @@
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 53a8092..ee348cf 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 @@
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 @@
}
}
- 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 @@
}
@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 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 @@
}
@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 @@
}
@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 @@
}
@Override
- public int getRepeatMode() {
- return mRepeatMode;
- }
-
- @Override
- public boolean isShuffleModeEnabled() {
- return mShuffleModeEnabled;
- }
-
- @Override
public boolean isTransportControlEnabled() {
return MediaSessionRecord.this.isTransportControlEnabled();
}
@@ -1524,9 +1363,7 @@
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 @@
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 f334ba4..cc3948e 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.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;
@@ -1322,7 +1323,8 @@
if (!fromListener) {
mListeners.notifyNotificationChannelChanged(
- pkg, modifiedChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);
+ pkg, UserHandle.getUserHandleForUid(uid),
+ modifiedChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);
}
synchronized (mNotificationLock) {
@@ -1647,7 +1649,8 @@
Preconditions.checkNotNull(group, "group in list is null");
mRankingHelper.createNotificationChannelGroup(pkg, Binder.getCallingUid(), group,
true /* fromTargetApp */);
- mListeners.notifyNotificationChannelGroupChanged(pkg, group,
+ mListeners.notifyNotificationChannelGroupChanged(pkg,
+ UserHandle.of(UserHandle.getCallingUserId()), group,
NOTIFICATION_CHANNEL_OR_GROUP_ADDED);
}
savePolicyFile();
@@ -1663,6 +1666,7 @@
mRankingHelper.createNotificationChannel(pkg, uid, channel,
true /* fromTargetApp */);
mListeners.notifyNotificationChannelChanged(pkg,
+ UserHandle.getUserHandleForUid(uid),
mRankingHelper.getNotificationChannel(pkg, uid, channel.getId(), false),
NOTIFICATION_CHANNEL_OR_GROUP_ADDED);
}
@@ -1708,6 +1712,7 @@
UserHandle.getUserId(callingUid), REASON_CHANNEL_BANNED, null);
mRankingHelper.deleteNotificationChannel(pkg, callingUid, channelId);
mListeners.notifyNotificationChannelChanged(pkg,
+ UserHandle.getUserHandleForUid(callingUid),
mRankingHelper.getNotificationChannel(pkg, callingUid, channelId, true),
NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
savePolicyFile();
@@ -1737,11 +1742,14 @@
true,
UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED,
null);
- mListeners.notifyNotificationChannelChanged(pkg, deletedChannel,
+ mListeners.notifyNotificationChannelChanged(pkg,
+ UserHandle.getUserHandleForUid(callingUid),
+ deletedChannel,
NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
}
mListeners.notifyNotificationChannelGroupChanged(
- pkg, groupToDelete, NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
+ pkg, UserHandle.getUserHandleForUid(callingUid), groupToDelete,
+ NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
savePolicyFile();
}
}
@@ -2691,43 +2699,59 @@
@Override
public void updateNotificationChannelFromPrivilegedListener(INotificationListener token,
- String pkg, NotificationChannel channel) throws RemoteException {
+ String pkg, UserHandle user, NotificationChannel channel) throws RemoteException {
Preconditions.checkNotNull(channel);
+ Preconditions.checkNotNull(pkg);
+ Preconditions.checkNotNull(user);
- ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
- if (!hasCompanionDevice(info)) {
- throw new SecurityException(info + " does not have access");
- }
-
- int uid = mPackageManager.getPackageUid(pkg, 0, info.userid);
- updateNotificationChannelInt(pkg, uid, channel, true);
+ verifyPrivilegedListener(token, user);
+ updateNotificationChannelInt(pkg, getUidForPackageAndUser(pkg, user), channel, true);
}
@Override
public ParceledListSlice<NotificationChannel> getNotificationChannelsFromPrivilegedListener(
- INotificationListener token, String pkg) throws RemoteException {
- ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
- if (!hasCompanionDevice(info)) {
- throw new SecurityException(info + " does not have access");
- }
+ INotificationListener token, String pkg, UserHandle user) throws RemoteException {
+ Preconditions.checkNotNull(pkg);
+ Preconditions.checkNotNull(user);
+ verifyPrivilegedListener(token, user);
- int uid = mPackageManager.getPackageUid(pkg, 0, info.userid);
- return mRankingHelper.getNotificationChannels(pkg, uid, false /* includeDeleted */);
+ return mRankingHelper.getNotificationChannels(pkg, getUidForPackageAndUser(pkg, user),
+ false /* includeDeleted */);
}
@Override
public ParceledListSlice<NotificationChannelGroup>
getNotificationChannelGroupsFromPrivilegedListener(
- INotificationListener token, String pkg) throws RemoteException {
+ INotificationListener token, String pkg, UserHandle user) throws RemoteException {
+ Preconditions.checkNotNull(pkg);
+ Preconditions.checkNotNull(user);
+ verifyPrivilegedListener(token, user);
+
+ List<NotificationChannelGroup> groups = new ArrayList<>();
+ groups.addAll(mRankingHelper.getNotificationChannelGroups(
+ pkg, getUidForPackageAndUser(pkg, user)));
+ return new ParceledListSlice<>(groups);
+ }
+
+ private void verifyPrivilegedListener(INotificationListener token, UserHandle user) {
ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
if (!hasCompanionDevice(info)) {
throw new SecurityException(info + " does not have access");
}
+ if (!info.enabledAndUserMatches(user.getIdentifier())) {
+ throw new SecurityException(info + " does not have access");
+ }
+ }
- List<NotificationChannelGroup> groups = new ArrayList<>();
- int uid = mPackageManager.getPackageUid(pkg, 0, info.userid);
- groups.addAll(mRankingHelper.getNotificationChannelGroups(pkg, uid));
- return new ParceledListSlice<>(groups);
+ private int getUidForPackageAndUser(String pkg, UserHandle user) throws RemoteException {
+ int uid = 0;
+ long identity = Binder.clearCallingIdentity();
+ try {
+ uid = mPackageManager.getPackageUid(pkg, 0, user.getIdentifier());
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ return uid;
}
};
@@ -3162,16 +3186,16 @@
// 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());
@@ -3203,6 +3227,26 @@
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)) {
@@ -5019,7 +5063,7 @@
}
}
- protected void notifyNotificationChannelChanged(final String pkg,
+ protected void notifyNotificationChannelChanged(final String pkg, final UserHandle user,
final NotificationChannel channel, final int modificationType) {
if (channel == null) {
return;
@@ -5034,15 +5078,16 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- notifyNotificationChannelChanged(serviceInfo, pkg, channel,
- modificationType);
+ notifyNotificationChannelChanged(
+ serviceInfo, pkg, user, channel, modificationType);
}
});
}
}
- protected void notifyNotificationChannelGroupChanged(final String pkg,
- final NotificationChannelGroup group, final int modificationType) {
+ protected void notifyNotificationChannelGroupChanged(
+ final String pkg, final UserHandle user, final NotificationChannelGroup group,
+ final int modificationType) {
if (group == null) {
return;
}
@@ -5056,8 +5101,8 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- notifyNotificationChannelGroupChanged(serviceInfo, pkg, group,
- modificationType);
+ notifyNotificationChannelGroupChanged(
+ serviceInfo, pkg, user, group, modificationType);
}
});
}
@@ -5118,22 +5163,22 @@
}
void notifyNotificationChannelChanged(ManagedServiceInfo info,
- final String pkg, final NotificationChannel channel,
+ final String pkg, final UserHandle user, final NotificationChannel channel,
final int modificationType) {
final INotificationListener listener = (INotificationListener) info.service;
try {
- listener.onNotificationChannelModification(pkg, channel, modificationType);
+ listener.onNotificationChannelModification(pkg, user, channel, modificationType);
} catch (RemoteException ex) {
Log.e(TAG, "unable to notify listener (channel changed): " + listener, ex);
}
}
private void notifyNotificationChannelGroupChanged(ManagedServiceInfo info,
- final String pkg, final NotificationChannelGroup group,
+ final String pkg, final UserHandle user, final NotificationChannelGroup group,
final int modificationType) {
final INotificationListener listener = (INotificationListener) info.service;
try {
- listener.onNotificationChannelGroupModification(pkg, group, modificationType);
+ listener.onNotificationChannelGroupModification(pkg, user, group, modificationType);
} catch (RemoteException ex) {
Log.e(TAG, "unable to notify listener (channel group changed): " + listener, ex);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 28810a7..312c310 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 @@
* $ 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 @@
}
};
- 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 @@
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 @@
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 @@
}
// 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 @@
}
}
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 @@
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 @@
* 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 @@
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 @@
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 @@
? 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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
? 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 4f29bfa..bcb4121 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.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 @@
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 @@
PowerManager mPowerManager;
ActivityManagerInternal mActivityManagerInternal;
InputManagerInternal mInputManagerInternal;
+ InputMethodManagerInternal mInputMethodManagerInternal;
DreamManagerInternal mDreamManagerInternal;
PowerManagerInternal mPowerManagerInternal;
IStatusBarService mStatusBarService;
@@ -494,6 +497,9 @@
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 @@
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 @@
}
@Override
+ public void setDismissImeOnBackKeyPressed(boolean newValue) {
+ synchronized (mLock) {
+ mDismissImeOnBackKeyPressed = newValue;
+ }
+ }
+
+ @Override
public int getInputMethodWindowVisibleHeightLw() {
return mDockBottom - mCurBottom;
}
@@ -8170,6 +8204,8 @@
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 a77d33f..03b754f 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.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.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 @@
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 @@
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 1684878..82416ec 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.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 @@
mSnapAlgorithm.setMinimized(isMinimized);
});
}
+
+ @Override
+ public int getDisplayRotation() {
+ synchronized (mService.mWindowMap) {
+ return mDisplayInfo.rotation;
+ }
+ }
}
/**
@@ -221,22 +227,26 @@
* @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);
+ 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;
+ 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 @@
* 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;
+
+ // 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 */);
+
+ outBounds.set(postChangeStackBounds);
+ return true;
}
-
- 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);
- }
-
- notifyMovementBoundsChanged(false /* fromImeAdjustment */);
-
- outBounds.set(postChangeStackBounds);
- return true;
}
/**
@@ -378,25 +390,27 @@
* 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);
+ 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);
}
- 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);
- } catch (RemoteException e) {
- Slog.e(TAG_WM, "Error delivering actions changed event.", e);
}
}
}
@@ -405,11 +419,13 @@
* @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 @@
* controller.
*/
private Rect getMovementBounds(Rect stackBounds) {
- return getMovementBounds(stackBounds, true /* adjustForIme */);
+ synchronized (mService.mWindowMap) {
+ return getMovementBounds(stackBounds, true /* adjustForIme */);
+ }
}
/**
@@ -425,23 +443,27 @@
* controller.
*/
private Rect getMovementBounds(Rect stackBounds, boolean adjustForIme) {
- final Rect movementBounds = new Rect();
- getInsetBounds(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;
+ // 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 0049585..252b4d4 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 @@
@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 86662b9..74ecd11 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 @@
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::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 @@
// 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/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index f666727..57ee928 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -49,6 +49,7 @@
import android.content.pm.ParceledListSlice;
import android.graphics.Color;
import android.os.Binder;
+import android.os.Process;
import android.os.UserHandle;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
@@ -460,10 +461,10 @@
mBinderService.createNotificationChannels(PKG,
new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
- eq(mTestNotificationChannel),
+ eq(Process.myUserHandle()), eq(mTestNotificationChannel),
eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
- eq(channel2),
+ eq(Process.myUserHandle()), eq(channel2),
eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
}
@@ -481,10 +482,10 @@
mBinderService.createNotificationChannelGroups(PKG,
new ParceledListSlice(Arrays.asList(group1, group2)));
verify(mNotificationListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
- eq(group1),
+ eq(Process.myUserHandle()), eq(group1),
eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
verify(mNotificationListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
- eq(group2),
+ eq(Process.myUserHandle()), eq(group2),
eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
}
@@ -503,7 +504,7 @@
reset(mNotificationListeners);
mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
- eq(mTestNotificationChannel),
+ eq(Process.myUserHandle()), eq(mTestNotificationChannel),
eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
}
@@ -520,7 +521,7 @@
reset(mNotificationListeners);
mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
- eq(mTestNotificationChannel),
+ eq(Process.myUserHandle()), eq(mTestNotificationChannel),
eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
}
@@ -537,7 +538,7 @@
reset(mNotificationListeners);
mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
verify(mNotificationListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
- eq(ncg),
+ eq(Process.myUserHandle()), eq(ncg),
eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
}
@@ -550,12 +551,12 @@
when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
mBinderService.updateNotificationChannelFromPrivilegedListener(
- null, PKG, mTestNotificationChannel);
+ null, PKG, Process.myUserHandle(), mTestNotificationChannel);
verify(mRankingHelper, times(1)).updateNotificationChannel(anyString(), anyInt(), any());
verify(mNotificationListeners, never()).notifyNotificationChannelChanged(eq(PKG),
- eq(mTestNotificationChannel),
+ eq(Process.myUserHandle()), eq(mTestNotificationChannel),
eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
}
@@ -568,7 +569,7 @@
try {
mBinderService.updateNotificationChannelFromPrivilegedListener(
- null, PKG, mTestNotificationChannel);
+ null, PKG, Process.myUserHandle(), mTestNotificationChannel);
fail("listeners that don't have a companion device shouldn't be able to call this");
} catch (SecurityException e) {
// pass
@@ -577,7 +578,33 @@
verify(mRankingHelper, never()).updateNotificationChannel(anyString(), anyInt(), any());
verify(mNotificationListeners, never()).notifyNotificationChannelChanged(eq(PKG),
- eq(mTestNotificationChannel),
+ eq(Process.myUserHandle()), eq(mTestNotificationChannel),
+ eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
+ mNotificationManagerService.setRankingHelper(mRankingHelper);
+ List<String> associations = new ArrayList<>();
+ associations.add("a");
+ when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+ mListener = mock(ManagedServices.ManagedServiceInfo.class);
+ when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
+ when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
+
+ try {
+ mBinderService.updateNotificationChannelFromPrivilegedListener(
+ null, PKG, UserHandle.ALL, mTestNotificationChannel);
+ fail("incorrectly allowed a change to a user listener cannot see");
+ } catch (SecurityException e) {
+ // pass
+ }
+
+ verify(mRankingHelper, never()).updateNotificationChannel(anyString(), anyInt(), any());
+
+ verify(mNotificationListeners, never()).notifyNotificationChannelChanged(eq(PKG),
+ eq(Process.myUserHandle()), eq(mTestNotificationChannel),
eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
}
@@ -589,7 +616,8 @@
associations.add("a");
when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
- mBinderService.getNotificationChannelsFromPrivilegedListener(null, PKG);
+ mBinderService.getNotificationChannelsFromPrivilegedListener(
+ null, PKG, Process.myUserHandle());
verify(mRankingHelper, times(1)).getNotificationChannels(
anyString(), anyInt(), anyBoolean());
@@ -603,7 +631,8 @@
when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
try {
- mBinderService.getNotificationChannelsFromPrivilegedListener(null, PKG);
+ mBinderService.getNotificationChannelsFromPrivilegedListener(
+ null, PKG, Process.myUserHandle());
fail("listeners that don't have a companion device shouldn't be able to call this");
} catch (SecurityException e) {
// pass
@@ -615,13 +644,37 @@
@Test
@UiThreadTest
+ public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
+ mNotificationManagerService.setRankingHelper(mRankingHelper);
+ List<String> associations = new ArrayList<>();
+ associations.add("a");
+ when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+ mListener = mock(ManagedServices.ManagedServiceInfo.class);
+ when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
+ when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
+
+ try {
+ mBinderService.getNotificationChannelsFromPrivilegedListener(
+ null, PKG, Process.myUserHandle());
+ fail("listener getting channels from a user they cannot see");
+ } catch (SecurityException e) {
+ // pass
+ }
+
+ verify(mRankingHelper, never()).getNotificationChannels(
+ anyString(), anyInt(), anyBoolean());
+ }
+
+ @Test
+ @UiThreadTest
public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
mNotificationManagerService.setRankingHelper(mRankingHelper);
List<String> associations = new ArrayList<>();
associations.add("a");
when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
- mBinderService.getNotificationChannelGroupsFromPrivilegedListener(null, PKG);
+ mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
+ null, PKG, Process.myUserHandle());
verify(mRankingHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
}
@@ -634,7 +687,29 @@
when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
try {
- mBinderService.getNotificationChannelGroupsFromPrivilegedListener(null, PKG);
+ mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
+ null, PKG, Process.myUserHandle());
+ fail("listeners that don't have a companion device shouldn't be able to call this");
+ } catch (SecurityException e) {
+ // pass
+ }
+
+ verify(mRankingHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
+ }
+
+ @Test
+ @UiThreadTest
+ public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
+ mNotificationManagerService.setRankingHelper(mRankingHelper);
+ List<String> associations = new ArrayList<>();
+ when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+ mListener = mock(ManagedServices.ManagedServiceInfo.class);
+ when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
+ when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
+
+ try {
+ mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
+ null, PKG, Process.myUserHandle());
fail("listeners that don't have a companion device shouldn't be able to call this");
} catch (SecurityException e) {
// pass
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 0000000..243c1b3
--- /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 0000000..8f2f34e
--- /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 5ad7f80..094c7bd 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.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 @@
try {
return mInstaller.isQuotaSupported(volumeUuid);
} catch (InstallerException e) {
- throw new IllegalStateException(e);
+ throw new ParcelableException(new IOException(e.getMessage()));
}
}
@@ -163,7 +164,8 @@
} 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 @@
} 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
checkEquals("External " + userId, manualStats, stats);
}
} catch (InstallerException e) {
- throw new IllegalStateException(e);
+ throw new ParcelableException(new IOException(e.getMessage()));
}
final ExternalStorageStats res = new ExternalStorageStats();