diff options
70 files changed, 1429 insertions, 1765 deletions
diff --git a/api/current.txt b/api/current.txt index 7a3ec57ebcbb..4fc4bfc76854 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5604,7 +5604,6 @@ package android.app { method public boolean removeAutomaticZenRule(java.lang.String); method public final void setInterruptionFilter(int); method public void setNotificationPolicy(android.app.NotificationManager.Policy); - method public deprecated android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification); method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule); field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED"; field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED"; @@ -6890,7 +6889,7 @@ package android.app.job { } public abstract class JobServiceEngine { - ctor public JobServiceEngine(android.content.Context); + ctor public JobServiceEngine(android.app.Service); method public final android.os.IBinder getBinder(); method public final void jobFinished(android.app.job.JobParameters, boolean); method public abstract boolean onStartJob(android.app.job.JobParameters); @@ -24011,7 +24010,6 @@ package android.media.browse { method public android.content.ComponentName getServiceComponent(); method public android.media.session.MediaSession.Token getSessionToken(); method public boolean isConnected(); - method public void search(java.lang.String, android.os.Bundle, android.media.browse.MediaBrowser.SearchCallback); method public void subscribe(java.lang.String, android.media.browse.MediaBrowser.SubscriptionCallback); method public void subscribe(java.lang.String, android.os.Bundle, android.media.browse.MediaBrowser.SubscriptionCallback); method public void unsubscribe(java.lang.String); @@ -24047,12 +24045,6 @@ package android.media.browse { field public static final int FLAG_PLAYABLE = 2; // 0x2 } - public static abstract class MediaBrowser.SearchCallback { - ctor public MediaBrowser.SearchCallback(); - method public void onError(java.lang.String, android.os.Bundle); - method public void onSearchResult(java.lang.String, android.os.Bundle, java.util.List<android.media.browse.MediaBrowser.MediaItem>); - } - public static abstract class MediaBrowser.SubscriptionCallback { ctor public MediaBrowser.SubscriptionCallback(); method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>); @@ -24261,8 +24253,6 @@ package android.media.session { public final class MediaController { ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token); - method public void addQueueItem(android.media.MediaDescription); - method public void addQueueItem(android.media.MediaDescription, int); method public void adjustVolume(int, int); method public boolean dispatchMediaButtonEvent(android.view.KeyEvent); method public android.os.Bundle getExtras(); @@ -24274,15 +24264,11 @@ package android.media.session { method public java.util.List<android.media.session.MediaSession.QueueItem> getQueue(); method public java.lang.CharSequence getQueueTitle(); method public int getRatingType(); - method public int getRepeatMode(); method public android.app.PendingIntent getSessionActivity(); method public android.media.session.MediaSession.Token getSessionToken(); method public android.media.session.MediaController.TransportControls getTransportControls(); - method public boolean isShuffleModeEnabled(); method public void registerCallback(android.media.session.MediaController.Callback); method public void registerCallback(android.media.session.MediaController.Callback, android.os.Handler); - method public void removeQueueItem(android.media.MediaDescription); - method public void removeQueueItemAt(int); method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver); method public void setVolumeTo(int, int); method public void unregisterCallback(android.media.session.MediaController.Callback); @@ -24296,10 +24282,8 @@ package android.media.session { method public void onPlaybackStateChanged(android.media.session.PlaybackState); method public void onQueueChanged(java.util.List<android.media.session.MediaSession.QueueItem>); method public void onQueueTitleChanged(java.lang.CharSequence); - method public void onRepeatModeChanged(int); method public void onSessionDestroyed(); method public void onSessionEvent(java.lang.String, android.os.Bundle); - method public void onShuffleModeChanged(boolean); } public static final class MediaController.PlaybackInfo { @@ -24328,8 +24312,6 @@ package android.media.session { method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle); method public void sendCustomAction(java.lang.String, android.os.Bundle); method public void setRating(android.media.Rating); - method public void setRepeatMode(int); - method public void setShuffleModeEnabled(boolean); method public void skipToNext(); method public void skipToPrevious(); method public void skipToQueueItem(long); @@ -24356,18 +24338,13 @@ package android.media.session { method public void setQueue(java.util.List<android.media.session.MediaSession.QueueItem>); method public void setQueueTitle(java.lang.CharSequence); method public void setRatingType(int); - method public void setRepeatMode(int); method public void setSessionActivity(android.app.PendingIntent); - method public void setShuffleModeEnabled(boolean); field public static final deprecated int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1 - field public static final int FLAG_HANDLES_QUEUE_COMMANDS = 4; // 0x4 field public static final deprecated int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2 } public static abstract class MediaSession.Callback { ctor public MediaSession.Callback(); - method public void onAddQueueItem(android.media.MediaDescription); - method public void onAddQueueItem(android.media.MediaDescription, int); method public void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver); method public void onCustomAction(java.lang.String, android.os.Bundle); method public void onFastForward(); @@ -24381,13 +24358,9 @@ package android.media.session { method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle); method public void onPrepareFromSearch(java.lang.String, android.os.Bundle); method public void onPrepareFromUri(android.net.Uri, android.os.Bundle); - method public void onRemoveQueueItem(android.media.MediaDescription); - method public void onRemoveQueueItemAt(int); method public void onRewind(); method public void onSeekTo(long); method public void onSetRating(android.media.Rating); - method public void onSetRepeatMode(int); - method public void onSetShuffleModeEnabled(boolean); method public void onSkipToNext(); method public void onSkipToPrevious(); method public void onSkipToQueueItem(long); @@ -24448,17 +24421,12 @@ package android.media.session { field public static final long ACTION_REWIND = 8L; // 0x8L field public static final long ACTION_SEEK_TO = 256L; // 0x100L field public static final long ACTION_SET_RATING = 128L; // 0x80L - field public static final long ACTION_SET_REPEAT_MODE = 262144L; // 0x40000L - field public static final long ACTION_SET_SHUFFLE_MODE_ENABLED = 524288L; // 0x80000L field public static final long ACTION_SKIP_TO_NEXT = 32L; // 0x20L field public static final long ACTION_SKIP_TO_PREVIOUS = 16L; // 0x10L field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L field public static final long ACTION_STOP = 1L; // 0x1L field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR; field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL - field public static final int REPEAT_MODE_ALL = 2; // 0x2 - field public static final int REPEAT_MODE_NONE = 0; // 0x0 - field public static final int REPEAT_MODE_ONE = 1; // 0x1 field public static final int STATE_BUFFERING = 6; // 0x6 field public static final int STATE_CONNECTING = 8; // 0x8 field public static final int STATE_ERROR = 7; // 0x7 @@ -37360,7 +37328,6 @@ package android.service.media { method public abstract void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>); method public void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>, android.os.Bundle); method public void onLoadItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>); - method public void onSearch(java.lang.String, android.os.Bundle, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>); method public void setSessionToken(android.media.session.MediaSession.Token); field public static final java.lang.String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService"; } @@ -40938,7 +40905,6 @@ package android.test.mock { method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException; method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException; method public android.content.ComponentName startService(android.content.Intent); - method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification); method public boolean stopService(android.content.Intent); method public void unbindService(android.content.ServiceConnection); method public void unregisterReceiver(android.content.BroadcastReceiver); diff --git a/api/system-current.txt b/api/system-current.txt index 37bba95394a7..db3792be653b 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5806,7 +5806,6 @@ package android.app { method public boolean removeAutomaticZenRule(java.lang.String); method public final void setInterruptionFilter(int); method public void setNotificationPolicy(android.app.NotificationManager.Policy); - method public deprecated android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification); method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule); field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED"; field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED"; @@ -7326,7 +7325,7 @@ package android.app.job { } public abstract class JobServiceEngine { - ctor public JobServiceEngine(android.content.Context); + ctor public JobServiceEngine(android.app.Service); method public final android.os.IBinder getBinder(); method public final void jobFinished(android.app.job.JobParameters, boolean); method public abstract boolean onStartJob(android.app.job.JobParameters); @@ -25933,7 +25932,6 @@ package android.media.browse { method public android.content.ComponentName getServiceComponent(); method public android.media.session.MediaSession.Token getSessionToken(); method public boolean isConnected(); - method public void search(java.lang.String, android.os.Bundle, android.media.browse.MediaBrowser.SearchCallback); method public void subscribe(java.lang.String, android.media.browse.MediaBrowser.SubscriptionCallback); method public void subscribe(java.lang.String, android.os.Bundle, android.media.browse.MediaBrowser.SubscriptionCallback); method public void unsubscribe(java.lang.String); @@ -25969,12 +25967,6 @@ package android.media.browse { field public static final int FLAG_PLAYABLE = 2; // 0x2 } - public static abstract class MediaBrowser.SearchCallback { - ctor public MediaBrowser.SearchCallback(); - method public void onError(java.lang.String, android.os.Bundle); - method public void onSearchResult(java.lang.String, android.os.Bundle, java.util.List<android.media.browse.MediaBrowser.MediaItem>); - } - public static abstract class MediaBrowser.SubscriptionCallback { ctor public MediaBrowser.SubscriptionCallback(); method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>); @@ -26183,8 +26175,6 @@ package android.media.session { public final class MediaController { ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token); - method public void addQueueItem(android.media.MediaDescription); - method public void addQueueItem(android.media.MediaDescription, int); method public void adjustVolume(int, int); method public boolean dispatchMediaButtonEvent(android.view.KeyEvent); method public android.os.Bundle getExtras(); @@ -26196,15 +26186,11 @@ package android.media.session { method public java.util.List<android.media.session.MediaSession.QueueItem> getQueue(); method public java.lang.CharSequence getQueueTitle(); method public int getRatingType(); - method public int getRepeatMode(); method public android.app.PendingIntent getSessionActivity(); method public android.media.session.MediaSession.Token getSessionToken(); method public android.media.session.MediaController.TransportControls getTransportControls(); - method public boolean isShuffleModeEnabled(); method public void registerCallback(android.media.session.MediaController.Callback); method public void registerCallback(android.media.session.MediaController.Callback, android.os.Handler); - method public void removeQueueItem(android.media.MediaDescription); - method public void removeQueueItemAt(int); method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver); method public void setVolumeTo(int, int); method public void unregisterCallback(android.media.session.MediaController.Callback); @@ -26218,10 +26204,8 @@ package android.media.session { method public void onPlaybackStateChanged(android.media.session.PlaybackState); method public void onQueueChanged(java.util.List<android.media.session.MediaSession.QueueItem>); method public void onQueueTitleChanged(java.lang.CharSequence); - method public void onRepeatModeChanged(int); method public void onSessionDestroyed(); method public void onSessionEvent(java.lang.String, android.os.Bundle); - method public void onShuffleModeChanged(boolean); } public static final class MediaController.PlaybackInfo { @@ -26250,8 +26234,6 @@ package android.media.session { method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle); method public void sendCustomAction(java.lang.String, android.os.Bundle); method public void setRating(android.media.Rating); - method public void setRepeatMode(int); - method public void setShuffleModeEnabled(boolean); method public void skipToNext(); method public void skipToPrevious(); method public void skipToQueueItem(long); @@ -26278,18 +26260,13 @@ package android.media.session { method public void setQueue(java.util.List<android.media.session.MediaSession.QueueItem>); method public void setQueueTitle(java.lang.CharSequence); method public void setRatingType(int); - method public void setRepeatMode(int); method public void setSessionActivity(android.app.PendingIntent); - method public void setShuffleModeEnabled(boolean); field public static final deprecated int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1 - field public static final int FLAG_HANDLES_QUEUE_COMMANDS = 4; // 0x4 field public static final deprecated int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2 } public static abstract class MediaSession.Callback { ctor public MediaSession.Callback(); - method public void onAddQueueItem(android.media.MediaDescription); - method public void onAddQueueItem(android.media.MediaDescription, int); method public void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver); method public void onCustomAction(java.lang.String, android.os.Bundle); method public void onFastForward(); @@ -26303,13 +26280,9 @@ package android.media.session { method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle); method public void onPrepareFromSearch(java.lang.String, android.os.Bundle); method public void onPrepareFromUri(android.net.Uri, android.os.Bundle); - method public void onRemoveQueueItem(android.media.MediaDescription); - method public void onRemoveQueueItemAt(int); method public void onRewind(); method public void onSeekTo(long); method public void onSetRating(android.media.Rating); - method public void onSetRepeatMode(int); - method public void onSetShuffleModeEnabled(boolean); method public void onSkipToNext(); method public void onSkipToPrevious(); method public void onSkipToQueueItem(long); @@ -26380,17 +26353,12 @@ package android.media.session { field public static final long ACTION_REWIND = 8L; // 0x8L field public static final long ACTION_SEEK_TO = 256L; // 0x100L field public static final long ACTION_SET_RATING = 128L; // 0x80L - field public static final long ACTION_SET_REPEAT_MODE = 262144L; // 0x40000L - field public static final long ACTION_SET_SHUFFLE_MODE_ENABLED = 524288L; // 0x80000L field public static final long ACTION_SKIP_TO_NEXT = 32L; // 0x20L field public static final long ACTION_SKIP_TO_PREVIOUS = 16L; // 0x10L field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L field public static final long ACTION_STOP = 1L; // 0x1L field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR; field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL - field public static final int REPEAT_MODE_ALL = 2; // 0x2 - field public static final int REPEAT_MODE_NONE = 0; // 0x0 - field public static final int REPEAT_MODE_ONE = 1; // 0x1 field public static final int STATE_BUFFERING = 6; // 0x6 field public static final int STATE_CONNECTING = 8; // 0x8 field public static final int STATE_ERROR = 7; // 0x7 @@ -40472,7 +40440,6 @@ package android.service.media { method public abstract void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>); method public void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>, android.os.Bundle); method public void onLoadItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>); - method public void onSearch(java.lang.String, android.os.Bundle, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>); method public void setSessionToken(android.media.session.MediaSession.Token); field public static final java.lang.String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService"; } @@ -44494,7 +44461,6 @@ package android.test.mock { method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException; method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException; method public android.content.ComponentName startService(android.content.Intent); - method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification); method public boolean stopService(android.content.Intent); method public void unbindService(android.content.ServiceConnection); method public void unregisterReceiver(android.content.BroadcastReceiver); diff --git a/api/test-current.txt b/api/test-current.txt index 02b3db7e4074..f8a04d237d7c 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -5618,7 +5618,6 @@ package android.app { method public boolean removeAutomaticZenRule(java.lang.String); method public final void setInterruptionFilter(int); method public void setNotificationPolicy(android.app.NotificationManager.Policy); - method public deprecated android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification); method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule); field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED"; field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED"; @@ -6920,7 +6919,7 @@ package android.app.job { } public abstract class JobServiceEngine { - ctor public JobServiceEngine(android.content.Context); + ctor public JobServiceEngine(android.app.Service); method public final android.os.IBinder getBinder(); method public final void jobFinished(android.app.job.JobParameters, boolean); method public abstract boolean onStartJob(android.app.job.JobParameters); @@ -24118,7 +24117,6 @@ package android.media.browse { method public android.content.ComponentName getServiceComponent(); method public android.media.session.MediaSession.Token getSessionToken(); method public boolean isConnected(); - method public void search(java.lang.String, android.os.Bundle, android.media.browse.MediaBrowser.SearchCallback); method public void subscribe(java.lang.String, android.media.browse.MediaBrowser.SubscriptionCallback); method public void subscribe(java.lang.String, android.os.Bundle, android.media.browse.MediaBrowser.SubscriptionCallback); method public void unsubscribe(java.lang.String); @@ -24154,12 +24152,6 @@ package android.media.browse { field public static final int FLAG_PLAYABLE = 2; // 0x2 } - public static abstract class MediaBrowser.SearchCallback { - ctor public MediaBrowser.SearchCallback(); - method public void onError(java.lang.String, android.os.Bundle); - method public void onSearchResult(java.lang.String, android.os.Bundle, java.util.List<android.media.browse.MediaBrowser.MediaItem>); - } - public static abstract class MediaBrowser.SubscriptionCallback { ctor public MediaBrowser.SubscriptionCallback(); method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>); @@ -24368,8 +24360,6 @@ package android.media.session { public final class MediaController { ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token); - method public void addQueueItem(android.media.MediaDescription); - method public void addQueueItem(android.media.MediaDescription, int); method public void adjustVolume(int, int); method public boolean dispatchMediaButtonEvent(android.view.KeyEvent); method public android.os.Bundle getExtras(); @@ -24381,15 +24371,11 @@ package android.media.session { method public java.util.List<android.media.session.MediaSession.QueueItem> getQueue(); method public java.lang.CharSequence getQueueTitle(); method public int getRatingType(); - method public int getRepeatMode(); method public android.app.PendingIntent getSessionActivity(); method public android.media.session.MediaSession.Token getSessionToken(); method public android.media.session.MediaController.TransportControls getTransportControls(); - method public boolean isShuffleModeEnabled(); method public void registerCallback(android.media.session.MediaController.Callback); method public void registerCallback(android.media.session.MediaController.Callback, android.os.Handler); - method public void removeQueueItem(android.media.MediaDescription); - method public void removeQueueItemAt(int); method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver); method public void setVolumeTo(int, int); method public void unregisterCallback(android.media.session.MediaController.Callback); @@ -24403,10 +24389,8 @@ package android.media.session { method public void onPlaybackStateChanged(android.media.session.PlaybackState); method public void onQueueChanged(java.util.List<android.media.session.MediaSession.QueueItem>); method public void onQueueTitleChanged(java.lang.CharSequence); - method public void onRepeatModeChanged(int); method public void onSessionDestroyed(); method public void onSessionEvent(java.lang.String, android.os.Bundle); - method public void onShuffleModeChanged(boolean); } public static final class MediaController.PlaybackInfo { @@ -24435,8 +24419,6 @@ package android.media.session { method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle); method public void sendCustomAction(java.lang.String, android.os.Bundle); method public void setRating(android.media.Rating); - method public void setRepeatMode(int); - method public void setShuffleModeEnabled(boolean); method public void skipToNext(); method public void skipToPrevious(); method public void skipToQueueItem(long); @@ -24463,18 +24445,13 @@ package android.media.session { method public void setQueue(java.util.List<android.media.session.MediaSession.QueueItem>); method public void setQueueTitle(java.lang.CharSequence); method public void setRatingType(int); - method public void setRepeatMode(int); method public void setSessionActivity(android.app.PendingIntent); - method public void setShuffleModeEnabled(boolean); field public static final deprecated int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1 - field public static final int FLAG_HANDLES_QUEUE_COMMANDS = 4; // 0x4 field public static final deprecated int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2 } public static abstract class MediaSession.Callback { ctor public MediaSession.Callback(); - method public void onAddQueueItem(android.media.MediaDescription); - method public void onAddQueueItem(android.media.MediaDescription, int); method public void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver); method public void onCustomAction(java.lang.String, android.os.Bundle); method public void onFastForward(); @@ -24488,13 +24465,9 @@ package android.media.session { method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle); method public void onPrepareFromSearch(java.lang.String, android.os.Bundle); method public void onPrepareFromUri(android.net.Uri, android.os.Bundle); - method public void onRemoveQueueItem(android.media.MediaDescription); - method public void onRemoveQueueItemAt(int); method public void onRewind(); method public void onSeekTo(long); method public void onSetRating(android.media.Rating); - method public void onSetRepeatMode(int); - method public void onSetShuffleModeEnabled(boolean); method public void onSkipToNext(); method public void onSkipToPrevious(); method public void onSkipToQueueItem(long); @@ -24555,17 +24528,12 @@ package android.media.session { field public static final long ACTION_REWIND = 8L; // 0x8L field public static final long ACTION_SEEK_TO = 256L; // 0x100L field public static final long ACTION_SET_RATING = 128L; // 0x80L - field public static final long ACTION_SET_REPEAT_MODE = 262144L; // 0x40000L - field public static final long ACTION_SET_SHUFFLE_MODE_ENABLED = 524288L; // 0x80000L field public static final long ACTION_SKIP_TO_NEXT = 32L; // 0x20L field public static final long ACTION_SKIP_TO_PREVIOUS = 16L; // 0x10L field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L field public static final long ACTION_STOP = 1L; // 0x1L field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR; field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL - field public static final int REPEAT_MODE_ALL = 2; // 0x2 - field public static final int REPEAT_MODE_NONE = 0; // 0x0 - field public static final int REPEAT_MODE_ONE = 1; // 0x1 field public static final int STATE_BUFFERING = 6; // 0x6 field public static final int STATE_CONNECTING = 8; // 0x8 field public static final int STATE_ERROR = 7; // 0x7 @@ -37513,7 +37481,6 @@ package android.service.media { method public abstract void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>); method public void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>, android.os.Bundle); method public void onLoadItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>); - method public void onSearch(java.lang.String, android.os.Bundle, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>); method public void setSessionToken(android.media.session.MediaSession.Token); field public static final java.lang.String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService"; } @@ -41133,7 +41100,6 @@ package android.test.mock { method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException; method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException; method public android.content.ComponentName startService(android.content.Intent); - method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification); method public boolean stopService(android.content.Intent); method public void unbindService(android.content.ServiceConnection); method public void unregisterReceiver(android.content.BroadcastReceiver); diff --git a/cmds/media/src/com/android/commands/media/Media.java b/cmds/media/src/com/android/commands/media/Media.java index 4be46540e19b..9df229cbf490 100644 --- a/cmds/media/src/com/android/commands/media/Media.java +++ b/cmds/media/src/com/android/commands/media/Media.java @@ -228,16 +228,6 @@ public class Media extends BaseCommand { System.out.println("onVolumeInfoChanged " + info); } - @Override - public void onRepeatModeChanged(int repeatMode) throws RemoteException { - System.out.println("onRepeatModeChanged " + repeatMode); - } - - @Override - public void onShuffleModeChanged(boolean enabled) throws RemoteException { - System.out.println("onShuffleModeChanged " + enabled); - } - void printUsageMessage() { try { System.out.println("V2Monitoring session " + mController.getTag() diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 169dcb01c90a..c4b7ed771b70 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2070,6 +2070,7 @@ public class Activity extends ContextThemeWrapper if (args == null) { throw new IllegalArgumentException("Expected non-null picture-in-picture args"); } + updatePictureInPictureArgsForContentInsets(args); return ActivityManagerNative.getDefault().enterPictureInPictureMode(mToken, args); } catch (RemoteException e) { return false; @@ -2087,11 +2088,27 @@ public class Activity extends ContextThemeWrapper if (args == null) { throw new IllegalArgumentException("Expected non-null picture-in-picture args"); } + updatePictureInPictureArgsForContentInsets(args); ActivityManagerNative.getDefault().setPictureInPictureArgs(mToken, args); } catch (RemoteException e) { } } + /** + * Updates the provided {@param args} with the last known content insets for this activity, to + * be used with the source hint rect for the transition into PiP. + */ + private void updatePictureInPictureArgsForContentInsets(PictureInPictureArgs args) { + if (args != null && args.hasSourceBoundsHint() && getWindow() != null && + getWindow().peekDecorView() != null && + getWindow().peekDecorView().getViewRootImpl() != null) { + args.setSourceRectHintInsets( + getWindow().peekDecorView().getViewRootImpl().getLastContentInsets()); + } else { + args.setSourceRectHintInsets(null); + } + } + void dispatchMovedToDisplay(int displayId, Configuration config) { updateDisplay(displayId); onMovedToDisplay(displayId, config); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 6cc8a14ea2f9..80de64b94519 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1447,21 +1447,13 @@ class ContextImpl extends Context { @Override public ComponentName startService(Intent service) { warnIfCallingFromSystemProcess(); - return startServiceCommon(service, -1, null, false, mUser); + return startServiceCommon(service, false, mUser); } @Override public ComponentName startForegroundService(Intent service) { warnIfCallingFromSystemProcess(); - return startServiceCommon(service, -1, null, true, mUser); - } - - // STOPSHIP: remove when NotificationManager.startServiceInForeground() is retired - @Override - public ComponentName startServiceInForeground(Intent service, - int id, Notification notification) { - warnIfCallingFromSystemProcess(); - return startServiceCommon(service, id, notification, false, mUser); + return startServiceCommon(service, true, mUser); } @Override @@ -1472,29 +1464,22 @@ class ContextImpl extends Context { @Override public ComponentName startServiceAsUser(Intent service, UserHandle user) { - return startServiceCommon(service, -1, null, false, user); + return startServiceCommon(service, false, user); } @Override public ComponentName startForegroundServiceAsUser(Intent service, UserHandle user) { - return startServiceCommon(service, -1, null, true, user); + return startServiceCommon(service, true, user); } - // STOPSHIP: remove when NotificationManager.startServiceInForeground() is retired - @Override - public ComponentName startServiceInForegroundAsUser(Intent service, - int id, Notification notification, UserHandle user) { - return startServiceCommon(service, id, notification, false, user); - } - - private ComponentName startServiceCommon(Intent service, int id, Notification notification, - boolean requireForeground, UserHandle user) { + private ComponentName startServiceCommon(Intent service, boolean requireForeground, + UserHandle user) { try { validateServiceIntent(service); service.prepareToLeaveProcess(this); ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( - getContentResolver()), id, notification, requireForeground, + getContentResolver()), requireForeground, getOpPackageName(), user.getIdentifier()); if (cn != null) { if (cn.getPackageName().equals("!")) { diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 4210d2e7d3ec..d2702440f839 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -129,8 +129,7 @@ interface IActivityManager { void finishSubActivity(in IBinder token, in String resultWho, int requestCode); PendingIntent getRunningServiceControlPanel(in ComponentName service); ComponentName startService(in IApplicationThread caller, in Intent service, - in String resolvedType, int id, in Notification notification, - boolean requireForeground, in String callingPackage, int userId); + in String resolvedType, boolean requireForeground, in String callingPackage, int userId); int stopService(in IApplicationThread caller, in Intent service, in String resolvedType, int userId); int bindService(in IApplicationThread caller, in IBinder token, in Intent service, diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 8ed52a1bba59..cab2114f6918 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -4202,9 +4202,22 @@ public class Notification implements Parcelable * @hide */ public RemoteViews makePublicContentView() { + return makePublicView(false /* ambient */); + } + + /** + * Construct a RemoteViews for the display in public contexts like on the lockscreen. + * + * @hide + */ + public RemoteViews makePublicAmbientNotification() { + return makePublicView(true /* ambient */); + } + + private RemoteViews makePublicView(boolean ambient) { if (mN.publicVersion != null) { final Builder builder = recoverBuilder(mContext, mN.publicVersion); - return builder.createContentView(); + return ambient ? builder.makeAmbientNotification() : builder.createContentView(); } Bundle savedBundle = mN.extras; Style style = mStyle; @@ -4221,14 +4234,15 @@ public class Notification implements Parcelable publicExtras.putBoolean(EXTRA_CHRONOMETER_COUNT_DOWN, savedBundle.getBoolean(EXTRA_CHRONOMETER_COUNT_DOWN)); publicExtras.putCharSequence(EXTRA_TITLE, - mContext.getString(R.string.notification_hidden_text)); + mContext.getString(com.android.internal.R.string.notification_hidden_text)); mN.extras = publicExtras; - final RemoteViews publicView = applyStandardTemplate(getBaseLayoutResource()); + final RemoteViews view = ambient ? makeAmbientNotification() + : applyStandardTemplate(getBaseLayoutResource()); mN.extras = savedBundle; mN.mLargeIcon = largeIcon; mN.largeIcon = largeIconLegacy; mStyle = style; - return publicView; + return view; } /** diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 72c59781ae80..242d4a5e6267 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -1155,40 +1155,4 @@ public class NotificationManager } } - /** - * Start a service directly into the "foreground service" state. Unlike - * {@link android.content.Context#startService(Intent)}, this method - * can be used from within background operations like broadcast receivers - * or scheduled jobs. - * - * @param service Description of the service to be started. The Intent must be either - * fully explicit (supplying a component name) or specify a specific package - * name it is targeted to. - * @param id The identifier for this notification as per - * {@link #notify(int, Notification) NotificationManager.notify(int, Notification)}; - * must not be 0. - * @param notification The Notification to be displayed. - * @return If the service is being started or is already running, the - * {@link ComponentName} of the actual service that was started is - * returned; else if the service does not exist null is returned. - * - * @deprecated STOPSHIP transition away from this for O - */ - @Nullable - @Deprecated - public ComponentName startServiceInForeground(Intent service, - int id, Notification notification) { - return mContext.startServiceInForeground(service, id, notification); - } - - /** - * @hide like {@link #startServiceInForeground(Intent, int, Notification)} - * but for a specific user. - */ - @Nullable - public ComponentName startServiceInForegroundAsUser(Intent service, - int id, Notification notification, UserHandle user) { - return mContext.startServiceInForegroundAsUser(service, id, notification, user); - } - } diff --git a/core/java/android/app/PictureInPictureArgs.java b/core/java/android/app/PictureInPictureArgs.java index 0ce5eebed287..2fa636046901 100644 --- a/core/java/android/app/PictureInPictureArgs.java +++ b/core/java/android/app/PictureInPictureArgs.java @@ -49,6 +49,13 @@ public final class PictureInPictureArgs implements Parcelable { @Nullable private Rect mSourceRectHint; + /** + * The content insets that are used with the source hint rect for the transition into PiP where + * the insets are removed at the beginning of the transition. + */ + @Nullable + private Rect mSourceRectHintInsets; + PictureInPictureArgs(Parcel in) { if (in.readInt() != 0) { mAspectRatio = in.readFloat(); @@ -60,6 +67,9 @@ public final class PictureInPictureArgs implements Parcelable { if (in.readInt() != 0) { mSourceRectHint = Rect.CREATOR.createFromParcel(in); } + if (in.readInt() != 0) { + mSourceRectHintInsets = Rect.CREATOR.createFromParcel(in); + } } /** @@ -94,6 +104,9 @@ public final class PictureInPictureArgs implements Parcelable { if (otherArgs.hasSourceBoundsHint()) { mSourceRectHint = new Rect(otherArgs.getSourceRectHint()); } + if (otherArgs.hasSourceBoundsHintInsets()) { + mSourceRectHintInsets = new Rect(otherArgs.getSourceRectHintInsets()); + } } /** @@ -167,7 +180,19 @@ public final class PictureInPictureArgs implements Parcelable { } /** - * @return the launch bounds + * Sets the insets to be used with the source rect hint bounds. + * @hide + */ + public void setSourceRectHintInsets(Rect insets) { + if (insets == null) { + mSourceRectHintInsets = null; + } else { + mSourceRectHintInsets = new Rect(insets); + } + } + + /** + * @return the source rect hint * @hide */ public Rect getSourceRectHint() { @@ -175,6 +200,14 @@ public final class PictureInPictureArgs implements Parcelable { } /** + * @return the source rect hint insets. + * @hide + */ + public Rect getSourceRectHintInsets() { + return mSourceRectHintInsets; + } + + /** * @return whether there are launch bounds set * @hide */ @@ -182,12 +215,23 @@ public final class PictureInPictureArgs implements Parcelable { return mSourceRectHint != null && !mSourceRectHint.isEmpty(); } + /** + * @return whether there are source rect hint insets set + * @hide + */ + public boolean hasSourceBoundsHintInsets() { + return mSourceRectHintInsets != null; + } + @Override public PictureInPictureArgs clone() { PictureInPictureArgs args = new PictureInPictureArgs(mAspectRatio, mUserActions); if (mSourceRectHint != null) { args.setSourceRectHint(mSourceRectHint); } + if (mSourceRectHintInsets != null) { + args.setSourceRectHintInsets(mSourceRectHintInsets); + } return args; } @@ -216,6 +260,12 @@ public final class PictureInPictureArgs implements Parcelable { } else { out.writeInt(0); } + if (mSourceRectHintInsets != null) { + out.writeInt(1); + mSourceRectHintInsets.writeToParcel(out, 0); + } else { + out.writeInt(0); + } } public static final Creator<PictureInPictureArgs> CREATOR = diff --git a/core/java/android/app/job/JobParameters.java b/core/java/android/app/job/JobParameters.java index 016a0fa8b92b..673d1b886b25 100644 --- a/core/java/android/app/job/JobParameters.java +++ b/core/java/android/app/job/JobParameters.java @@ -164,6 +164,20 @@ public class JobParameters implements Parcelable { * you should not call {@link JobService#jobFinished(JobParameters, boolean)} yourself * (otherwise you risk losing an upcoming JobWorkItem that is being enqueued at the same time). * + * <p>Once you are done with the {@link JobWorkItem} returned by this method, you must call + * {@link #completeWork(JobWorkItem)} with it to inform the system that you are done + * executing the work. The job will not be finished until all dequeued work has been + * completed. You do not, however, have to complete each returned work item before deqeueing + * the next one -- you can use {@link #dequeueWork()} multiple times before completing + * previous work if you want to process work in parallel, and you can complete the work + * in whatever order you want.</p> + * + * <p>If the job runs to the end of its available time period before all work has been + * completed, it will stop as normal. You should return true from + * {@link JobService#onStopJob(JobParameters)} in order to have the job rescheduled, and by + * doing so any pending as well as remaining uncompleted work will be re-queued + * for the next time the job runs.</p> + * * @return Returns a new {@link JobWorkItem} if there is one pending, otherwise null. * If null is returned, the system will also stop the job if all work has also been completed. * (This means that for correct operation, you must always call dequeueWork() after you have diff --git a/core/java/android/app/job/JobServiceEngine.java b/core/java/android/app/job/JobServiceEngine.java index 879212ea1fb3..a62861902a55 100644 --- a/core/java/android/app/job/JobServiceEngine.java +++ b/core/java/android/app/job/JobServiceEngine.java @@ -54,7 +54,7 @@ public abstract class JobServiceEngine { /** * Context we are running in. */ - private final Context mContext; + private final Service mService; private final IJobService mBinder; @@ -182,12 +182,12 @@ public abstract class JobServiceEngine { /** * Create a new engine, ready for use. * - * @param context The {@link Service} that is creating this engine. + * @param service The {@link Service} that is creating this engine and in which it will run. */ - public JobServiceEngine(Context context) { - mContext = context; + public JobServiceEngine(Service service) { + mService = service; mBinder = new JobInterface(this); - mHandler = new JobHandler(mContext.getMainLooper()); + mHandler = new JobHandler(mService.getMainLooper()); } /** diff --git a/core/java/android/app/job/JobWorkItem.java b/core/java/android/app/job/JobWorkItem.java index 4bb057e689b2..05687ee9aace 100644 --- a/core/java/android/app/job/JobWorkItem.java +++ b/core/java/android/app/job/JobWorkItem.java @@ -27,6 +27,7 @@ import android.os.Parcelable; final public class JobWorkItem implements Parcelable { final Intent mIntent; int mWorkId; + Object mGrants; /** * Create a new piece of work. @@ -57,6 +58,20 @@ final public class JobWorkItem implements Parcelable { return mWorkId; } + /** + * @hide + */ + public void setGrants(Object grants) { + mGrants = grants; + } + + /** + * @hide + */ + public Object getGrants() { + return mGrants; + } + public String toString() { return "JobWorkItem{id=" + mWorkId + " intent=" + mIntent + "}"; } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 18120c714793..0adab1ad1752 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2647,18 +2647,6 @@ public abstract class Context { public abstract ComponentName startForegroundServiceAsUser(Intent service, UserHandle user); /** - * Start a service directly into the "foreground service" state. Unlike {@link #startService}, - * this method can be used from within background operations like broadcast receivers - * or scheduled jobs. The API entry point for this is in NotificationManager in order to - * preserve appropriate public package layering. - * @hide - * @deprecated STOPSHIP remove in favor of two-step startForegroundService() + startForeground() - */ - @Nullable - public abstract ComponentName startServiceInForeground(Intent service, - int id, Notification notification); - - /** * Request that a given application service be stopped. If the service is * not running, nothing happens. Otherwise it is stopped. Note that calls * to startService() are not counted -- this stops the service no matter @@ -2696,16 +2684,6 @@ public abstract class Context { public abstract ComponentName startServiceAsUser(Intent service, UserHandle user); /** - * @hide like {@link #startServiceInForeground(Intent, int, Notification)} - * but for a specific user. - * @deprecated STOPSHIP remove when trial API is turned off - */ - @Deprecated - @Nullable - public abstract ComponentName startServiceInForegroundAsUser(Intent service, - int id, Notification notification, UserHandle user); - - /** * @hide like {@link #stopService(Intent)} but for a specific user. */ public abstract boolean stopServiceAsUser(Intent service, UserHandle user); diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 53b021cbdf9f..b59fc3ddbb84 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -649,13 +649,6 @@ public class ContextWrapper extends Context { return mBase.startForegroundService(service); } - /** @hide STOPSHIP remove when trial API is turned down */ - @Override - public ComponentName startServiceInForeground(Intent service, - int id, Notification notification) { - return mBase.startServiceInForeground(service, id, notification); - } - @Override public boolean stopService(Intent name) { return mBase.stopService(name); @@ -673,13 +666,6 @@ public class ContextWrapper extends Context { return mBase.startForegroundServiceAsUser(service, user); } - /** @hide STOPSHIP removed when trial API is turned down */ - @Override - public ComponentName startServiceInForegroundAsUser(Intent service, - int id, Notification notification, UserHandle user) { - return mBase.startServiceInForegroundAsUser(service, id, notification, user); - } - /** @hide */ @Override public boolean stopServiceAsUser(Intent name, UserHandle user) { diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index 23e54baab622..d64f018c3f2e 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -1787,7 +1787,7 @@ public class IntentFilter implements Parcelable { sb.append(", mHasPartialTypes="); sb.append(mHasPartialTypes); du.println(sb.toString()); } - { + if (getAutoVerify()) { sb.setLength(0); sb.append(prefix); sb.append("AutoVerify="); sb.append(getAutoVerify()); du.println(sb.toString()); diff --git a/core/java/android/view/IPinnedStackController.aidl b/core/java/android/view/IPinnedStackController.aidl index 2fe98c0b6f05..dbeb747adfba 100644 --- a/core/java/android/view/IPinnedStackController.aidl +++ b/core/java/android/view/IPinnedStackController.aidl @@ -28,4 +28,9 @@ interface IPinnedStackController { * Notifies the controller that the PiP is currently minimized. */ oneway void setIsMinimized(boolean isMinimized); + + /** + * @return what WM considers to be the current device rotation. + */ + int getDisplayRotation(); } diff --git a/core/java/android/view/IPinnedStackListener.aidl b/core/java/android/view/IPinnedStackListener.aidl index 782f3499fb79..9382741a81ec 100644 --- a/core/java/android/view/IPinnedStackListener.aidl +++ b/core/java/android/view/IPinnedStackListener.aidl @@ -41,9 +41,13 @@ oneway interface IPinnedStackListener { * current state with the aspect ratio applied. The {@param animatingBounds} are provided * to indicate the current target bounds of the pinned stack (the final bounds if animating, * the current bounds if not), which may be helpful in calculating dependent animation bounds. + * + * The {@param displayRotation} is provided so that the client can verify when making certain + * calls that it will not provide stale information based on an old display rotation (ie. if + * the WM has changed in the mean time but the client has not received onMovementBoundsChanged). */ void onMovementBoundsChanged(in Rect insetBounds, in Rect normalBounds, in Rect animatingBounds, - boolean fromImeAdjustement); + boolean fromImeAdjustement, int displayRotation); /** * Called when window manager decides to adjust the pinned stack bounds because of the IME, or diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index a7ececf6c782..080ffeb011f8 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1561,6 +1561,16 @@ public final class ViewRootImpl implements ViewParent, host.dispatchApplyWindowInsets(getWindowInsets(true /* forceConstruct */)); } + /** + * @return the last content insets for use in adjusting the source hint rect for the + * picture-in-picture transition. + * + * @hide + */ + public Rect getLastContentInsets() { + return mAttachInfo.mContentInsets; + } + private static boolean shouldUseDisplaySize(final WindowManager.LayoutParams lp) { return lp.type == TYPE_STATUS_BAR_PANEL || lp.type == TYPE_INPUT_METHOD diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java index 6dbc09ceef97..bf0e10f993ad 100644 --- a/core/java/android/view/WindowManagerInternal.java +++ b/core/java/android/view/WindowManagerInternal.java @@ -303,13 +303,16 @@ public abstract class WindowManagerInternal { * hidden, no matter how WindowManagerService will react / has reacted * to corresponding API calls. Note that this state is not guaranteed * to be synchronized with state in WindowManagerService. + * @param dismissImeOnBackKeyPressed {@code true} if the software keyboard is shown and the back + * key is expected to dismiss the software keyboard. * @param targetWindowToken token to identify the target window that the IME is associated with. * {@code null} when application, system, or the IME itself decided to * change its window visibility before being associated with any target * window. */ public abstract void updateInputMethodWindowStatus(@NonNull IBinder imeToken, - boolean imeWindowVisible, @Nullable IBinder targetWindowToken); + boolean imeWindowVisible, boolean dismissImeOnBackKeyPressed, + @Nullable IBinder targetWindowToken); /** * Returns true when the hardware keyboard is available. diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index bb6e0eed57cc..030c78b7f4b6 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -1537,6 +1537,18 @@ public interface WindowManagerPolicy { public void setLastInputMethodWindowLw(WindowState ime, WindowState target); /** + * An internal callback (from InputMethodManagerService) to notify a state change regarding + * whether the back key should dismiss the software keyboard (IME) or not. + * + * @param newValue {@code true} if the software keyboard is shown and the back key is expected + * to dismiss the software keyboard. + * @hide + */ + default void setDismissImeOnBackKeyPressed(boolean newValue) { + // Default implementation does nothing. + } + + /** * Show the recents task list app. * @hide */ diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index baf6db93daaf..80b6b0848a0b 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -82,6 +82,7 @@ import android.widget.PopupWindow; import static android.app.ActivityManager.StackId; import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; +import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; @@ -2182,19 +2183,22 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind final boolean wasAdjustedForStack = mElevationAdjustedForStack; // Do not use a shadow when we are in resizing mode (mBackdropFrameRenderer not null) // since the shadow is bound to the content size and not the target size. - if (StackId.hasWindowShadow(mStackId) && !isResizing()) { + if ((mStackId == FREEFORM_WORKSPACE_STACK_ID) && !isResizing()) { elevation = hasWindowFocus() ? DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP; // Add a maximum shadow height value to the top level view. // Note that pinned stack doesn't have focus // so maximum shadow height adjustment isn't needed. // TODO(skuhne): Remove this if clause once b/22668382 got fixed. - if (!mAllowUpdateElevation && mStackId != PINNED_STACK_ID) { + if (!mAllowUpdateElevation) { elevation = DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP; } // Convert the DP elevation into physical pixels. elevation = dipToPx(elevation); mElevationAdjustedForStack = true; + } else if (mStackId == PINNED_STACK_ID) { + elevation = dipToPx(DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP); + mElevationAdjustedForStack = true; } else { mElevationAdjustedForStack = false; } diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 45dccb6bfe33..6a31e161842b 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -852,6 +852,8 @@ 1 - Go to sleep (doze) 2 - Really go to sleep (don't doze) 3 - Really go to sleep and go home (don't doze) + 4 - Go to home + 5 - Dismiss IME if shown. Otherwise go to home --> <integer name="config_shortPressOnPowerBehavior">1</integer> diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java index 5bf205e12799..789d5e0d8478 100644 --- a/media/java/android/media/browse/MediaBrowser.java +++ b/media/java/android/media/browse/MediaBrowser.java @@ -365,7 +365,7 @@ public final class MediaBrowser { * @param parentId The id of the parent media item whose list of children * will be subscribed. * @param options The bundle of service-specific arguments to send to the media - * browse service. The contents of this bundle may affect the + * browser service. The contents of this bundle may affect the * information returned when browsing. * @param callback The callback to receive the list of children. */ @@ -453,7 +453,7 @@ public final class MediaBrowser { try { mServiceBinder.getMediaItem(mediaId, receiver, mServiceCallbacks); } catch (RemoteException e) { - Log.i(TAG, "Remote error getting media item.", e); + Log.i(TAG, "Remote error getting media item."); mHandler.post(new Runnable() { @Override public void run() { @@ -463,62 +463,6 @@ public final class MediaBrowser { } } - /** - * Searches {@link MediaItem media items} from the connected service. Not - * all services may support this, and {@link SearchCallback#onError} will be - * called if not implemented. - * - * @param query The search query that contains keywords separated by space. Should not be - * an empty string. - * @param extras The bundle of service-specific arguments to send to the media browser - * service. The contents of this bundle may affect the search result. - * @param callback The callback to receive the search result. - * @throws IllegalStateException if the browser is not connected to the media browser service. - */ - public void search(@NonNull final String query, final Bundle extras, SearchCallback callback) { - if (TextUtils.isEmpty(query)) { - throw new IllegalArgumentException("query cannot be empty."); - } - if (callback == null) { - throw new IllegalArgumentException("callback cannot be null."); - } - if (mState != CONNECT_STATE_CONNECTED) { - throw new IllegalStateException("search() called while not connected (state=" - + getStateLabel(mState) + ")"); - } - ResultReceiver receiver = new ResultReceiver(mHandler) { - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - if (resultCode != 0 || resultData == null - || !resultData.containsKey(MediaBrowserService.KEY_SEARCH_RESULTS)) { - callback.onError(query, extras); - return; - } - Parcelable[] items = resultData.getParcelableArray( - MediaBrowserService.KEY_SEARCH_RESULTS); - List<MediaItem> results = null; - if (items != null) { - results = new ArrayList<>(); - for (Parcelable item : items) { - results.add((MediaItem) item); - } - } - callback.onSearchResult(query, extras, results); - } - }; - try { - mServiceBinder.search(query, extras, receiver, mServiceCallbacks); - } catch (RemoteException e) { - Log.i(TAG, "Remote error getting media item.", e); - mHandler.post(new Runnable() { - @Override - public void run() { - callback.onError(query, extras); - } - }); - } - } - private void subscribeInternal(String parentId, Bundle options, SubscriptionCallback callback) { // Check arguments. if (TextUtils.isEmpty(parentId)) { @@ -945,7 +889,7 @@ public final class MediaBrowser { * @param parentId The media id of the parent media item. * @param children The children which were loaded. * @param options The bundle of service-specific arguments sent to the media - * browse service. The contents of this bundle may affect the + * browser service. The contents of this bundle may affect the * information returned when browsing. */ public void onChildrenLoaded(@NonNull String parentId, @NonNull List<MediaItem> children, @@ -1004,32 +948,6 @@ public final class MediaBrowser { } /** - * Callback for receiving the result of {@link #search}. - */ - public static abstract class SearchCallback { - /** - * Called when the {@link #search} finished successfully. - * - * @param query The search query sent for the search request to the connected service. - * @param extras The bundle of service-specific arguments sent to the connected service. - * @param items The list of media items which contains the search result. - */ - public void onSearchResult(@NonNull String query, Bundle extras, - @NonNull List<MediaItem> items) { - } - - /** - * Called when an error happens while {@link #search} or the connected service doesn't - * support {@link #search}. - * - * @param query The search query sent for the search request to the connected service. - * @param extras The bundle of service-specific arguments sent to the connected service. - */ - public void onError(@NonNull String query, Bundle extras) { - } - } - - /** * ServiceConnection to the other app. */ private class MediaServiceConnection implements ServiceConnection { diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl index 4f3314c1e8ab..3affee5c0aa7 100644 --- a/media/java/android/media/session/ISession.aidl +++ b/media/java/android/media/session/ISession.aidl @@ -45,8 +45,6 @@ interface ISession { void setQueueTitle(CharSequence title); void setExtras(in Bundle extras); void setRatingType(int type); - void setRepeatMode(int repeatMode); - void setShuffleModeEnabled(boolean enabled); // These commands relate to volume handling void setPlaybackToLocal(in AudioAttributes attributes); diff --git a/media/java/android/media/session/ISessionCallback.aidl b/media/java/android/media/session/ISessionCallback.aidl index a146c6226171..893bd3c8cbb1 100644 --- a/media/java/android/media/session/ISessionCallback.aidl +++ b/media/java/android/media/session/ISessionCallback.aidl @@ -16,7 +16,6 @@ package android.media.session; import android.content.Intent; -import android.media.MediaDescription; import android.media.Rating; import android.net.Uri; import android.os.Bundle; @@ -47,13 +46,7 @@ oneway interface ISessionCallback { void onRewind(); void onSeekTo(long pos); void onRate(in Rating rating); - void onRepeatMode(int repeatMode); - void onShuffleMode(boolean enabled); void onCustomAction(String action, in Bundle args); - void onAddQueueItem(in MediaDescription description); - void onAddQueueItemAt(in MediaDescription description, int index); - void onRemoveQueueItem(in MediaDescription description); - void onRemoveQueueItemAt(int index); // These callbacks are for volume handling void onAdjustVolume(int direction); diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl index 7b5233ac0704..249bcdc802ce 100644 --- a/media/java/android/media/session/ISessionController.aidl +++ b/media/java/android/media/session/ISessionController.aidl @@ -18,7 +18,6 @@ package android.media.session; import android.app.PendingIntent; import android.content.Intent; import android.content.pm.ParceledListSlice; -import android.media.MediaDescription; import android.media.MediaMetadata; import android.media.Rating; import android.media.session.ISessionControllerCallback; @@ -49,19 +48,6 @@ interface ISessionController { ParcelableVolumeInfo getVolumeAttributes(); void adjustVolume(int direction, int flags, String packageName); void setVolumeTo(int value, int flags, String packageName); - MediaMetadata getMetadata(); - PlaybackState getPlaybackState(); - ParceledListSlice getQueue(); - void addQueueItem(in MediaDescription description); - void addQueueItemAt(in MediaDescription description, int index); - void removeQueueItem(in MediaDescription description); - void removeQueueItemAt(int index); - - CharSequence getQueueTitle(); - Bundle getExtras(); - int getRatingType(); - int getRepeatMode(); - boolean isShuffleModeEnabled(); // These commands are for the TransportControls void prepare(); @@ -81,7 +67,11 @@ interface ISessionController { void rewind(); void seekTo(long pos); void rate(in Rating rating); - void repeatMode(int repeatMode); - void shuffleMode(boolean enabled); void sendCustomAction(String action, in Bundle args); + MediaMetadata getMetadata(); + PlaybackState getPlaybackState(); + ParceledListSlice getQueue(); + CharSequence getQueueTitle(); + Bundle getExtras(); + int getRatingType(); } diff --git a/media/java/android/media/session/ISessionControllerCallback.aidl b/media/java/android/media/session/ISessionControllerCallback.aidl index 9517c088bcf3..cf3176706d7e 100644 --- a/media/java/android/media/session/ISessionControllerCallback.aidl +++ b/media/java/android/media/session/ISessionControllerCallback.aidl @@ -36,6 +36,4 @@ oneway interface ISessionControllerCallback { void onQueueTitleChanged(CharSequence title); void onExtrasChanged(in Bundle extras); void onVolumeInfoChanged(in ParcelableVolumeInfo info); - void onRepeatModeChanged(int repeatMode); - void onShuffleModeChanged(boolean shuffleMode); } diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java index bab2af25dde5..622900f5c7f9 100644 --- a/media/java/android/media/session/MediaController.java +++ b/media/java/android/media/session/MediaController.java @@ -23,7 +23,6 @@ import android.content.Context; import android.content.pm.ParceledListSlice; import android.media.AudioAttributes; import android.media.AudioManager; -import android.media.MediaDescription; import android.media.MediaMetadata; import android.media.Rating; import android.media.VolumeProvider; @@ -39,7 +38,6 @@ import android.util.Log; import android.view.KeyEvent; import java.lang.ref.WeakReference; -import java.lang.UnsupportedOperationException; import java.util.ArrayList; import java.util.List; @@ -65,9 +63,7 @@ public final class MediaController { private static final int MSG_UPDATE_QUEUE = 5; private static final int MSG_UPDATE_QUEUE_TITLE = 6; private static final int MSG_UPDATE_EXTRAS = 7; - private static final int MSG_UPDATE_REPEAT_MODE = 8; - private static final int MSG_UPDATE_SHUFFLE_MODE = 9; - private static final int MSG_DESTROYED = 10; + private static final int MSG_DESTROYED = 8; private final ISessionController mSessionBinder; @@ -113,7 +109,8 @@ public final class MediaController { } /** - * Get a {@link TransportControls} instance to send transport actions to this session. + * Get a {@link TransportControls} instance to send transport actions to + * the associated session. * * @return A transport controls instance. */ @@ -152,7 +149,7 @@ public final class MediaController { try { return mSessionBinder.getPlaybackState(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getPlaybackState", e); + Log.wtf(TAG, "Error calling getPlaybackState.", e); return null; } } @@ -166,7 +163,7 @@ public final class MediaController { try { return mSessionBinder.getMetadata(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getMetadata", e); + Log.wtf(TAG, "Error calling getMetadata.", e); return null; } } @@ -184,103 +181,12 @@ public final class MediaController { return queue.getList(); } } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getQueue", e); + Log.wtf(TAG, "Error calling getQueue.", e); } return null; } /** - * Add a queue item from the given {@code description} at the end of the play queue - * of this session. Not all sessions may support this. - * - * @param description The {@link MediaDescription} for creating the - * {@link MediaSession.QueueItem} to be inserted. - * @throws UnsupportedOperationException If this session doesn't support this. - * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS - */ - public void addQueueItem(MediaDescription description) { - try { - long flags = mSessionBinder.getFlags(); - if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) { - throw new UnsupportedOperationException( - "This session doesn't support queue management operations"); - } - mSessionBinder.addQueueItem(description); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling addQueueItem", e); - } - } - - /** - * Add a queue item from the given {@code description} at the specified position - * in the play queue of this session. Shifts the queue item currently at that position - * (if any) and any subsequent queue items to the right (adds one to their indices). - * Not all sessions may support this. - * - * @param description The {@link MediaDescription} for creating the - * {@link MediaSession.QueueItem} to be inserted. - * @param index The index at which the created {@link MediaSession.QueueItem} is to be inserted. - * @throws UnsupportedOperationException If this session doesn't support this. - * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS - */ - public void addQueueItem(MediaDescription description, int index) { - try { - long flags = mSessionBinder.getFlags(); - if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) { - throw new UnsupportedOperationException( - "This session doesn't support queue management operations"); - } - mSessionBinder.addQueueItemAt(description, index); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling addQueueItemAt", e); - } - } - - /** - * Remove the first occurrence of the specified {@link MediaSession.QueueItem} - * with the given {@link MediaDescription description} in the play queue of the associated - * session. Not all sessions may support this. - * - * @param description The {@link MediaDescription} for denoting the - * {@link MediaSession.QueueItem} to be removed. - * @throws UnsupportedOperationException If this session doesn't support this. - * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS - */ - public void removeQueueItem(MediaDescription description) { - try { - long flags = mSessionBinder.getFlags(); - if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) { - throw new UnsupportedOperationException( - "This session doesn't support queue management operations"); - } - mSessionBinder.removeQueueItem(description); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling removeQueueItem", e); - } - } - - /** - * Remove an queue item at the specified position in the play queue - * of this session. Not all sessions may support this. - * - * @param index The index of the element to be removed. - * @throws UnsupportedOperationException If this session doesn't support this. - * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS - */ - public void removeQueueItemAt(int index) { - try { - long flags = mSessionBinder.getFlags(); - if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) { - throw new UnsupportedOperationException( - "This session doesn't support queue management operations"); - } - mSessionBinder.removeQueueItemAt(index); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling removeQueueItemAt", e); - } - } - - /** * Get the queue title for this session. */ public @Nullable CharSequence getQueueTitle() { @@ -322,41 +228,12 @@ public final class MediaController { try { return mSessionBinder.getRatingType(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getRatingType", e); + Log.wtf(TAG, "Error calling getRatingType.", e); return Rating.RATING_NONE; } } /** - * Get the repeat mode for this session. - * - * @return The latest repeat mode set to the session, or - * {@link PlaybackState#REPEAT_MODE_NONE} if not set. - */ - public int getRepeatMode() { - try { - return mSessionBinder.getRepeatMode(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getRepeatMode", e); - return PlaybackState.REPEAT_MODE_NONE; - } - } - - /** - * Return whether the shuffle mode is enabled for this session. - * - * @return {@code true} if the shuffle mode is enabled, {@code false} if disabled or not set. - */ - public boolean isShuffleModeEnabled() { - try { - return mSessionBinder.isShuffleModeEnabled(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling isShuffleModeEnabled", e); - return false; - } - } - - /** * Get the flags for this session. Flags are defined in {@link MediaSession}. * * @return The current set of flags for the session. @@ -365,7 +242,7 @@ public final class MediaController { try { return mSessionBinder.getFlags(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getFlags", e); + Log.wtf(TAG, "Error calling getFlags.", e); } return 0; } @@ -382,7 +259,7 @@ public final class MediaController { result.maxVolume, result.currentVolume); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getAudioInfo", e); + Log.wtf(TAG, "Error calling getAudioInfo.", e); } return null; } @@ -397,7 +274,7 @@ public final class MediaController { try { return mSessionBinder.getLaunchPendingIntent(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getPendingIntent", e); + Log.wtf(TAG, "Error calling getPendingIntent.", e); } return null; } @@ -426,7 +303,7 @@ public final class MediaController { try { mSessionBinder.setVolumeTo(value, flags, mContext.getPackageName()); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling setVolumeTo", e); + Log.wtf(TAG, "Error calling setVolumeTo.", e); } } @@ -447,7 +324,7 @@ public final class MediaController { try { mSessionBinder.adjustVolume(direction, flags, mContext.getPackageName()); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling adjustVolumeBy", e); + Log.wtf(TAG, "Error calling adjustVolumeBy.", e); } } @@ -513,7 +390,7 @@ public final class MediaController { try { mSessionBinder.sendCommand(command, args, cb); } catch (RemoteException e) { - Log.d(TAG, "Dead object in sendCommand", e); + Log.d(TAG, "Dead object in sendCommand.", e); } } @@ -527,7 +404,7 @@ public final class MediaController { try { mPackageName = mSessionBinder.getPackageName(); } catch (RemoteException e) { - Log.d(TAG, "Dead object in getPackageName", e); + Log.d(TAG, "Dead object in getPackageName.", e); } } return mPackageName; @@ -544,7 +421,7 @@ public final class MediaController { try { mTag = mSessionBinder.getTag(); } catch (RemoteException e) { - Log.d(TAG, "Dead object in getTag", e); + Log.d(TAG, "Dead object in getTag.", e); } } return mTag; @@ -702,25 +579,6 @@ public final class MediaController { */ public void onAudioInfoChanged(PlaybackInfo info) { } - - /** - * Override to handle changes to the repeat mode. - * - * @param repeatMode The repeat mode. It should be one of followings: - * {@link PlaybackState#REPEAT_MODE_NONE}, - * {@link PlaybackState#REPEAT_MODE_ONE}, - * {@link PlaybackState#REPEAT_MODE_ALL} - */ - public void onRepeatModeChanged(@PlaybackState.RepeatMode int repeatMode) { - } - - /** - * Override to handle changes to the shuffle mode. - * - * @param enabled {@code true} if the shuffle mode is enabled, {@code false} otherwise. - */ - public void onShuffleModeChanged(boolean enabled) { - } } /** @@ -744,7 +602,7 @@ public final class MediaController { try { mSessionBinder.prepare(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling prepare", e); + Log.wtf(TAG, "Error calling prepare.", e); } } @@ -763,12 +621,12 @@ public final class MediaController { public void prepareFromMediaId(String mediaId, Bundle extras) { if (TextUtils.isEmpty(mediaId)) { throw new IllegalArgumentException( - "You must specify a non-empty String for prepareFromMediaId"); + "You must specify a non-empty String for prepareFromMediaId."); } try { mSessionBinder.prepareFromMediaId(mediaId, extras); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling prepare(" + mediaId + ")", e); + Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e); } } @@ -794,7 +652,7 @@ public final class MediaController { try { mSessionBinder.prepareFromSearch(query, extras); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling prepare(" + query + ")", e); + Log.wtf(TAG, "Error calling prepare(" + query + ").", e); } } @@ -813,12 +671,12 @@ public final class MediaController { public void prepareFromUri(Uri uri, Bundle extras) { if (uri == null || Uri.EMPTY.equals(uri)) { throw new IllegalArgumentException( - "You must specify a non-empty Uri for prepareFromUri"); + "You must specify a non-empty Uri for prepareFromUri."); } try { mSessionBinder.prepareFromUri(uri, extras); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling prepare(" + uri + ")", e); + Log.wtf(TAG, "Error calling prepare(" + uri + ").", e); } } @@ -829,7 +687,7 @@ public final class MediaController { try { mSessionBinder.play(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling play", e); + Log.wtf(TAG, "Error calling play.", e); } } @@ -843,12 +701,12 @@ public final class MediaController { public void playFromMediaId(String mediaId, Bundle extras) { if (TextUtils.isEmpty(mediaId)) { throw new IllegalArgumentException( - "You must specify a non-empty String for playFromMediaId"); + "You must specify a non-empty String for playFromMediaId."); } try { mSessionBinder.playFromMediaId(mediaId, extras); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling play(" + mediaId + ")", e); + Log.wtf(TAG, "Error calling play(" + mediaId + ").", e); } } @@ -870,7 +728,7 @@ public final class MediaController { try { mSessionBinder.playFromSearch(query, extras); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling play(" + query + ")", e); + Log.wtf(TAG, "Error calling play(" + query + ").", e); } } @@ -884,12 +742,12 @@ public final class MediaController { public void playFromUri(Uri uri, Bundle extras) { if (uri == null || Uri.EMPTY.equals(uri)) { throw new IllegalArgumentException( - "You must specify a non-empty Uri for playFromUri"); + "You must specify a non-empty Uri for playFromUri."); } try { mSessionBinder.playFromUri(uri, extras); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling play(" + uri + ")", e); + Log.wtf(TAG, "Error calling play(" + uri + ").", e); } } @@ -901,7 +759,7 @@ public final class MediaController { try { mSessionBinder.skipToQueueItem(id); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling skipToItem(" + id + ")", e); + Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e); } } @@ -913,7 +771,7 @@ public final class MediaController { try { mSessionBinder.pause(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling pause", e); + Log.wtf(TAG, "Error calling pause.", e); } } @@ -925,7 +783,7 @@ public final class MediaController { try { mSessionBinder.stop(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling stop", e); + Log.wtf(TAG, "Error calling stop.", e); } } @@ -938,7 +796,7 @@ public final class MediaController { try { mSessionBinder.seekTo(pos); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling seekTo", e); + Log.wtf(TAG, "Error calling seekTo.", e); } } @@ -950,7 +808,7 @@ public final class MediaController { try { mSessionBinder.fastForward(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling fastForward", e); + Log.wtf(TAG, "Error calling fastForward.", e); } } @@ -961,7 +819,7 @@ public final class MediaController { try { mSessionBinder.next(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling next", e); + Log.wtf(TAG, "Error calling next.", e); } } @@ -973,7 +831,7 @@ public final class MediaController { try { mSessionBinder.rewind(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling rewind", e); + Log.wtf(TAG, "Error calling rewind.", e); } } @@ -984,7 +842,7 @@ public final class MediaController { try { mSessionBinder.previous(); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling previous", e); + Log.wtf(TAG, "Error calling previous.", e); } } @@ -999,36 +857,7 @@ public final class MediaController { try { mSessionBinder.rate(rating); } catch (RemoteException e) { - Log.wtf(TAG, "Error calling rate", e); - } - } - - /** - * Set the repeat mode for this session. - * - * @param repeatMode The repeat mode. Must be one of the followings: - * {@link PlaybackState#REPEAT_MODE_NONE}, - * {@link PlaybackState#REPEAT_MODE_ONE}, - * {@link PlaybackState#REPEAT_MODE_ALL} - */ - public void setRepeatMode(@PlaybackState.RepeatMode int repeatMode) { - try { - mSessionBinder.repeatMode(repeatMode); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling setRepeatMode", e); - } - } - - /** - * Set the shuffle mode for this session. - * - * @param enabled {@code true} to enable the shuffle mode, {@code false} to disable. - */ - public void setShuffleModeEnabled(boolean enabled) { - try { - mSessionBinder.shuffleMode(enabled); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling shuffleMode", e); + Log.wtf(TAG, "Error calling rate.", e); } } @@ -1042,7 +871,7 @@ public final class MediaController { public void sendCustomAction(@NonNull PlaybackState.CustomAction customAction, @Nullable Bundle args) { if (customAction == null) { - throw new IllegalArgumentException("CustomAction cannot be null"); + throw new IllegalArgumentException("CustomAction cannot be null."); } sendCustomAction(customAction.getAction(), args); } @@ -1058,12 +887,12 @@ public final class MediaController { */ public void sendCustomAction(@NonNull String action, @Nullable Bundle args) { if (TextUtils.isEmpty(action)) { - throw new IllegalArgumentException("CustomAction cannot be null"); + throw new IllegalArgumentException("CustomAction cannot be null."); } try { mSessionBinder.sendCustomAction(action, args); } catch (RemoteException e) { - Log.d(TAG, "Dead object in sendCustomAction", e); + Log.d(TAG, "Dead object in sendCustomAction.", e); } } } @@ -1233,21 +1062,6 @@ public final class MediaController { } } - @Override - public void onRepeatModeChanged(int repeatMode) { - MediaController controller = mController.get(); - if (controller != null) { - controller.postMessage(MSG_UPDATE_REPEAT_MODE, repeatMode, null); - } - } - - @Override - public void onShuffleModeChanged(boolean enabled) { - MediaController controller = mController.get(); - if (controller != null) { - controller.postMessage(MSG_UPDATE_SHUFFLE_MODE, enabled, null); - } - } } private final static class MessageHandler extends Handler { @@ -1286,12 +1100,6 @@ public final class MediaController { case MSG_UPDATE_VOLUME: mCallback.onAudioInfoChanged((PlaybackInfo) msg.obj); break; - case MSG_UPDATE_REPEAT_MODE: - mCallback.onRepeatModeChanged((int) msg.obj); - break; - case MSG_UPDATE_SHUFFLE_MODE: - mCallback.onShuffleModeChanged((boolean) msg.obj); - break; case MSG_DESTROYED: mCallback.onSessionDestroyed(); break; diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java index f10f4427d6f0..dfd2bb35d6ea 100644 --- a/media/java/android/media/session/MediaSession.java +++ b/media/java/android/media/session/MediaSession.java @@ -93,12 +93,6 @@ public final class MediaSession { public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 1 << 1; /** - * Set this flag on the session to indicate that it handles queue - * management commands through its {@link Callback}. - */ - public static final int FLAG_HANDLES_QUEUE_COMMANDS = 1 << 2; - - /** * System only flag for a session that needs to have priority over all other * sessions. This flag ensures this session will receive media button events * regardless of the current ordering in the system. @@ -112,7 +106,6 @@ public final class MediaSession { @IntDef(flag = true, value = { FLAG_HANDLES_MEDIA_BUTTONS, FLAG_HANDLES_TRANSPORT_CONTROLS, - FLAG_HANDLES_QUEUE_COMMANDS, FLAG_EXCLUSIVE_GLOBAL_PRIORITY }) public @interface SessionFlags { } @@ -493,41 +486,6 @@ public final class MediaSession { } /** - * Set the repeat mode for this session. - * <p> - * Note that if this method is not called before, {@link MediaController#getRepeatMode} - * will return {@link PlaybackState#REPEAT_MODE_NONE}. - * - * @param repeatMode The repeat mode. Must be one of the followings: - * {@link PlaybackState#REPEAT_MODE_NONE}, - * {@link PlaybackState#REPEAT_MODE_ONE}, - * {@link PlaybackState#REPEAT_MODE_ALL} - */ - public void setRepeatMode(@PlaybackState.RepeatMode int repeatMode) { - try { - mBinder.setRepeatMode(repeatMode); - } catch (RemoteException e) { - Log.e(TAG, "Error in setRepeatMode.", e); - } - } - - /** - * Set the shuffle mode for this session. - * <p> - * Note that if this method is not called before, {@link MediaController#isShuffleModeEnabled} - * will return {@code false}. - * - * @param enabled {@code true} to enable the shuffle mode, {@code false} to disable. - */ - public void setShuffleModeEnabled(boolean enabled) { - try { - mBinder.setShuffleModeEnabled(enabled); - } catch (RemoteException e) { - Log.e(TAG, "Error in setShuffleModeEnabled.", e); - } - } - - /** * Set some extras that can be associated with the {@link MediaSession}. No assumptions should * be made as to how a {@link MediaController} will handle these extras. * Keys should be fully qualified (e.g. com.example.MY_EXTRA) to avoid conflicts. @@ -646,34 +604,10 @@ public final class MediaSession { postToCallback(CallbackMessageHandler.MSG_RATE, rating); } - private void dispatchRepeatMode(int repeatMode) { - postToCallback(CallbackMessageHandler.MSG_REPEAT_MODE, repeatMode); - } - - private void dispatchShuffleMode(boolean enabled) { - postToCallback(CallbackMessageHandler.MSG_SHUFFLE_MODE, enabled); - } - private void dispatchCustomAction(String action, Bundle args) { postToCallback(CallbackMessageHandler.MSG_CUSTOM_ACTION, action, args); } - private void dispatchAddQueueItem(MediaDescription description) { - postToCallback(CallbackMessageHandler.MSG_ADD_QUEUE_ITEM, description); - } - - private void dispatchAddQueueItem(MediaDescription description, int index) { - postToCallback(CallbackMessageHandler.MSG_ADD_QUEUE_ITEM_AT, description, index); - } - - private void dispatchRemoveQueueItem(MediaDescription description) { - postToCallback(CallbackMessageHandler.MSG_REMOVE_QUEUE_ITEM, description); - } - - private void dispatchRemoveQueueItemAt(int index) { - postToCallback(CallbackMessageHandler.MSG_REMOVE_QUEUE_ITEM_AT, index); - } - private void dispatchMediaButton(Intent mediaButtonIntent) { postToCallback(CallbackMessageHandler.MSG_MEDIA_BUTTON, mediaButtonIntent); } @@ -695,22 +629,10 @@ public final class MediaSession { postToCallback(CallbackMessageHandler.MSG_COMMAND, cmd); } - private void postToCallback(int what, int arg1) { - postToCallback(what, null, arg1); - } - private void postToCallback(int what, Object obj) { postToCallback(what, obj, null); } - private void postToCallback(int what, Object obj, int arg1) { - synchronized (mLock) { - if (mCallback != null) { - mCallback.post(what, obj, arg1); - } - } - } - private void postToCallback(int what, Object obj, Bundle extras) { synchronized (mLock) { if (mCallback != null) { @@ -1048,33 +970,6 @@ public final class MediaSession { } /** - * Override to handle the setting of the repeat mode. - * <p> - * You should call {@link #setRepeatMode} before end of this method in order to notify - * the change to the {@link MediaController}, or {@link MediaController#getRepeatMode} - * could return an invalid value. - * - * @param repeatMode The repeat mode which is one of followings: - * {@link PlaybackState#REPEAT_MODE_NONE}, - * {@link PlaybackState#REPEAT_MODE_ONE}, - * {@link PlaybackState#REPEAT_MODE_ALL} - */ - public void onSetRepeatMode(@PlaybackState.RepeatMode int repeatMode) { - } - - /** - * Override to handle the setting of the shuffle mode. - * <p> - * You should call {@link #setShuffleModeEnabled} before the end of this method in order to - * notify the change to the {@link MediaController}, or - * {@link MediaController#isShuffleModeEnabled} could return an invalid value. - * - * @param enabled true when the shuffle mode is enabled, false otherwise. - */ - public void onSetShuffleModeEnabled(boolean enabled) { - } - - /** * Called when a {@link MediaController} wants a {@link PlaybackState.CustomAction} to be * performed. * @@ -1084,47 +979,6 @@ public final class MediaSession { */ public void onCustomAction(@NonNull String action, @Nullable Bundle extras) { } - - /** - * Called when a {@link MediaController} wants to add a {@link QueueItem} with the given - * {@link MediaDescription description} at the end of the play queue. - * - * @param description The {@link MediaDescription} for creating the {@link QueueItem} to be - * inserted. - */ - public void onAddQueueItem(MediaDescription description) { - } - - /** - * Called when a {@link MediaController} wants to add a {@link QueueItem} with the given - * {@link MediaDescription description} at the specified position in the play queue. - * - * @param description The {@link MediaDescription} for creating the {@link QueueItem} to be - * inserted. - * @param index The index at which the created {@link QueueItem} is to be inserted. - */ - public void onAddQueueItem(MediaDescription description, int index) { - } - - /** - * Called when a {@link MediaController} wants to remove the first occurrence of the - * specified {@link QueueItem} with the given {@link MediaDescription description} - * in the play queue. - * - * @param description The {@link MediaDescription} for denoting the {@link QueueItem} to be - * removed. - */ - public void onRemoveQueueItem(MediaDescription description) { - } - - /** - * Called when a {@link MediaController} wants to remove a {@link QueueItem} at the - * specified position in the play queue. - * - * @param index The index of the element to be removed. - */ - public void onRemoveQueueItemAt(int index) { - } } /** @@ -1297,22 +1151,6 @@ public final class MediaSession { } @Override - public void onRepeatMode(int repeatMode) { - MediaSession session = mMediaSession.get(); - if (session != null) { - session.dispatchRepeatMode(repeatMode); - } - } - - @Override - public void onShuffleMode(boolean enabled) { - MediaSession session = mMediaSession.get(); - if (session != null) { - session.dispatchShuffleMode(enabled); - } - } - - @Override public void onCustomAction(String action, Bundle args) { MediaSession session = mMediaSession.get(); if (session != null) { @@ -1321,38 +1159,6 @@ public final class MediaSession { } @Override - public void onAddQueueItem(MediaDescription description) { - MediaSession session = mMediaSession.get(); - if (session != null) { - session.dispatchAddQueueItem(description); - } - } - - @Override - public void onAddQueueItemAt(MediaDescription description, int index) { - MediaSession session = mMediaSession.get(); - if (session != null) { - session.dispatchAddQueueItem(description, index); - } - } - - @Override - public void onRemoveQueueItem(MediaDescription description) { - MediaSession session = mMediaSession.get(); - if (session != null) { - session.dispatchRemoveQueueItem(description); - } - } - - @Override - public void onRemoveQueueItemAt(int index) { - MediaSession session = mMediaSession.get(); - if (session != null) { - session.dispatchRemoveQueueItemAt(index); - } - } - - @Override public void onAdjustVolume(int direction) { MediaSession session = mMediaSession.get(); if (session != null) { @@ -1376,7 +1182,7 @@ public final class MediaSession { */ public static final class QueueItem implements Parcelable { /** - * This id is reserved. No items can be explicitly asigned this id. + * This id is reserved. No items can be explicitly assigned this id. */ public static final int UNKNOWN_ID = -1; @@ -1485,15 +1291,9 @@ public final class MediaSession { private static final int MSG_REWIND = 17; private static final int MSG_SEEK_TO = 18; private static final int MSG_RATE = 19; - private static final int MSG_REPEAT_MODE = 20; - private static final int MSG_SHUFFLE_MODE = 21; - private static final int MSG_CUSTOM_ACTION = 22; - private static final int MSG_ADJUST_VOLUME = 23; - private static final int MSG_SET_VOLUME = 24; - private static final int MSG_ADD_QUEUE_ITEM = 25; - private static final int MSG_ADD_QUEUE_ITEM_AT = 26; - private static final int MSG_REMOVE_QUEUE_ITEM = 27; - private static final int MSG_REMOVE_QUEUE_ITEM_AT = 28; + private static final int MSG_CUSTOM_ACTION = 20; + private static final int MSG_ADJUST_VOLUME = 21; + private static final int MSG_SET_VOLUME = 22; private MediaSession.Callback mCallback; @@ -1582,33 +1382,15 @@ public final class MediaSession { case MSG_RATE: mCallback.onSetRating((Rating) msg.obj); break; - case MSG_REPEAT_MODE: - mCallback.onSetRepeatMode(msg.arg1); - break; - case MSG_SHUFFLE_MODE: - mCallback.onSetShuffleModeEnabled((boolean) msg.obj); - break; case MSG_CUSTOM_ACTION: mCallback.onCustomAction((String) msg.obj, msg.getData()); break; - case MSG_ADD_QUEUE_ITEM: - mCallback.onAddQueueItem((MediaDescription) msg.obj); - break; - case MSG_ADD_QUEUE_ITEM_AT: - mCallback.onAddQueueItem((MediaDescription) msg.obj, msg.arg1); - break; - case MSG_REMOVE_QUEUE_ITEM: - mCallback.onRemoveQueueItem((MediaDescription) msg.obj); - break; - case MSG_REMOVE_QUEUE_ITEM_AT: - mCallback.onRemoveQueueItemAt(msg.arg1); - break; case MSG_ADJUST_VOLUME: synchronized (mLock) { vp = mVolumeProvider; } if (vp != null) { - vp.onAdjustVolume(msg.arg1); + vp.onAdjustVolume((int) msg.obj); } break; case MSG_SET_VOLUME: @@ -1616,7 +1398,7 @@ public final class MediaSession { vp = mVolumeProvider; } if (vp != null) { - vp.onSetVolumeTo(msg.arg1); + vp.onSetVolumeTo((int) msg.obj); } break; } diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java index 1ea61093d869..8283c8b967e8 100644 --- a/media/java/android/media/session/PlaybackState.java +++ b/media/java/android/media/session/PlaybackState.java @@ -45,8 +45,7 @@ public final class PlaybackState implements Parcelable { ACTION_SKIP_TO_PREVIOUS, ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_SET_RATING, ACTION_SEEK_TO, ACTION_PLAY_PAUSE, ACTION_PLAY_FROM_MEDIA_ID, ACTION_PLAY_FROM_SEARCH, ACTION_SKIP_TO_QUEUE_ITEM, ACTION_PLAY_FROM_URI, ACTION_PREPARE, - ACTION_PREPARE_FROM_MEDIA_ID, ACTION_PREPARE_FROM_SEARCH, ACTION_PREPARE_FROM_URI, - ACTION_SET_REPEAT_MODE, ACTION_SET_SHUFFLE_MODE_ENABLED}) + ACTION_PREPARE_FROM_MEDIA_ID, ACTION_PREPARE_FROM_SEARCH, ACTION_PREPARE_FROM_URI}) @Retention(RetentionPolicy.SOURCE) public @interface Actions {} @@ -177,20 +176,6 @@ public final class PlaybackState implements Parcelable { public static final long ACTION_PREPARE_FROM_URI = 1 << 17; /** - * Indicates this session supports the set repeat mode command. - * - * @see Builder#setActions(long) - */ - public static final long ACTION_SET_REPEAT_MODE = 1 << 18; - - /** - * Indicates this session supports the set shuffle mode enabled command. - * - * @see Builder#setActions(long) - */ - public static final long ACTION_SET_SHUFFLE_MODE_ENABLED = 1 << 19; - - /** * @hide */ @IntDef({STATE_NONE, STATE_STOPPED, STATE_PAUSED, STATE_PLAYING, STATE_FAST_FORWARDING, @@ -296,30 +281,6 @@ public final class PlaybackState implements Parcelable { */ public final static long PLAYBACK_POSITION_UNKNOWN = -1; - /** - * @hide - */ - @IntDef({REPEAT_MODE_NONE, REPEAT_MODE_ONE, REPEAT_MODE_ALL}) - @Retention(RetentionPolicy.SOURCE) - public @interface RepeatMode {} - /** - * Use this value with {@link MediaController.TransportControls#setRepeatMode} - * to indicate that the playback will be stopped at the end of the playing media list. - */ - public final static int REPEAT_MODE_NONE = 0; - - /** - * Use this value with {@link MediaController.TransportControls#setRepeatMode} - * to indicate that the playback of the current playing media item will be repeated. - */ - public final static int REPEAT_MODE_ONE = 1; - - /** - * Use this value with {@link MediaController.TransportControls#setRepeatMode} - * to indicate that the playback of the playing media list will be repeated. - */ - public final static int REPEAT_MODE_ALL = 2; - private final int mState; private final long mPosition; private final long mBufferedPosition; @@ -466,8 +427,6 @@ public final class PlaybackState implements Parcelable { * <li> {@link PlaybackState#ACTION_PREPARE_FROM_MEDIA_ID}</li> * <li> {@link PlaybackState#ACTION_PREPARE_FROM_SEARCH}</li> * <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li> - * <li> {@link PlaybackState#ACTION_SET_REPEAT_MODE}</li> - * <li> {@link PlaybackState#ACTION_SET_SHUFFLE_MODE_ENABLED}</li> * </ul> */ @Actions @@ -1002,8 +961,6 @@ public final class PlaybackState implements Parcelable { * <li> {@link PlaybackState#ACTION_PREPARE_FROM_MEDIA_ID}</li> * <li> {@link PlaybackState#ACTION_PREPARE_FROM_SEARCH}</li> * <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li> - * <li> {@link PlaybackState#ACTION_SET_REPEAT_MODE}</li> - * <li> {@link PlaybackState#ACTION_SET_SHUFFLE_MODE_ENABLED}</li> * </ul> * * @param actions The set of actions allowed. diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java index 1b55380ed5a9..71f9ba257aa3 100644 --- a/media/java/android/media/tv/TvContract.java +++ b/media/java/android/media/tv/TvContract.java @@ -436,6 +436,14 @@ public final class TvContract { public static final String PARAM_CANONICAL_GENRE = "canonical_genre"; /** + * A query, update or delete URI parameter that allows the caller to operate only on preview or + * non-preview channels. If set to "true", the operation affects the rows for preview channels + * only. If set to "false", the operation affects the rows for non-preview channels only. + * @hide + */ + public static final String PARAM_PREVIEW = "preview"; + + /** * Builds an ID that uniquely identifies a TV input service. * * @param name The {@link ComponentName} of the TV input service to build ID for. diff --git a/media/java/android/service/media/IMediaBrowserService.aidl b/media/java/android/service/media/IMediaBrowserService.aidl index e95154ff4540..84f41f6c3afe 100644 --- a/media/java/android/service/media/IMediaBrowserService.aidl +++ b/media/java/android/service/media/IMediaBrowserService.aidl @@ -19,10 +19,8 @@ oneway interface IMediaBrowserService { void addSubscriptionDeprecated(String uri, IMediaBrowserServiceCallbacks callbacks); void removeSubscriptionDeprecated(String uri, IMediaBrowserServiceCallbacks callbacks); - void getMediaItem(String uri, in ResultReceiver cb, IMediaBrowserServiceCallbacks callbacks); - void search(String query, in Bundle extras, in ResultReceiver cb, - IMediaBrowserServiceCallbacks callbacks); + void getMediaItem(String uri, in ResultReceiver cb, IMediaBrowserServiceCallbacks callbacks); void addSubscription(String uri, in IBinder token, in Bundle options, IMediaBrowserServiceCallbacks callbacks); void removeSubscription(String uri, in IBinder token, IMediaBrowserServiceCallbacks callbacks); diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java index d372efbea5ca..b52906ddd1ae 100644 --- a/media/java/android/service/media/MediaBrowserService.java +++ b/media/java/android/service/media/MediaBrowserService.java @@ -89,15 +89,8 @@ public abstract class MediaBrowserService extends Service { */ public static final String KEY_MEDIA_ITEM = "media_item"; - /** - * A key for passing the list of MediaItems to the ResultReceiver in search. - * @hide - */ - public static final String KEY_SEARCH_RESULTS = "search_results"; - private static final int RESULT_FLAG_OPTION_NOT_HANDLED = 1 << 0; private static final int RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED = 1 << 1; - private static final int RESULT_FLAG_ON_SEARCH_NOT_IMPLEMENTED = 1 << 2; private static final int RESULT_ERROR = -1; private static final int RESULT_OK = 0; @@ -105,7 +98,7 @@ public abstract class MediaBrowserService extends Service { /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(flag=true, value = { RESULT_FLAG_OPTION_NOT_HANDLED, - RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED, RESULT_FLAG_ON_SEARCH_NOT_IMPLEMENTED }) + RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED }) private @interface ResultFlags { } private final ArrayMap<IBinder, ConnectionRecord> mConnections = new ArrayMap<>(); @@ -137,7 +130,6 @@ public abstract class MediaBrowserService extends Service { * * @see #onLoadChildren * @see #onLoadItem - * @see #onSearch */ public class Result<T> { private Object mDebug; @@ -330,23 +322,6 @@ public abstract class MediaBrowserService extends Service { } }); } - - @Override - public void search(final String query, Bundle extras, ResultReceiver receiver, - final IMediaBrowserServiceCallbacks callbacks) { - mHandler.post(new Runnable() { - @Override - public void run() { - final IBinder b = callbacks.asBinder(); - ConnectionRecord connection = mConnections.get(b); - if (connection == null) { - Log.w(TAG, "search for callback that isn't registered query=" + query); - return; - } - performSearch(query, extras, connection, receiver); - } - }); - } } @Override @@ -472,32 +447,6 @@ public abstract class MediaBrowserService extends Service { } /** - * Called to get the search result. - * <p> - * Implementations must call {@link Result#sendResult result.sendResult}. If - * the search will be an expensive operation {@link Result#detach result.detach} - * may be called before returning from this function, and then {@link Result#sendResult - * result.sendResult} called when the search has been completed. - * </p><p> - * In case there are no search results, call {@link Result#sendResult} with an empty list. - * In case there are some errors happened, call {@link Result#sendResult result.sendResult} - * with {@code null}, which will invoke {@link MediaBrowser.SearchCallback#onError}. - * </p><p> - * The default implementation will invoke {@link MediaBrowser.SearchCallback#onError}. - * </p> - * - * @param query The search query sent from the media browser. It contains keywords separated - * by space. - * @param extras The bundle of service-specific arguments sent from the media browser. - * @param result The {@link Result} to send the search result. - */ - public void onSearch(@NonNull String query, Bundle extras, - Result<List<MediaBrowser.MediaItem>> result) { - result.setFlags(RESULT_FLAG_ON_SEARCH_NOT_IMPLEMENTED); - result.sendResult(null); - } - - /** * Call to set the media session. * <p> * This should be called as soon as possible during the service's startup. @@ -545,16 +494,16 @@ public abstract class MediaBrowserService extends Service { * media browser service when connecting and retrieving the root id for browsing, or null if * none. The contents of this bundle may affect the information returned when browsing. * - * @throws IllegalStateException If this method is called outside of {@link #onLoadChildren}, - * {@link #onLoadItem} or {@link #onSearch}. + * @throws IllegalStateException If this method is called outside of {@link #onLoadChildren} or + * {@link #onLoadItem}. * @see MediaBrowserService.BrowserRoot#EXTRA_RECENT * @see MediaBrowserService.BrowserRoot#EXTRA_OFFLINE * @see MediaBrowserService.BrowserRoot#EXTRA_SUGGESTED */ public final Bundle getBrowserRootHints() { if (mCurConnection == null) { - throw new IllegalStateException("This should be called inside of onLoadChildren," - + " onLoadItem or onSearch methods"); + throw new IllegalStateException("This should be called inside of onLoadChildren or" + + " onLoadItem methods"); } return mCurConnection.rootHints == null ? null : new Bundle(mCurConnection.rootHints); } @@ -771,34 +720,6 @@ public abstract class MediaBrowserService extends Service { } } - private void performSearch(String query, Bundle extras, final ConnectionRecord connection, - final ResultReceiver receiver) { - final Result<List<MediaBrowser.MediaItem>> result = - new Result<List<MediaBrowser.MediaItem>>(query) { - @Override - void onResultSent(List<MediaBrowser.MediaItem> items, @ResultFlags int flag) { - if ((flag & RESULT_FLAG_ON_SEARCH_NOT_IMPLEMENTED) != 0 - || items == null) { - receiver.send(RESULT_ERROR, null); - return; - } - Bundle bundle = new Bundle(); - bundle.putParcelableArray(KEY_SEARCH_RESULTS, - items.toArray(new MediaBrowser.MediaItem[0])); - receiver.send(RESULT_OK, bundle); - } - }; - - mCurConnection = connection; - onSearch(query, extras, result); - mCurConnection = null; - - if (!result.isDone()) { - throw new IllegalStateException("onSearch must call detach() or sendResult()" - + " before returning for query=" + query); - } - } - /** * Contains information that the browser service needs to send to the client * when first connected. diff --git a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityButtonHelper.java b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityButtonHelper.java new file mode 100644 index 000000000000..972ea347e6dd --- /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/drawer/CategoryKey.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java index d6bde8132327..9d09737a14dc 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java @@ -40,6 +40,8 @@ public final class CategoryKey { "com.android.settings.category.ia.language"; public static final String CATEGORY_SYSTEM_DEVELOPMENT = "com.android.settings.category.ia.development"; + public static final String CATEGORY_NOTIFICATIONS = + "com.android.settings.category.ia.notifications"; public static final Map<String, String> KEY_COMPAT_MAP; diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java index c5653733bac7..28bd23ce9825 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -143,10 +143,10 @@ public class PipManager implements BasePipManager { @Override public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, - Rect animatingBounds, boolean fromImeAdjustement) { + Rect animatingBounds, boolean fromImeAdjustement, int displayRotation) { mHandler.post(() -> { mTouchHandler.onMovementBoundsChanged(insetBounds, normalBounds, animatingBounds, - fromImeAdjustement); + fromImeAdjustement, displayRotation); }); } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java index ac0670348af2..982b8085b216 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java @@ -221,6 +221,13 @@ public class PipMenuActivity extends Activity { } @Override + protected void onStop() { + super.onStop(); + + cancelDelayedFinish(); + } + + @Override protected void onDestroy() { super.onDestroy(); diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java index 127296cd7f8e..67255d35590a 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java @@ -316,7 +316,8 @@ public class PipMotionHelper { * Animates the PiP from the expanded state to the normal state after the menu is hidden. */ void animateToUnexpandedState(Rect normalBounds, float savedSnapFraction, - Rect normalMovementBounds, Rect currentMovementBounds, boolean minimized) { + Rect normalMovementBounds, Rect currentMovementBounds, boolean minimized, + boolean immediate) { if (savedSnapFraction < 0f) { // If there are no saved snap fractions, then just use the current bounds savedSnapFraction = mSnapAlgorithm.getSnapFraction(new Rect(mBounds), @@ -326,7 +327,11 @@ public class PipMotionHelper { if (minimized) { normalBounds = getClosestMinimizedBounds(normalBounds, normalMovementBounds); } - resizeAndAnimatePipUnchecked(normalBounds, SHRINK_STACK_FROM_MENU_DURATION); + if (immediate) { + movePip(normalBounds); + } else { + resizeAndAnimatePipUnchecked(normalBounds, SHRINK_STACK_FROM_MENU_DURATION); + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java index 3f26fddb1b3c..fbf7ff21b0ce 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 @@ public class PipTouchHandler implements TunerService.Tunable { 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 @@ public class PipTouchHandler implements TunerService.Tunable { private Rect mExpandedMovementBounds = new Rect(); private int mExpandedShortestEdgeSize; + // Used to workaround an issue where the WM rotation happens before we are notified, allowing + // us to send stale bounds + private int mDeferResizeToNormalBoundsUntilRotation = -1; + private int mDisplayRotation; + private Handler mHandler = new Handler(); private Runnable mShowDismissAffordance = new Runnable() { @Override @@ -216,13 +222,18 @@ public class PipTouchHandler implements TunerService.Tunable { 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 class PipTouchHandler implements TunerService.Tunable { } public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, Rect animatingBounds, - boolean fromImeAdjustement) { + boolean fromImeAdjustement, int displayRotation) { // Re-calculate the expanded bounds mNormalBounds = normalBounds; Rect normalMovementBounds = new Rect(); @@ -304,7 +315,17 @@ public class PipTouchHandler implements TunerService.Tunable { // above mNormalMovementBounds = normalMovementBounds; mExpandedMovementBounds = expandedMovementBounds; + mDisplayRotation = displayRotation; updateMovementBounds(mMenuState); + + // If we have a deferred resize, apply it now + if (mDeferResizeToNormalBoundsUntilRotation == displayRotation) { + mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction, + mNormalMovementBounds, mMovementBounds, mIsMinimized, + true /* immediate */); + mSavedSnapFraction = -1f; + mDeferResizeToNormalBoundsUntilRotation = -1; + } } private void onRegistrationChanged(boolean isRegistered) { @@ -474,11 +495,34 @@ public class PipTouchHandler implements TunerService.Tunable { // Try and restore the PiP to the closest edge, using the saved snap fraction // if possible if (resize) { - Rect normalBounds = new Rect(mNormalBounds); - mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction, - mNormalMovementBounds, mMovementBounds, mIsMinimized); + // This is a very special case: when the menu is expanded and visible, navigating to + // another activity can trigger auto-enter PiP, and if the revealed activity has a + // forced rotation set, then the controller will get updated with the new rotation + // of the display. However, at the same time, SystemUI will try to hide the menu by + // creating an animation to the normal bounds which are now stale. In such a case + // we defer the animation to the normal bounds until after the next + // onMovementBoundsChanged() call to get the bounds in the new orientation + if (mDeferResizeToNormalBoundsUntilRotation == -1) { + try { + int displayRotation = mPinnedStackController.getDisplayRotation(); + if (mDisplayRotation != displayRotation) { + mDeferResizeToNormalBoundsUntilRotation = displayRotation; + } + } catch (RemoteException e) { + Log.e(TAG, "Could not get display rotation from controller"); + } + } + + if (mDeferResizeToNormalBoundsUntilRotation == -1) { + Rect normalBounds = new Rect(mNormalBounds); + mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction, + mNormalMovementBounds, mMovementBounds, mIsMinimized, + false /* immediate */); + mSavedSnapFraction = -1f; + } + } else { + mSavedSnapFraction = -1f; } - mSavedSnapFraction = -1f; } mMenuState = menuState; updateMovementBounds(menuState); diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java index f2f0d7a5a86c..657f08be8b52 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java @@ -178,7 +178,7 @@ public class PipManager implements BasePipManager { @Override public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, - Rect animatingBounds, boolean fromImeAdjustement) { + Rect animatingBounds, boolean fromImeAdjustement, int displayRotation) { mHandler.post(() -> { mDefaultPipBounds.set(normalBounds); }); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index 677642e53d6e..cc9175382903 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -1115,6 +1115,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mNotificationInflater.setInflateExceptionHandler(inflateExceptionHandler); } + public void setNeedsRedaction(boolean needsRedaction) { + mNotificationInflater.setRedactAmbient(needsRedaction); + } + public interface ExpansionLogger { public void logNotificationExpansion(String key, boolean userAction, boolean expanded); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java index 8f160dc0384e..609856522e75 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java @@ -428,6 +428,9 @@ public class NotificationContentView extends FrameLayout { mAmbientChild.animate().cancel(); removeView(mAmbientChild); } + if (child == null) { + return; + } addView(child); mAmbientChild = child; mAmbientWrapper = NotificationViewWrapper.wrap(getContext(), child, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java index fee24b7b7645..802925a315eb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java @@ -227,6 +227,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl if (mShouldShowMenu && !NotificationStackScrollLayout.isPinnedHeadsUp(view) && !mParent.areGutsExposed() + && !mParent.isDark() && (mCheckForDrag == null || !mHandler.hasCallbacks(mCheckForDrag))) { // Only show the menu if we're not a heads up view and guts aren't exposed. mCheckForDrag = new CheckForDrag(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java index 73eecbbf2728..2e34f2483a85 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java @@ -21,6 +21,8 @@ import android.content.Context; import android.service.notification.StatusBarNotification; import android.util.Log; import android.view.View; +import android.view.ViewGroup; +import android.view.ViewParent; import android.widget.RemoteViews; import com.android.internal.annotations.VisibleForTesting; @@ -49,6 +51,7 @@ public class NotificationInflater { private RemoteViews.OnClickHandler mRemoteViewClickHandler; private boolean mIsChildInGroup; private InflationExceptionHandler mInflateExceptionHandler; + private boolean mRedactAmbient; public NotificationInflater(ExpandableNotificationRow row) { mRow = row; @@ -92,6 +95,21 @@ public class NotificationInflater { mRemoteViewClickHandler = remoteViewClickHandler; } + public void setRedactAmbient(boolean redactAmbient) { + if (mRedactAmbient != redactAmbient) { + mRedactAmbient = redactAmbient; + if (mRow.getEntry() == null) { + return; + } + try { + inflateNotificationViews(FLAG_REINFLATE_AMBIENT_VIEW); + } catch (InflationException e) { + mInflateExceptionHandler.handleInflationException( + mRow.getStatusBarNotification(), e); + } + } + } + public void inflateNotificationViews() throws InflationException { inflateNotificationViews(FLAG_REINFLATE_ALL); } @@ -123,6 +141,8 @@ public class NotificationInflater { Notification.Builder builder, Context packageContext) { NotificationData.Entry entry = mRow.getEntry(); NotificationContentView privateLayout = mRow.getPrivateLayout(); + NotificationContentView publicLayout = mRow.getPublicLayout(); + boolean isLowPriority = mIsLowPriority && !mIsChildInGroup; if ((reInflateFlags & FLAG_REINFLATE_CONTENT_VIEW) != 0) { final RemoteViews newContentView = createContentView(builder, @@ -190,7 +210,6 @@ public class NotificationInflater { } if ((reInflateFlags & FLAG_REINFLATE_PUBLIC_VIEW) != 0) { - NotificationContentView publicLayout = mRow.getPublicLayout(); final RemoteViews newPublicNotification = builder.makePublicContentView(); if (!compareRemoteViews(newPublicNotification, entry.cachedPublicContentView)) { @@ -209,18 +228,24 @@ public class NotificationInflater { } if ((reInflateFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) { - final RemoteViews newAmbientNotification - = builder.makeAmbientNotification(); - if (!compareRemoteViews(newAmbientNotification, entry.cachedAmbientContentView)) { + final RemoteViews newAmbientNotification = mRedactAmbient + ? builder.makePublicAmbientNotification() + : builder.makeAmbientNotification(); + NotificationContentView newParent = mRedactAmbient ? publicLayout : privateLayout; + NotificationContentView otherParent = !mRedactAmbient ? publicLayout : privateLayout; + + if (newParent.getAmbientChild() == null || + !compareRemoteViews(newAmbientNotification, entry.cachedAmbientContentView)) { View ambientContentView = newAmbientNotification.apply( packageContext, - privateLayout, + newParent, mRemoteViewClickHandler); ambientContentView.setIsRootNamespace(true); - privateLayout.setAmbientChild(ambientContentView); + newParent.setAmbientChild(ambientContentView); + otherParent.setAmbientChild(null); } else { newAmbientNotification.reapply(packageContext, - privateLayout.getAmbientChild(), + newParent.getAmbientChild(), mRemoteViewClickHandler); } entry.cachedAmbientContentView = newAmbientNotification; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 39060fc26428..79191f3c2114 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -49,10 +49,8 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentSender; -import android.content.pm.ActivityInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.database.ContentObserver; @@ -141,7 +139,6 @@ import com.android.systemui.doze.DozeLog; import com.android.systemui.fragments.FragmentHostManager; import com.android.systemui.fragments.PluginFragmentListener; import com.android.systemui.keyguard.KeyguardViewMediator; -import com.android.systemui.pip.phone.PipManager; import com.android.systemui.plugins.qs.QS; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption; @@ -1814,6 +1811,7 @@ public class StatusBar extends SystemUI implements DemoMode, updatePublicContentView(ent, ent.notification); } ent.row.setSensitive(sensitive, deviceSensitive); + ent.row.setNeedsRedaction(needsRedaction(ent)); if (mGroupManager.isChildInGroupWithSummary(ent.row.getStatusBarNotification())) { ExpandableNotificationRow summary = mGroupManager.getGroupSummary( ent.row.getStatusBarNotification()); @@ -1902,6 +1900,21 @@ public class StatusBar extends SystemUI implements DemoMode, mNotificationIconAreaController.updateNotificationIcons(mNotificationData); } + /** @return true if the entry needs redaction when on the lockscreen. */ + private boolean needsRedaction(Entry ent) { + int userId = ent.notification.getUserId(); + + boolean currentUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(mCurrentUserId); + boolean notiUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(userId); + boolean redactedLockscreen = currentUserWantsRedaction || notiUserWantsRedaction; + + boolean notificationRequestsRedaction = + ent.notification.getNotification().visibility == Notification.VISIBILITY_PRIVATE; + boolean userForcesRedaction = packageHasVisibilityOverride(ent.notification.getKey()); + + return userForcesRedaction || notificationRequestsRedaction && redactedLockscreen; + } + /** * Disable QS if device not provisioned. * If the user switcher is simple then disable QS during setup because @@ -5862,6 +5875,9 @@ public class StatusBar extends SystemUI implements DemoMode, } final ExpandableNotificationRow row = (ExpandableNotificationRow) v; + if (row.isDark()) { + return false; + } bindGuts(row, item); NotificationGuts guts = row.getGuts(); @@ -6163,6 +6179,7 @@ public class StatusBar extends SystemUI implements DemoMode, } } + row.setNeedsRedaction(needsRedaction(entry)); boolean isLowPriority = mNotificationData.isAmbient(sbn.getKey()); row.setIsLowPriority(isLowPriority); // bind the click event to the content area @@ -6527,7 +6544,6 @@ public class StatusBar extends SystemUI implements DemoMode, NotificationData.Entry entry = new NotificationData.Entry(sbn); Dependency.get(LeakDetector.class).trackInstance(entry); entry.createIcons(mContext, sbn); - // Construct the expanded view. inflateViews(entry, mStackScroller); return entry; diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 39bfedae69d8..8ad3d23648bf 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -49,6 +49,7 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; +import android.annotation.BinderThread; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -2146,6 +2147,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return mKeyguardManager != null && mKeyguardManager.isKeyguardLocked(); } + @BinderThread @SuppressWarnings("deprecation") @Override public void setImeWindowStatus(IBinder token, IBinder startInputToken, int vis, @@ -2161,9 +2163,23 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mBackDisposition = backDisposition; updateSystemUiLocked(token, vis, backDisposition); } + + final boolean dismissImeOnBackKeyPressed; + switch (backDisposition) { + case InputMethodService.BACK_DISPOSITION_WILL_DISMISS: + dismissImeOnBackKeyPressed = true; + break; + case InputMethodService.BACK_DISPOSITION_WILL_NOT_DISMISS: + dismissImeOnBackKeyPressed = false; + break; + default: + case InputMethodService.BACK_DISPOSITION_DEFAULT: + dismissImeOnBackKeyPressed = ((vis & InputMethodService.IME_VISIBLE) != 0); + break; + } mWindowManagerInternal.updateInputMethodWindowStatus(token, (vis & InputMethodService.IME_VISIBLE) != 0, - info != null ? info.mTargetWindow : null); + dismissImeOnBackKeyPressed, info != null ? info.mTargetWindow : null); } private void updateSystemUi(IBinder token, int vis, int backDisposition) { diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index c77820b4de3a..2cd14e93791d 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -312,8 +312,7 @@ public final class ActiveServices { } ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, - int id, Notification notification, int callingPid, int callingUid, - boolean fgRequired, String callingPackage, final int userId) + int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId) throws TransactionTooLargeException { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service + " type=" + resolvedType + " args=" + service.getExtras()); @@ -464,10 +463,6 @@ public final class ActiveServices { } ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); - // STOPSHIP deprecated; remove when NotificationManager.startServiceInForeground is retired - if (notification != null) { - setServiceForegroundInnerLocked(r, id, notification, 0); - } return cmp; } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 1c2a6aa2bbdf..d43fa0123925 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1230,6 +1230,20 @@ public class ActivityManagerService extends IActivityManager.Stub */ int[] mDeviceIdleTempWhitelist = new int[0]; + static final class PendingTempWhitelist { + final int targetUid; + final long duration; + final String tag; + + PendingTempWhitelist(int _targetUid, long _duration, String _tag) { + targetUid = _targetUid; + duration = _duration; + tag = _tag; + } + } + + final SparseArray<PendingTempWhitelist> mPendingTempWhitelist = new SparseArray<>(); + /** * Information about and control over application operations */ @@ -1688,6 +1702,7 @@ public class ActivityManagerService extends IActivityManager.Stub static final int NOTIFY_VR_SLEEPING_MSG = 65; static final int SERVICE_FOREGROUND_TIMEOUT_MSG = 66; static final int DISPATCH_PENDING_INTENT_CANCEL_MSG = 67; + static final int PUSH_TEMP_WHITELIST_UI_MSG = 68; static final int START_USER_SWITCH_FG_MSG = 712; static final int FIRST_ACTIVITY_STACK_MSG = 100; @@ -1921,6 +1936,9 @@ public class ActivityManagerService extends IActivityManager.Stub case DISPATCH_UIDS_CHANGED_UI_MSG: { dispatchUidsChanged(); } break; + case PUSH_TEMP_WHITELIST_UI_MSG: { + pushTempWhitelist(); + } break; } } } @@ -6493,7 +6511,8 @@ public class ActivityManagerService extends IActivityManager.Stub // This is the first appearance of the uid, report it now! if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, "Creating new process uid: " + uidRec); - if (Arrays.binarySearch(mDeviceIdleTempWhitelist, UserHandle.getAppId(proc.uid)) >= 0) { + if (Arrays.binarySearch(mDeviceIdleTempWhitelist, UserHandle.getAppId(proc.uid)) >= 0 + || mPendingTempWhitelist.indexOfKey(proc.uid) >= 0) { uidRec.setWhitelist = uidRec.curWhitelist = true; } uidRec.updateHasInternetPermission(); @@ -7487,43 +7506,6 @@ public class ActivityManagerService extends IActivityManager.Stub } } - /** - * Whitelists {@code targetUid} to temporarily bypass Power Save mode. - */ - void tempWhitelistAppForPowerSave(int callerPid, int callerUid, int targetUid, long duration) { - if (DEBUG_WHITELISTS) { - Slog.d(TAG, "tempWhitelistAppForPowerSave(" + callerPid + ", " + callerUid + ", " - + targetUid + ", " + duration + ")"); - } - - if (checkPermission(CHANGE_DEVICE_IDLE_TEMP_WHITELIST, callerPid, callerUid) - != PackageManager.PERMISSION_GRANTED) { - synchronized (mPidsSelfLocked) { - final ProcessRecord pr = mPidsSelfLocked.get(callerPid); - if (pr == null) { - Slog.w(TAG, "tempWhitelistAppForPowerSave() no ProcessRecord for pid " - + callerPid); - return; - } - if (!pr.whitelistManager) { - if (DEBUG_WHITELISTS) { - Slog.d(TAG, "tempWhitelistAppForPowerSave() for target " + targetUid - + ": pid " + callerPid + " is not allowed"); - } - return; - } - } - } - - final long token = Binder.clearCallingIdentity(); - try { - mLocalDeviceIdleController.addPowerSaveTempWhitelistAppDirect(targetUid, duration, - true, "pe from uid:" + callerUid); - } finally { - Binder.restoreCallingIdentity(token); - } - } - @Override public void cancelIntentSender(IIntentSender sender) { if (!(sender instanceof PendingIntentRecord)) { @@ -7863,7 +7845,14 @@ public class ActivityManagerService extends IActivityManager.Stub r.pictureInPictureArgs.copyOnlySet(args); final float aspectRatio = r.pictureInPictureArgs.getAspectRatio(); final List<RemoteAction> actions = r.pictureInPictureArgs.getActions(); - final Rect sourceBounds = r.pictureInPictureArgs.getSourceRectHint(); + // Adjust the source bounds by the insets for the transition down + final Rect sourceBounds = new Rect(r.pictureInPictureArgs.getSourceRectHint()); + final Rect insets = r.pictureInPictureArgs.getSourceRectHintInsets(); + if (insets != null) { + sourceBounds.offsetTo(Math.max(0, sourceBounds.left - insets.left), + Math.max(0, sourceBounds.top - insets.top)); + } + mStackSupervisor.moveActivityToPinnedStackLocked(r, sourceBounds, aspectRatio, true /* moveHomeStackToFront */, "enterPictureInPictureMode"); final PinnedActivityStack stack = mStackSupervisor.getStack(PINNED_STACK_ID); @@ -8412,7 +8401,8 @@ public class ActivityManagerService extends IActivityManager.Stub boolean isOnDeviceIdleWhitelistLocked(int uid) { final int appId = UserHandle.getAppId(uid); return Arrays.binarySearch(mDeviceIdleWhitelist, appId) >= 0 - || Arrays.binarySearch(mDeviceIdleTempWhitelist, appId) >= 0; + || Arrays.binarySearch(mDeviceIdleTempWhitelist, appId) >= 0 + || mPendingTempWhitelist.indexOfKey(uid) >= 0; } private ProviderInfo getProviderInfoLocked(String authority, int userHandle, int pmFlags) { @@ -15588,6 +15578,18 @@ public class ActivityManagerService extends IActivityManager.Stub } pw.println(" mDeviceIdleWhitelist=" + Arrays.toString(mDeviceIdleWhitelist)); pw.println(" mDeviceIdleTempWhitelist=" + Arrays.toString(mDeviceIdleTempWhitelist)); + if (mPendingTempWhitelist.size() > 0) { + pw.println(" mPendingTempWhitelist:"); + for (int i = 0; i < mPendingTempWhitelist.size(); i++) { + PendingTempWhitelist ptw = mPendingTempWhitelist.valueAt(i); + pw.print(" "); + UserHandle.formatUid(pw, ptw.targetUid); + pw.print(": "); + TimeUtils.formatDuration(ptw.duration, pw); + pw.print(" "); + pw.println(ptw.tag); + } + } } if (dumpPackage == null) { pw.println(" mWakefulness=" @@ -17929,8 +17931,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public ComponentName startService(IApplicationThread caller, Intent service, - String resolvedType, int id, Notification notification, boolean requireForeground, - String callingPackage, int userId) + String resolvedType, boolean requireForeground, String callingPackage, int userId) throws TransactionTooLargeException { enforceNotIsolatedCaller("startService"); // Refuse possible leaked file descriptors @@ -17951,7 +17952,7 @@ public class ActivityManagerService extends IActivityManager.Stub ComponentName res; try { res = mServices.startServiceLocked(caller, service, - resolvedType, id, notification, callingPid, callingUid, + resolvedType, callingPid, callingUid, requireForeground, callingPackage, userId); } finally { Binder.restoreCallingIdentity(origId); @@ -17970,7 +17971,7 @@ public class ActivityManagerService extends IActivityManager.Stub ComponentName res; try { res = mServices.startServiceLocked(null, service, - resolvedType, 0, null, -1, uid, fgRequired, callingPackage, userId); + resolvedType, -1, uid, fgRequired, callingPackage, userId); } finally { Binder.restoreCallingIdentity(origId); } @@ -22700,6 +22701,80 @@ public class ActivityManagerService extends IActivityManager.Stub enqueueUidChangeLocked(uidRec, uid, UidRecord.CHANGE_IDLE); } + /** + * Whitelists {@code targetUid} to temporarily bypass Power Save mode. + */ + void tempWhitelistForPendingIntentLocked(int callerPid, int callerUid, int targetUid, + long duration, String tag) { + if (DEBUG_WHITELISTS) { + Slog.d(TAG, "tempWhitelistForPendingIntentLocked(" + callerPid + ", " + callerUid + ", " + + targetUid + ", " + duration + ")"); + } + + synchronized (mPidsSelfLocked) { + final ProcessRecord pr = mPidsSelfLocked.get(callerPid); + if (pr == null) { + Slog.w(TAG, "tempWhitelistForPendingIntentLocked() no ProcessRecord for pid " + + callerPid); + return; + } + if (!pr.whitelistManager) { + if (checkPermission(CHANGE_DEVICE_IDLE_TEMP_WHITELIST, callerPid, callerUid) + != PackageManager.PERMISSION_GRANTED) { + if (DEBUG_WHITELISTS) { + Slog.d(TAG, "tempWhitelistForPendingIntentLocked() for target " + targetUid + + ": pid " + callerPid + " is not allowed"); + } + return; + } + } + } + + tempWhitelistUidLocked(targetUid, duration, tag); + } + + /** + * Whitelists {@code targetUid} to temporarily bypass Power Save mode. + */ + void tempWhitelistUidLocked(int targetUid, long duration, String tag) { + mPendingTempWhitelist.put(targetUid, new PendingTempWhitelist(targetUid, duration, tag)); + setUidTempWhitelistStateLocked(targetUid, true); + mUiHandler.obtainMessage(PUSH_TEMP_WHITELIST_UI_MSG).sendToTarget(); + } + + void pushTempWhitelist() { + final int N; + final PendingTempWhitelist[] list; + + // First copy out the pending changes... we need to leave them in the map for now, + // in case someone needs to check what is coming up while we don't have the lock held. + synchronized(this) { + N = mPendingTempWhitelist.size(); + list = new PendingTempWhitelist[N]; + for (int i = 0; i < N; i++) { + list[i] = mPendingTempWhitelist.valueAt(i); + } + } + + // Now safely dispatch changes to device idle controller. + for (int i = 0; i < N; i++) { + PendingTempWhitelist ptw = list[i]; + mLocalDeviceIdleController.addPowerSaveTempWhitelistAppDirect(ptw.targetUid, + ptw.duration, true, ptw.tag); + } + + // And now we can safely remove them from the map. + synchronized(this) { + for (int i = 0; i < N; i++) { + PendingTempWhitelist ptw = list[i]; + int index = mPendingTempWhitelist.indexOfKey(ptw.targetUid); + if (index >= 0 && mPendingTempWhitelist.valueAt(index) == ptw) { + mPendingTempWhitelist.removeAt(index); + } + } + } + } + final void setAppIdTempWhitelistStateLocked(int appId, boolean onWhitelist) { boolean changed = false; for (int i=mActiveUids.size()-1; i>=0; i--) { @@ -22714,6 +22789,15 @@ public class ActivityManagerService extends IActivityManager.Stub } } + final void setUidTempWhitelistStateLocked(int uid, boolean onWhitelist) { + boolean changed = false; + final UidRecord uidRec = mActiveUids.get(uid); + if (uidRec != null && uidRec.curWhitelist != onWhitelist) { + uidRec.curWhitelist = onWhitelist; + updateOomAdjLocked(); + } + } + final void trimApplications() { synchronized (this) { int i; diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 0fcf3e66debe..b6bfb00d3815 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -524,7 +524,7 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println("Starting service: " + intent); pw.flush(); ComponentName cn = mInterface.startService(null, intent, intent.getType(), - -1, null, asForeground, SHELL_PACKAGE_NAME, mUserId); + asForeground, SHELL_PACKAGE_NAME, mUserId); if (cn == null) { err.println("Error: Not found; no service started."); return -1; diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java index 28817878373b..494aaa766b94 100644 --- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java @@ -314,7 +314,8 @@ class ActivityMetricsLogger { builder.setPackageName(info.launchedActivity.packageName); builder.setType(type); builder.addTaggedData(FIELD_CLASS_NAME, info.launchedActivity.info.name); - if (info.launchedActivity.launchedFromPackage != null) { + final boolean isInstantApp = info.launchedActivity.info.applicationInfo.isInstantApp(); + if (isInstantApp && info.launchedActivity.launchedFromPackage != null) { builder.addTaggedData(APP_TRANSITION_CALLING_PACKAGE_NAME, info.launchedActivity.launchedFromPackage); } @@ -323,8 +324,7 @@ class ActivityMetricsLogger { info.launchedActivity.info.launchToken); info.launchedActivity.info.launchToken = null; } - builder.addTaggedData(APP_TRANSITION_IS_EPHEMERAL, - info.launchedActivity.info.applicationInfo.isInstantApp() ? 1 : 0); + builder.addTaggedData(APP_TRANSITION_IS_EPHEMERAL, isInstantApp ? 1 : 0); builder.addTaggedData(APP_TRANSITION_DEVICE_UPTIME_SECONDS, mCurrentTransitionDeviceUptime); builder.addTaggedData(APP_TRANSITION_DELAY_MS, mCurrentTransitionDelayMs); diff --git a/services/core/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java index 02ec07561f4f..c9c1d005a85a 100644 --- a/services/core/java/com/android/server/am/AppErrorDialog.java +++ b/services/core/java/com/android/server/am/AppErrorDialog.java @@ -148,18 +148,7 @@ final class AppErrorDialog extends BaseErrorDialog implements View.OnClickListen private final Handler mHandler = new Handler() { public void handleMessage(Message msg) { - final int result = msg.what; - - synchronized (mService) { - if (mProc != null && mProc.crashDialog == AppErrorDialog.this) { - mProc.crashDialog = null; - } - } - mResult.set(result); - - // Make sure we don't have time timeout still hanging around. - removeMessages(TIMEOUT); - + setResult(msg.what); dismiss(); } }; @@ -168,11 +157,23 @@ final class AppErrorDialog extends BaseErrorDialog implements View.OnClickListen public void dismiss() { if (!mResult.mHasResult) { // We are dismissing and the result has not been set...go ahead and set. - mResult.set(FORCE_QUIT); + setResult(FORCE_QUIT); } super.dismiss(); } + private void setResult(int result) { + synchronized (mService) { + if (mProc != null && mProc.crashDialog == AppErrorDialog.this) { + mProc.crashDialog = null; + } + } + mResult.set(result); + + // Make sure we don't have time timeout still hanging around. + mHandler.removeMessages(TIMEOUT); + } + @Override public void onClick(View v) { switch (v.getId()) { diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index baa71d708caa..349180fd28a9 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -155,8 +155,6 @@ public final class BroadcastQueue { static final int BROADCAST_INTENT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG; static final int BROADCAST_TIMEOUT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 1; - static final int SCHEDULE_TEMP_WHITELIST_MSG - = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 2; final BroadcastHandler mHandler; @@ -178,13 +176,6 @@ public final class BroadcastQueue { broadcastTimeoutLocked(true); } } break; - case SCHEDULE_TEMP_WHITELIST_MSG: { - DeviceIdleController.LocalService dic = mService.mLocalDeviceIdleController; - if (dic != null) { - dic.addPowerSaveTempWhitelistAppDirect(UserHandle.getAppId(msg.arg1), - msg.arg2, true, (String)msg.obj); - } - } break; } } } @@ -789,12 +780,11 @@ public final class BroadcastQueue { if (r.intent.getAction() != null) { b.append(r.intent.getAction()); } else if (r.intent.getComponent() != null) { - b.append(r.intent.getComponent().flattenToShortString()); + r.intent.getComponent().appendShortString(b); } else if (r.intent.getData() != null) { b.append(r.intent.getData()); } - mHandler.obtainMessage(SCHEDULE_TEMP_WHITELIST_MSG, uid, (int)duration, b.toString()) - .sendToTarget(); + mService.tempWhitelistUidLocked(uid, duration, b.toString()); } /** diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java index c697f2876c65..a580d4bdde5e 100644 --- a/services/core/java/com/android/server/am/PendingIntentRecord.java +++ b/services/core/java/com/android/server/am/PendingIntentRecord.java @@ -237,14 +237,6 @@ final class PendingIntentRecord extends IIntentSender.Stub { if (intent != null) intent.setDefusable(true); if (options != null) options.setDefusable(true); - if (whitelistDuration > 0 && !canceled) { - // Must call before acquiring the lock. It's possible the method return before sending - // the intent due to some validations inside the lock, in which case the UID shouldn't - // be whitelisted, but since the whitelist is temporary, that would be ok. - owner.tempWhitelistAppForPowerSave(Binder.getCallingPid(), Binder.getCallingUid(), uid, - whitelistDuration); - } - synchronized (owner) { final ActivityContainer activityContainer = (ActivityContainer)container; if (activityContainer != null && activityContainer.mParentActivity != null && @@ -279,6 +271,22 @@ final class PendingIntentRecord extends IIntentSender.Stub { resolvedType = key.requestResolvedType; } + if (whitelistDuration > 0) { + StringBuilder tag = new StringBuilder(64); + tag.append("pendingintent:"); + UserHandle.formatUid(tag, Binder.getCallingUid()); + tag.append(":"); + if (finalIntent.getAction() != null) { + tag.append(finalIntent.getAction()); + } else if (finalIntent.getComponent() != null) { + finalIntent.getComponent().appendShortString(tag); + } else if (finalIntent.getData() != null) { + tag.append(finalIntent.getData()); + } + owner.tempWhitelistForPendingIntentLocked(Binder.getCallingPid(), + Binder.getCallingUid(), uid, whitelistDuration, tag.toString()); + } + final long origId = Binder.clearCallingIdentity(); boolean sendFinish = finishedReceiver != null; diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 268724283351..e7617f5f5c7b 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 @@ public class AudioService extends IAudioService.Stub 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 @@ public class AudioService extends IAudioService.Stub } 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 @@ public class AudioService extends IAudioService.Stub 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 000000000000..e413d8d1d8c0 --- /dev/null +++ b/services/core/java/com/android/server/job/GrantedUriPermissions.java @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.job; + +import android.app.IActivityManager; +import android.content.ClipData; +import android.content.ContentProvider; +import android.content.Intent; +import android.net.Uri; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.UserHandle; +import android.util.Slog; + +import java.io.PrintWriter; +import java.util.ArrayList; + +public class GrantedUriPermissions { + private final int mGrantFlags; + private final int mSourceUserId; + private final String mTag; + private final IBinder mPermissionOwner; + private final ArrayList<Uri> mUris = new ArrayList<>(); + + private GrantedUriPermissions(IActivityManager am, int grantFlags, int uid, String tag) + throws RemoteException { + mGrantFlags = grantFlags; + mSourceUserId = UserHandle.getUserId(uid); + mTag = tag; + mPermissionOwner = am.newUriPermissionOwner("job: " + tag); + } + + public void revoke(IActivityManager am) { + for (int i = mUris.size()-1; i >= 0; i--) { + try { + am.revokeUriPermissionFromOwner(mPermissionOwner, mUris.get(i), + mGrantFlags, mSourceUserId); + } catch (RemoteException e) { + } + } + mUris.clear(); + } + + public static boolean checkGrantFlags(int grantFlags) { + return (grantFlags & (Intent.FLAG_GRANT_WRITE_URI_PERMISSION + |Intent.FLAG_GRANT_READ_URI_PERMISSION)) != 0; + } + + public static GrantedUriPermissions createFromIntent(IActivityManager am, Intent intent, + int sourceUid, String targetPackage, int targetUserId, String tag) { + int grantFlags = intent.getFlags(); + if (!checkGrantFlags(grantFlags)) { + return null; + } + + GrantedUriPermissions perms = null; + + Uri data = intent.getData(); + if (data != null) { + perms = grantUri(am, data, sourceUid, targetPackage, targetUserId, grantFlags, tag, + perms); + } + + ClipData clip = intent.getClipData(); + if (clip != null) { + perms = grantClip(am, clip, sourceUid, targetPackage, targetUserId, grantFlags, tag, + perms); + } + + return perms; + } + + public static GrantedUriPermissions createFromClip(IActivityManager am, ClipData clip, + int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag) { + if (!checkGrantFlags(grantFlags)) { + return null; + } + GrantedUriPermissions perms = null; + if (clip != null) { + perms = grantClip(am, clip, sourceUid, targetPackage, targetUserId, grantFlags, + tag, perms); + } + return perms; + } + + private static GrantedUriPermissions grantClip(IActivityManager am, ClipData clip, + int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag, + GrantedUriPermissions curPerms) { + final int N = clip.getItemCount(); + for (int i = 0; i < N; i++) { + curPerms = grantItem(am, clip.getItemAt(i), sourceUid, targetPackage, targetUserId, + grantFlags, tag, curPerms); + } + return curPerms; + } + + private static GrantedUriPermissions grantUri(IActivityManager am, Uri uri, + int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag, + GrantedUriPermissions curPerms) { + try { + int sourceUserId = ContentProvider.getUserIdFromUri(uri, + UserHandle.getUserId(sourceUid)); + uri = ContentProvider.getUriWithoutUserId(uri); + if (curPerms == null) { + curPerms = new GrantedUriPermissions(am, grantFlags, sourceUid, tag); + } + am.grantUriPermissionFromOwner(curPerms.mPermissionOwner, sourceUid, targetPackage, + uri, grantFlags, sourceUserId, targetUserId); + curPerms.mUris.add(uri); + } catch (RemoteException e) { + Slog.e("JobScheduler", "AM dead"); + } + return curPerms; + } + + private static GrantedUriPermissions grantItem(IActivityManager am, ClipData.Item item, + int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag, + GrantedUriPermissions curPerms) { + if (item.getUri() != null) { + curPerms = grantUri(am, item.getUri(), sourceUid, targetPackage, targetUserId, + grantFlags, tag, curPerms); + } + Intent intent = item.getIntent(); + if (intent != null && intent.getData() != null) { + curPerms = grantUri(am, intent.getData(), sourceUid, targetPackage, targetUserId, + grantFlags, tag, curPerms); + } + return curPerms; + } + + // Dumpsys infrastructure + public void dump(PrintWriter pw, String prefix) { + pw.print(prefix); pw.print("mGrantFlags=0x"); pw.print(Integer.toHexString(mGrantFlags)); + pw.print(" mSourceUserId="); pw.println(mSourceUserId); + pw.print(prefix); pw.print("mTag="); pw.println(mTag); + pw.print(prefix); pw.print("mPermissionOwner="); pw.println(mPermissionOwner); + for (int i = 0; i < mUris.size(); i++) { + pw.print(prefix); pw.print("#"); pw.print(i); pw.print(": "); + pw.println(mUris.get(i)); + } + } +} diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index d01de3c9157d..c8bfa345af10 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -601,7 +601,7 @@ public final class JobSchedulerService extends com.android.server.SystemService // Fast path: we are adding work to an existing job, and the JobInfo is not // changing. We can just directly enqueue this work in to the job. if (toCancel.getJob().equals(job)) { - toCancel.enqueueWorkLocked(work); + toCancel.enqueueWorkLocked(ActivityManager.getService(), work); return JobScheduler.RESULT_SUCCESS; } } @@ -625,7 +625,7 @@ public final class JobSchedulerService extends com.android.server.SystemService } if (work != null) { // If work has been supplied, enqueue it into the new job. - jobStatus.enqueueWorkLocked(work); + jobStatus.enqueueWorkLocked(ActivityManager.getService(), work); } startTrackingJobLocked(jobStatus, toCancel); mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget(); @@ -758,7 +758,7 @@ public final class JobSchedulerService extends com.android.server.SystemService final JobStatus executing = jsc.getRunningJob(); if (executing != null && (executing.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) == 0) { - jsc.cancelExecutingJob(JobParameters.REASON_DEVICE_IDLE); + jsc.cancelExecutingJobLocked(JobParameters.REASON_DEVICE_IDLE); } } } else { @@ -921,7 +921,7 @@ public final class JobSchedulerService extends com.android.server.SystemService private boolean stopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean writeBack) { // Deal with any remaining work items in the old job. - jobStatus.stopTrackingJobLocked(incomingJob); + jobStatus.stopTrackingJobLocked(ActivityManager.getService(), incomingJob); // Remove from store as well as controllers. final boolean removed = mJobs.remove(jobStatus, writeBack); @@ -939,7 +939,7 @@ public final class JobSchedulerService extends com.android.server.SystemService JobServiceContext jsc = mActiveServices.get(i); final JobStatus executing = jsc.getRunningJob(); if (executing != null && executing.matches(job.getUid(), job.getJobId())) { - jsc.cancelExecutingJob(reason); + jsc.cancelExecutingJobLocked(reason); return true; } } @@ -1071,9 +1071,16 @@ public final class JobSchedulerService extends com.android.server.SystemService if (DEBUG) { Slog.d(TAG, "Completed " + jobStatus + ", reschedule=" + needsReschedule); } + + // If the job wants to be rescheduled, we first need to make the next upcoming + // job so we can transfer any appropriate state over from the previous job when + // we stop it. + final JobStatus rescheduledJob = needsReschedule + ? getRescheduleJobForFailureLocked(jobStatus) : null; + // Do not write back immediately if this is a periodic job. The job may get lost if system // shuts down before it is added back. - if (!stopTrackingJobLocked(jobStatus, null, !jobStatus.getJob().isPeriodic())) { + if (!stopTrackingJobLocked(jobStatus, rescheduledJob, !jobStatus.getJob().isPeriodic())) { if (DEBUG) { Slog.d(TAG, "Could not find job to remove. Was job removed while executing?"); } @@ -1082,18 +1089,14 @@ public final class JobSchedulerService extends com.android.server.SystemService mHandler.obtainMessage(MSG_CHECK_JOB_GREEDY).sendToTarget(); return; } - // Note: there is a small window of time in here where, when rescheduling a job, - // we will stop monitoring its content providers. This should be fixed by stopping - // the old job after scheduling the new one, but since we have no lock held here - // that may cause ordering problems if the app removes jobStatus while in here. - if (needsReschedule) { - JobStatus rescheduled = getRescheduleJobForFailureLocked(jobStatus); + + if (rescheduledJob != null) { try { - rescheduled.prepareLocked(ActivityManager.getService()); + rescheduledJob.prepareLocked(ActivityManager.getService()); } catch (SecurityException e) { - Slog.w(TAG, "Unable to regrant job permissions for " + rescheduled); + Slog.w(TAG, "Unable to regrant job permissions for " + rescheduledJob); } - startTrackingJobLocked(rescheduled, jobStatus); + startTrackingJobLocked(rescheduledJob, jobStatus); } else if (jobStatus.getJob().isPeriodic()) { JobStatus rescheduledPeriodic = getRescheduleJobForPeriodic(jobStatus); try { @@ -1561,7 +1564,7 @@ public final class JobSchedulerService extends com.android.server.SystemService Slog.d(TAG, "preempting job: " + mActiveServices.get(i).getRunningJob()); } // preferredUid will be set to uid of currently running job. - mActiveServices.get(i).preemptExecutingJob(); + mActiveServices.get(i).preemptExecutingJobLocked(); preservePreferredUid = true; } else { final JobStatus pendingJob = contextIdToJobMap[i]; diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java index c7ef0e26971f..9144966da409 100644 --- a/services/core/java/com/android/server/job/JobServiceContext.java +++ b/services/core/java/com/android/server/job/JobServiceContext.java @@ -44,8 +44,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IBatteryStats; import com.android.server.job.controllers.JobStatus; -import java.util.concurrent.atomic.AtomicBoolean; - /** * Handles client binding and lifecycle of a job. Jobs execute one at a time on an instance of this * class. @@ -56,19 +54,15 @@ import java.util.concurrent.atomic.AtomicBoolean; * job lands, and again when it is complete. * - Cancelling is trickier, because there are also interactions from the client. It's possible * the {@link com.android.server.job.JobServiceContext.JobServiceHandler} tries to process a - * {@link #MSG_CANCEL} after the client has already finished. This is handled by having - * {@link com.android.server.job.JobServiceContext.JobServiceHandler#handleCancelH} check whether + * {@link #doCancelLocked(int)} after the client has already finished. This is handled by having + * {@link com.android.server.job.JobServiceContext.JobServiceHandler#handleCancelLocked} check whether * the context is still valid. - * To mitigate this, tearing down the context removes all messages from the handler, including any - * tardy {@link #MSG_CANCEL}s. Additionally, we avoid sending duplicate onStopJob() + * To mitigate this, we avoid sending duplicate onStopJob() * calls to the client after they've specified jobFinished(). */ public class JobServiceContext extends IJobCallback.Stub implements ServiceConnection { private static final boolean DEBUG = JobSchedulerService.DEBUG; private static final String TAG = "JobServiceContext"; - /** Define the maximum # of jobs allowed to run on a service at once. */ - private static final int defaultMaxActiveJobsPerService = - ActivityManager.isLowRamDeviceStatic() ? 1 : 3; /** Amount of time a job is allowed to execute for before being considered timed-out. */ private static final long EXECUTING_TIMESLICE_MILLIS = 10 * 60 * 1000; // 10mins. /** Amount of time the JobScheduler waits for the initial service launch+bind. */ @@ -90,14 +84,6 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne // Messages that result from interactions with the client service. /** System timed out waiting for a response. */ private static final int MSG_TIMEOUT = 0; - /** Received a callback from client. */ - private static final int MSG_CALLBACK = 1; - /** Run through list and start any ready jobs.*/ - private static final int MSG_SERVICE_BOUND = 2; - /** Cancel a job. */ - private static final int MSG_CANCEL = 3; - /** Shutdown the job. Used when the client crashes and we can't die gracefully.*/ - private static final int MSG_SHUTDOWN_EXECUTION = 4; public static final int NO_PREFERRED_UID = -1; @@ -115,7 +101,7 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne private JobParameters mParams; @VisibleForTesting int mVerb; - private AtomicBoolean mCancelled = new AtomicBoolean(); + private boolean mCancelled; /** * All the information maintained about the job currently being executed. @@ -245,14 +231,12 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne } /** Called externally when a job that was scheduled for execution should be cancelled. */ - void cancelExecutingJob(int reason) { - mCallbackHandler.obtainMessage(MSG_CANCEL, reason, 0 /* unused */).sendToTarget(); + void cancelExecutingJobLocked(int reason) { + doCancelLocked(reason); } - void preemptExecutingJob() { - Message m = mCallbackHandler.obtainMessage(MSG_CANCEL); - m.arg1 = JobParameters.REASON_PREEMPT; - m.sendToTarget(); + void preemptExecutingJobLocked() { + doCancelLocked(JobParameters.REASON_PREEMPT); } int getPreferredUid() { @@ -273,59 +257,54 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne @Override public void jobFinished(int jobId, boolean reschedule) { - if (!verifyCallingUid()) { - return; - } - mCallbackHandler.obtainMessage(MSG_CALLBACK, jobId, reschedule ? 1 : 0) - .sendToTarget(); + doCallback(reschedule); } @Override public void acknowledgeStopMessage(int jobId, boolean reschedule) { - if (!verifyCallingUid()) { - return; - } - mCallbackHandler.obtainMessage(MSG_CALLBACK, jobId, reschedule ? 1 : 0) - .sendToTarget(); + doCallback(reschedule); } @Override public void acknowledgeStartMessage(int jobId, boolean ongoing) { - if (!verifyCallingUid()) { - return; - } - mCallbackHandler.obtainMessage(MSG_CALLBACK, jobId, ongoing ? 1 : 0).sendToTarget(); + doCallback(ongoing); } @Override public JobWorkItem dequeueWork(int jobId) { - if (!verifyCallingUid()) { - throw new SecurityException("Bad calling uid: " + Binder.getCallingUid()); - } - JobWorkItem work = null; - boolean stillWorking = false; - synchronized (mLock) { - if (mRunningJob != null) { - work = mRunningJob.dequeueWorkLocked(); - stillWorking = mRunningJob.hasExecutingWorkLocked(); + final int callingUid = Binder.getCallingUid(); + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + if (!verifyCallingUidLocked(callingUid)) { + throw new SecurityException("Bad calling uid: " + callingUid); + } + + final JobWorkItem work = mRunningJob.dequeueWorkLocked(); + if (work == null && !mRunningJob.hasExecutingWorkLocked()) { + // This will finish the job. + doCallbackLocked(false); + } + return work; } + } finally { + Binder.restoreCallingIdentity(ident); } - if (work == null && !stillWorking) { - jobFinished(jobId, false); - } - return work; } @Override public boolean completeWork(int jobId, int workId) { - if (!verifyCallingUid()) { - throw new SecurityException("Bad calling uid: " + Binder.getCallingUid()); - } - synchronized (mLock) { - if (mRunningJob != null) { - return mRunningJob.completeWorkLocked(workId); + final int callingUid = Binder.getCallingUid(); + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + if (!verifyCallingUidLocked(callingUid)) { + throw new SecurityException("Bad calling uid: " + callingUid); + } + return mRunningJob.completeWorkLocked(ActivityManager.getService(), workId); } - return false; + } finally { + Binder.restoreCallingIdentity(ident); } } @@ -344,20 +323,20 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne // looper and at this point we can't get any binder callbacks from the client. Better // safe than sorry. runningJob = mRunningJob; - } - if (runningJob == null || !name.equals(runningJob.getServiceComponent())) { - mCallbackHandler.obtainMessage(MSG_SHUTDOWN_EXECUTION).sendToTarget(); - return; - } - this.service = IJobService.Stub.asInterface(service); - final PowerManager pm = - (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); - PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, - runningJob.getTag()); - wl.setWorkSource(new WorkSource(runningJob.getSourceUid())); - wl.setReferenceCounted(false); - wl.acquire(); - synchronized (mLock) { + + if (runningJob == null || !name.equals(runningJob.getServiceComponent())) { + closeAndCleanupJobLocked(true /* needsReschedule */); + return; + } + this.service = IJobService.Stub.asInterface(service); + final PowerManager pm = + (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, + runningJob.getTag()); + wl.setWorkSource(new WorkSource(runningJob.getSourceUid())); + wl.setReferenceCounted(false); + wl.acquire(); + // We use a new wakelock instance per job. In rare cases there is a race between // teardown following job completion/cancellation and new job service spin-up // such that if we simply assign mWakeLock to be the new instance, we orphan @@ -369,14 +348,16 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne mWakeLock.release(); } mWakeLock = wl; + doServiceBoundLocked(); } - mCallbackHandler.obtainMessage(MSG_SERVICE_BOUND).sendToTarget(); } /** If the client service crashes we reschedule this job and clean up. */ @Override public void onServiceDisconnected(ComponentName name) { - mCallbackHandler.obtainMessage(MSG_SHUTDOWN_EXECUTION).sendToTarget(); + synchronized (mLock) { + closeAndCleanupJobLocked(true /* needsReschedule */); + } } /** @@ -384,22 +365,18 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne * whether the client exercising the callback is the client we expect. * @return True if the binder calling is coming from the client we expect. */ - private boolean verifyCallingUid() { - synchronized (mLock) { - if (mRunningJob == null || Binder.getCallingUid() != mRunningJob.getUid()) { - if (DEBUG) { - Slog.d(TAG, "Stale callback received, ignoring."); - } - return false; + private boolean verifyCallingUidLocked(final int callingUid) { + if (mRunningJob == null || callingUid != mRunningJob.getUid()) { + if (DEBUG) { + Slog.d(TAG, "Stale callback received, ignoring."); } - return true; + return false; } + return true; } /** - * Handles the lifecycle of the JobService binding/callbacks, etc. The convention within this - * class is to append 'H' to each function name that can only be called on this handler. This - * isn't strictly necessary because all of these functions are private, but helps clarity. + * Scheduling of async messages (basically timeouts at this point). */ private class JobServiceHandler extends Handler { JobServiceHandler(Looper looper) { @@ -409,293 +386,277 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne @Override public void handleMessage(Message message) { switch (message.what) { - case MSG_SERVICE_BOUND: - doServiceBound(); - break; - case MSG_CALLBACK: - doCallback(message.arg2); - break; - case MSG_CANCEL: - doCancel(message.arg1); - break; case MSG_TIMEOUT: synchronized (mLock) { - handleOpTimeoutH(); + handleOpTimeoutLocked(); } break; - case MSG_SHUTDOWN_EXECUTION: - closeAndCleanupJobH(true /* needsReschedule */); - break; default: Slog.e(TAG, "Unrecognised message: " + message); } } + } - void doServiceBound() { + void doServiceBoundLocked() { + removeOpTimeOutLocked(); + handleServiceBoundLocked(); + } + + void doCallback(boolean reschedule) { + final int callingUid = Binder.getCallingUid(); + final long ident = Binder.clearCallingIdentity(); + try { synchronized (mLock) { - removeOpTimeOutLocked(); - handleServiceBoundH(); + if (!verifyCallingUidLocked(callingUid)) { + return; + } + doCallbackLocked(reschedule); } + } finally { + Binder.restoreCallingIdentity(ident); } + } - void doCallback(int arg2) { - synchronized (mLock) { - if (DEBUG) { - Slog.d(TAG, "MSG_CALLBACK of : " + mRunningJob - + " v:" + VERB_STRINGS[mVerb]); - } - removeOpTimeOutLocked(); + void doCallbackLocked(boolean reschedule) { + if (DEBUG) { + Slog.d(TAG, "doCallback of : " + mRunningJob + + " v:" + VERB_STRINGS[mVerb]); + } + removeOpTimeOutLocked(); - if (mVerb == VERB_STARTING) { - final boolean workOngoing = arg2 == 1; - handleStartedH(workOngoing); - } else if (mVerb == VERB_EXECUTING || - mVerb == VERB_STOPPING) { - final boolean reschedule = arg2 == 1; - handleFinishedH(reschedule); - } else { - if (DEBUG) { - Slog.d(TAG, "Unrecognised callback: " + mRunningJob); - } - } + if (mVerb == VERB_STARTING) { + handleStartedLocked(reschedule); + } else if (mVerb == VERB_EXECUTING || + mVerb == VERB_STOPPING) { + handleFinishedLocked(reschedule); + } else { + if (DEBUG) { + Slog.d(TAG, "Unrecognised callback: " + mRunningJob); } } + } - void doCancel(int arg1) { - synchronized (mLock) { - if (mVerb == VERB_FINISHED) { - if (DEBUG) { - Slog.d(TAG, - "Trying to process cancel for torn-down context, ignoring."); - } - return; - } - mParams.setStopReason(arg1); - if (arg1 == JobParameters.REASON_PREEMPT) { - mPreferredUid = mRunningJob != null ? mRunningJob.getUid() : - NO_PREFERRED_UID; - } - handleCancelH(); + void doCancelLocked(int arg1) { + if (mVerb == VERB_FINISHED) { + if (DEBUG) { + Slog.d(TAG, + "Trying to process cancel for torn-down context, ignoring."); } - + return; + } + mParams.setStopReason(arg1); + if (arg1 == JobParameters.REASON_PREEMPT) { + mPreferredUid = mRunningJob != null ? mRunningJob.getUid() : + NO_PREFERRED_UID; } + handleCancelLocked(); + } - /** Start the job on the service. */ - private void handleServiceBoundH() { + /** Start the job on the service. */ + private void handleServiceBoundLocked() { + if (DEBUG) { + Slog.d(TAG, "handleServiceBound for " + mRunningJob.toShortString()); + } + if (mVerb != VERB_BINDING) { + Slog.e(TAG, "Sending onStartJob for a job that isn't pending. " + + VERB_STRINGS[mVerb]); + closeAndCleanupJobLocked(false /* reschedule */); + return; + } + if (mCancelled) { if (DEBUG) { - Slog.d(TAG, "MSG_SERVICE_BOUND for " + mRunningJob.toShortString()); - } - if (mVerb != VERB_BINDING) { - Slog.e(TAG, "Sending onStartJob for a job that isn't pending. " - + VERB_STRINGS[mVerb]); - closeAndCleanupJobH(false /* reschedule */); - return; - } - if (mCancelled.get()) { - if (DEBUG) { - Slog.d(TAG, "Job cancelled while waiting for bind to complete. " - + mRunningJob); - } - closeAndCleanupJobH(true /* reschedule */); - return; - } - try { - mVerb = VERB_STARTING; - scheduleOpTimeOutLocked(); - service.startJob(mParams); - } catch (Exception e) { - // We catch 'Exception' because client-app malice or bugs might induce a wide - // range of possible exception-throw outcomes from startJob() and its handling - // of the client's ParcelableBundle extras. - Slog.e(TAG, "Error sending onStart message to '" + - mRunningJob.getServiceComponent().getShortClassName() + "' ", e); + Slog.d(TAG, "Job cancelled while waiting for bind to complete. " + + mRunningJob); } + closeAndCleanupJobLocked(true /* reschedule */); + return; } + try { + mVerb = VERB_STARTING; + scheduleOpTimeOutLocked(); + service.startJob(mParams); + } catch (Exception e) { + // We catch 'Exception' because client-app malice or bugs might induce a wide + // range of possible exception-throw outcomes from startJob() and its handling + // of the client's ParcelableBundle extras. + Slog.e(TAG, "Error sending onStart message to '" + + mRunningJob.getServiceComponent().getShortClassName() + "' ", e); + } + } - /** - * State behaviours. - * VERB_STARTING -> Successful start, change job to VERB_EXECUTING and post timeout. - * _PENDING -> Error - * _EXECUTING -> Error - * _STOPPING -> Error - */ - private void handleStartedH(boolean workOngoing) { - switch (mVerb) { - case VERB_STARTING: - mVerb = VERB_EXECUTING; - if (!workOngoing) { - // Job is finished already so fast-forward to handleFinished. - handleFinishedH(false); - return; - } - if (mCancelled.get()) { - if (DEBUG) { - Slog.d(TAG, "Job cancelled while waiting for onStartJob to complete."); - } - // Cancelled *while* waiting for acknowledgeStartMessage from client. - handleCancelH(); - return; + /** + * State behaviours. + * VERB_STARTING -> Successful start, change job to VERB_EXECUTING and post timeout. + * _PENDING -> Error + * _EXECUTING -> Error + * _STOPPING -> Error + */ + private void handleStartedLocked(boolean workOngoing) { + switch (mVerb) { + case VERB_STARTING: + mVerb = VERB_EXECUTING; + if (!workOngoing) { + // Job is finished already so fast-forward to handleFinished. + handleFinishedLocked(false); + return; + } + if (mCancelled) { + if (DEBUG) { + Slog.d(TAG, "Job cancelled while waiting for onStartJob to complete."); } - scheduleOpTimeOutLocked(); - break; - default: - Slog.e(TAG, "Handling started job but job wasn't starting! Was " - + VERB_STRINGS[mVerb] + "."); + // Cancelled *while* waiting for acknowledgeStartMessage from client. + handleCancelLocked(); return; - } + } + scheduleOpTimeOutLocked(); + break; + default: + Slog.e(TAG, "Handling started job but job wasn't starting! Was " + + VERB_STRINGS[mVerb] + "."); + return; } + } - /** - * VERB_EXECUTING -> Client called jobFinished(), clean up and notify done. - * _STOPPING -> Successful finish, clean up and notify done. - * _STARTING -> Error - * _PENDING -> Error - */ - private void handleFinishedH(boolean reschedule) { - switch (mVerb) { - case VERB_EXECUTING: - case VERB_STOPPING: - closeAndCleanupJobH(reschedule); - break; - default: - Slog.e(TAG, "Got an execution complete message for a job that wasn't being" + - "executed. Was " + VERB_STRINGS[mVerb] + "."); - } + /** + * VERB_EXECUTING -> Client called jobFinished(), clean up and notify done. + * _STOPPING -> Successful finish, clean up and notify done. + * _STARTING -> Error + * _PENDING -> Error + */ + private void handleFinishedLocked(boolean reschedule) { + switch (mVerb) { + case VERB_EXECUTING: + case VERB_STOPPING: + closeAndCleanupJobLocked(reschedule); + break; + default: + Slog.e(TAG, "Got an execution complete message for a job that wasn't being" + + "executed. Was " + VERB_STRINGS[mVerb] + "."); } + } - /** - * A job can be in various states when a cancel request comes in: - * VERB_BINDING -> Cancelled before bind completed. Mark as cancelled and wait for - * {@link #onServiceConnected(android.content.ComponentName, android.os.IBinder)} - * _STARTING -> Mark as cancelled and wait for - * {@link JobServiceContext#acknowledgeStartMessage(int, boolean)} - * _EXECUTING -> call {@link #sendStopMessageH}}, but only if there are no callbacks - * in the message queue. - * _ENDING -> No point in doing anything here, so we ignore. - */ - private void handleCancelH() { - if (JobSchedulerService.DEBUG) { - Slog.d(TAG, "Handling cancel for: " + mRunningJob.getJobId() + " " - + VERB_STRINGS[mVerb]); - } - switch (mVerb) { - case VERB_BINDING: - case VERB_STARTING: - mCancelled.set(true); - break; - case VERB_EXECUTING: - if (hasMessages(MSG_CALLBACK)) { - // If the client has called jobFinished, ignore this cancel. - return; - } - sendStopMessageH(); - break; - case VERB_STOPPING: - // Nada. - break; - default: - Slog.e(TAG, "Cancelling a job without a valid verb: " + mVerb); - break; - } + /** + * A job can be in various states when a cancel request comes in: + * VERB_BINDING -> Cancelled before bind completed. Mark as cancelled and wait for + * {@link #onServiceConnected(android.content.ComponentName, android.os.IBinder)} + * _STARTING -> Mark as cancelled and wait for + * {@link JobServiceContext#acknowledgeStartMessage(int, boolean)} + * _EXECUTING -> call {@link #sendStopMessageLocked}}, but only if there are no callbacks + * in the message queue. + * _ENDING -> No point in doing anything here, so we ignore. + */ + private void handleCancelLocked() { + if (JobSchedulerService.DEBUG) { + Slog.d(TAG, "Handling cancel for: " + mRunningJob.getJobId() + " " + + VERB_STRINGS[mVerb]); } + switch (mVerb) { + case VERB_BINDING: + case VERB_STARTING: + mCancelled = true; + break; + case VERB_EXECUTING: + sendStopMessageLocked(); + break; + case VERB_STOPPING: + // Nada. + break; + default: + Slog.e(TAG, "Cancelling a job without a valid verb: " + mVerb); + break; + } + } - /** Process MSG_TIMEOUT here. */ - private void handleOpTimeoutH() { - switch (mVerb) { - case VERB_BINDING: - Slog.e(TAG, "Time-out while trying to bind " + mRunningJob.toShortString() + - ", dropping."); - closeAndCleanupJobH(false /* needsReschedule */); - break; - case VERB_STARTING: - // Client unresponsive - wedged or failed to respond in time. We don't really - // know what happened so let's log it and notify the JobScheduler - // FINISHED/NO-RETRY. - Slog.e(TAG, "No response from client for onStartJob '" + - mRunningJob.toShortString()); - closeAndCleanupJobH(false /* needsReschedule */); - break; - case VERB_STOPPING: - // At least we got somewhere, so fail but ask the JobScheduler to reschedule. - Slog.e(TAG, "No response from client for onStopJob, '" + - mRunningJob.toShortString()); - closeAndCleanupJobH(true /* needsReschedule */); - break; - case VERB_EXECUTING: - // Not an error - client ran out of time. - Slog.i(TAG, "Client timed out while executing (no jobFinished received)." + - " sending onStop. " + mRunningJob.toShortString()); - mParams.setStopReason(JobParameters.REASON_TIMEOUT); - sendStopMessageH(); - break; - default: - Slog.e(TAG, "Handling timeout for an invalid job state: " + - mRunningJob.toShortString() + ", dropping."); - closeAndCleanupJobH(false /* needsReschedule */); - } + /** Process MSG_TIMEOUT here. */ + private void handleOpTimeoutLocked() { + switch (mVerb) { + case VERB_BINDING: + Slog.e(TAG, "Time-out while trying to bind " + mRunningJob.toShortString() + + ", dropping."); + closeAndCleanupJobLocked(false /* needsReschedule */); + break; + case VERB_STARTING: + // Client unresponsive - wedged or failed to respond in time. We don't really + // know what happened so let's log it and notify the JobScheduler + // FINISHED/NO-RETRY. + Slog.e(TAG, "No response from client for onStartJob '" + + mRunningJob.toShortString()); + closeAndCleanupJobLocked(false /* needsReschedule */); + break; + case VERB_STOPPING: + // At least we got somewhere, so fail but ask the JobScheduler to reschedule. + Slog.e(TAG, "No response from client for onStopJob, '" + + mRunningJob.toShortString()); + closeAndCleanupJobLocked(true /* needsReschedule */); + break; + case VERB_EXECUTING: + // Not an error - client ran out of time. + Slog.i(TAG, "Client timed out while executing (no jobFinished received)." + + " sending onStop. " + mRunningJob.toShortString()); + mParams.setStopReason(JobParameters.REASON_TIMEOUT); + sendStopMessageLocked(); + break; + default: + Slog.e(TAG, "Handling timeout for an invalid job state: " + + mRunningJob.toShortString() + ", dropping."); + closeAndCleanupJobLocked(false /* needsReschedule */); } + } - /** - * Already running, need to stop. Will switch {@link #mVerb} from VERB_EXECUTING -> - * VERB_STOPPING. - */ - private void sendStopMessageH() { - removeOpTimeOutLocked(); - if (mVerb != VERB_EXECUTING) { - Slog.e(TAG, "Sending onStopJob for a job that isn't started. " + mRunningJob); - closeAndCleanupJobH(false /* reschedule */); - return; - } - try { - mVerb = VERB_STOPPING; - scheduleOpTimeOutLocked(); - service.stopJob(mParams); - } catch (RemoteException e) { - Slog.e(TAG, "Error sending onStopJob to client.", e); - // The job's host app apparently crashed during the job, so we should reschedule. - closeAndCleanupJobH(true /* reschedule */); - } + /** + * Already running, need to stop. Will switch {@link #mVerb} from VERB_EXECUTING -> + * VERB_STOPPING. + */ + private void sendStopMessageLocked() { + removeOpTimeOutLocked(); + if (mVerb != VERB_EXECUTING) { + Slog.e(TAG, "Sending onStopJob for a job that isn't started. " + mRunningJob); + closeAndCleanupJobLocked(false /* reschedule */); + return; + } + try { + mVerb = VERB_STOPPING; + scheduleOpTimeOutLocked(); + service.stopJob(mParams); + } catch (RemoteException e) { + Slog.e(TAG, "Error sending onStopJob to client.", e); + // The job's host app apparently crashed during the job, so we should reschedule. + closeAndCleanupJobLocked(true /* reschedule */); } + } - /** - * The provided job has finished, either by calling - * {@link android.app.job.JobService#jobFinished(android.app.job.JobParameters, boolean)} - * or from acknowledging the stop message we sent. Either way, we're done tracking it and - * we want to clean up internally. - */ - private void closeAndCleanupJobH(boolean reschedule) { - final JobStatus completedJob; - synchronized (mLock) { - if (mVerb == VERB_FINISHED) { - return; - } - completedJob = mRunningJob; - mJobPackageTracker.noteInactive(completedJob); - try { - mBatteryStats.noteJobFinish(mRunningJob.getBatteryName(), - mRunningJob.getSourceUid()); - } catch (RemoteException e) { - // Whatever. - } - if (mWakeLock != null) { - mWakeLock.release(); - } - mContext.unbindService(JobServiceContext.this); - mWakeLock = null; - mRunningJob = null; - mParams = null; - mVerb = VERB_FINISHED; - mCancelled.set(false); - service = null; - mAvailable = true; - removeOpTimeOutLocked(); - removeMessages(MSG_CALLBACK); - removeMessages(MSG_SERVICE_BOUND); - removeMessages(MSG_CANCEL); - removeMessages(MSG_SHUTDOWN_EXECUTION); - mCompletedListener.onJobCompletedLocked(completedJob, reschedule); - } + /** + * The provided job has finished, either by calling + * {@link android.app.job.JobService#jobFinished(android.app.job.JobParameters, boolean)} + * or from acknowledging the stop message we sent. Either way, we're done tracking it and + * we want to clean up internally. + */ + private void closeAndCleanupJobLocked(boolean reschedule) { + final JobStatus completedJob; + if (mVerb == VERB_FINISHED) { + return; } + completedJob = mRunningJob; + mJobPackageTracker.noteInactive(completedJob); + try { + mBatteryStats.noteJobFinish(mRunningJob.getBatteryName(), + mRunningJob.getSourceUid()); + } catch (RemoteException e) { + // Whatever. + } + if (mWakeLock != null) { + mWakeLock.release(); + } + mContext.unbindService(JobServiceContext.this); + mWakeLock = null; + mRunningJob = null; + mParams = null; + mVerb = VERB_FINISHED; + mCancelled = false; + service = null; + mAvailable = true; + removeOpTimeOutLocked(); + mCompletedListener.onJobCompletedLocked(completedJob, reschedule); } /** diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java index e8cc078b7eb1..1ab66b9abb7f 100644 --- a/services/core/java/com/android/server/job/controllers/JobStatus.java +++ b/services/core/java/com/android/server/job/controllers/JobStatus.java @@ -26,7 +26,6 @@ import android.content.ContentProvider; import android.content.Intent; import android.net.Uri; import android.os.Binder; -import android.os.IBinder; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; @@ -35,6 +34,8 @@ import android.util.ArraySet; import android.util.Slog; import android.util.TimeUtils; +import com.android.server.job.GrantedUriPermissions; + import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; @@ -103,7 +104,7 @@ public final class JobStatus { final String tag; - private IBinder permissionOwner; + private GrantedUriPermissions uriPerms; private boolean prepared; /** @@ -284,12 +285,17 @@ public final class JobStatus { earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis); } - public void enqueueWorkLocked(JobWorkItem work) { + public void enqueueWorkLocked(IActivityManager am, JobWorkItem work) { if (pendingWork == null) { pendingWork = new ArrayList<>(); } work.setWorkId(nextPendingWorkId); nextPendingWorkId++; + if (work.getIntent() != null + && GrantedUriPermissions.checkGrantFlags(work.getIntent().getFlags())) { + work.setGrants(GrantedUriPermissions.createFromIntent(am, work.getIntent(), sourceUid, + sourcePackageName, sourceUserId, toShortString())); + } pendingWork.add(work); } @@ -311,12 +317,20 @@ public final class JobStatus { return executingWork != null && executingWork.size() > 0; } - public boolean completeWorkLocked(int workId) { + private static void ungrantWorkItem(IActivityManager am, JobWorkItem work) { + if (work.getGrants() != null) { + ((GrantedUriPermissions)work.getGrants()).revoke(am); + } + } + + public boolean completeWorkLocked(IActivityManager am, int workId) { if (executingWork != null) { final int N = executingWork.size(); for (int i = 0; i < N; i++) { - if (executingWork.get(i).getWorkId() == workId) { + JobWorkItem work = executingWork.get(i); + if (work.getWorkId() == workId) { executingWork.remove(i); + ungrantWorkItem(am, work); return true; } } @@ -324,15 +338,36 @@ public final class JobStatus { return false; } - public void stopTrackingJobLocked(JobStatus incomingJob) { + private static void ungrantWorkList(IActivityManager am, ArrayList<JobWorkItem> list) { + if (list != null) { + final int N = list.size(); + for (int i = 0; i < N; i++) { + ungrantWorkItem(am, list.get(i)); + } + } + } + + public void stopTrackingJobLocked(IActivityManager am, JobStatus incomingJob) { if (incomingJob != null) { - // We are replacing with a new job -- transfer the work! - incomingJob.pendingWork = pendingWork; + // We are replacing with a new job -- transfer the work! We do any executing + // work first, since that was originally at the front of the pending work. + if (executingWork != null && executingWork.size() > 0) { + incomingJob.pendingWork = executingWork; + } + if (incomingJob.pendingWork == null) { + incomingJob.pendingWork = pendingWork; + } else if (pendingWork != null && pendingWork.size() > 0) { + incomingJob.pendingWork.addAll(pendingWork); + } pendingWork = null; + executingWork = null; incomingJob.nextPendingWorkId = nextPendingWorkId; } else { // We are completely stopping the job... need to clean up work. - // XXX remove perms when that is impl. + ungrantWorkList(am, pendingWork); + pendingWork = null; + ungrantWorkList(am, executingWork); + executingWork = null; } } @@ -344,10 +379,8 @@ public final class JobStatus { prepared = true; final ClipData clip = job.getClipData(); if (clip != null) { - final int N = clip.getItemCount(); - for (int i = 0; i < N; i++) { - grantItemLocked(am, clip.getItemAt(i), sourceUid, sourcePackageName, sourceUserId); - } + uriPerms = GrantedUriPermissions.createFromClip(am, clip, sourceUid, sourcePackageName, + sourceUserId, job.getClipGrantFlags(), toShortString()); } } @@ -357,14 +390,9 @@ public final class JobStatus { return; } prepared = false; - if (permissionOwner != null) { - final ClipData clip = job.getClipData(); - if (clip != null) { - final int N = clip.getItemCount(); - for (int i = 0; i < N; i++) { - revokeItemLocked(am, clip.getItemAt(i)); - } - } + if (uriPerms != null) { + uriPerms.revoke(am); + uriPerms = null; } } @@ -372,57 +400,6 @@ public final class JobStatus { return prepared; } - private final void grantUriLocked(IActivityManager am, Uri uri, int sourceUid, - String targetPackage, int targetUserId) { - try { - int sourceUserId = ContentProvider.getUserIdFromUri(uri, - UserHandle.getUserId(sourceUid)); - uri = ContentProvider.getUriWithoutUserId(uri); - if (permissionOwner == null) { - permissionOwner = am.newUriPermissionOwner("job: " + toShortString()); - } - am.grantUriPermissionFromOwner(permissionOwner, sourceUid, targetPackage, - uri, job.getClipGrantFlags(), sourceUserId, targetUserId); - } catch (RemoteException e) { - Slog.e("JobScheduler", "AM dead"); - } - } - - private final void grantItemLocked(IActivityManager am, ClipData.Item item, int sourceUid, - String targetPackage, int targetUserId) { - if (item.getUri() != null) { - grantUriLocked(am, item.getUri(), sourceUid, targetPackage, targetUserId); - } - Intent intent = item.getIntent(); - if (intent != null && intent.getData() != null) { - grantUriLocked(am, intent.getData(), sourceUid, targetPackage, targetUserId); - } - } - - private final void revokeUriLocked(IActivityManager am, Uri uri) { - int userId = ContentProvider.getUserIdFromUri(uri, - UserHandle.getUserId(Binder.getCallingUid())); - long ident = Binder.clearCallingIdentity(); - try { - uri = ContentProvider.getUriWithoutUserId(uri); - am.revokeUriPermissionFromOwner(permissionOwner, uri, - job.getClipGrantFlags(), userId); - } catch (RemoteException e) { - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - private final void revokeItemLocked(IActivityManager am, ClipData.Item item) { - if (item.getUri() != null) { - revokeUriLocked(am, item.getUri()); - } - Intent intent = item.getIntent(); - if (intent != null && intent.getData() != null) { - revokeUriLocked(am, intent.getData()); - } - } - public JobInfo getJob() { return job; } @@ -833,6 +810,15 @@ public final class JobStatus { } } + private void dumpJobWorkItem(PrintWriter pw, String prefix, JobWorkItem work, int index) { + pw.print(prefix); pw.print(" #"); pw.print(index); pw.print(": #"); + pw.print(work.getWorkId()); pw.print(" "); pw.println(work.getIntent()); + if (work.getGrants() != null) { + pw.print(prefix); pw.println(" URI grants:"); + ((GrantedUriPermissions)work.getGrants()).dump(pw, prefix + " "); + } + } + // Dumpsys infrastructure public void dump(PrintWriter pw, String prefix, boolean full) { pw.print(prefix); UserHandle.formatUid(pw, callingUid); @@ -898,6 +884,10 @@ public final class JobStatus { job.getClipData().toShortString(b); pw.println(b); } + if (uriPerms != null) { + pw.print(prefix); pw.println(" Granted URI permissions:"); + uriPerms.dump(pw, prefix + " "); + } if (job.getNetworkType() != JobInfo.NETWORK_TYPE_NONE) { pw.print(prefix); pw.print(" Network type: "); pw.println(job.getNetworkType()); } @@ -950,17 +940,13 @@ public final class JobStatus { if (pendingWork != null && pendingWork.size() > 0) { pw.print(prefix); pw.println("Pending work:"); for (int i = 0; i < pendingWork.size(); i++) { - JobWorkItem work = pendingWork.get(i); - pw.print(prefix); pw.print(" #"); pw.print(i); pw.print(": #"); - pw.print(work.getWorkId()); pw.print(" "); pw.println(work.getIntent()); + dumpJobWorkItem(pw, prefix, pendingWork.get(i), i); } } if (executingWork != null && executingWork.size() > 0) { pw.print(prefix); pw.println("Executing work:"); for (int i = 0; i < executingWork.size(); i++) { - JobWorkItem work = executingWork.get(i); - pw.print(prefix); pw.print(" #"); pw.print(i); pw.print(": #"); - pw.print(work.getWorkId()); pw.print(" "); pw.println(work.getIntent()); + dumpJobWorkItem(pw, prefix, executingWork.get(i), i); } } pw.print(prefix); pw.print("Earliest run time: "); diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index 53a8092fa558..ee348cf71c88 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -101,8 +101,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { private ParceledListSlice mQueue; private CharSequence mQueueTitle; private int mRatingType; - private int mRepeatMode; - private boolean mShuffleModeEnabled; // End TransportPerformer fields // Volume handling fields @@ -622,47 +620,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } } - private void pushRepeatModeUpdate() { - synchronized (mLock) { - if (mDestroyed) { - return; - } - for (int i = mControllerCallbackHolders.size() - 1; i >= 0; i--) { - ISessionControllerCallbackHolder holder = mControllerCallbackHolders.get(i); - try { - holder.mCallback.onRepeatModeChanged(mRepeatMode); - } catch (DeadObjectException e) { - mControllerCallbackHolders.remove(i); - logCallbackException("Removed dead callback in pushRepeatModeUpdate", - holder, e); - } catch (RemoteException e) { - logCallbackException("unexpected exception in pushRepeatModeUpdate", holder, e); - } - } - } - } - - private void pushShuffleModeUpdate() { - synchronized (mLock) { - if (mDestroyed) { - return; - } - for (int i = mControllerCallbackHolders.size() - 1; i >= 0; i--) { - ISessionControllerCallbackHolder holder = mControllerCallbackHolders.get(i); - try { - holder.mCallback.onShuffleModeChanged(mShuffleModeEnabled); - } catch (DeadObjectException e) { - mControllerCallbackHolders.remove(i); - logCallbackException("Removed dead callback in pushShuffleModeUpdate", - holder, e); - } catch (RemoteException e) { - logCallbackException("unexpected exception in pushShuffleModeUpdate", - holder, e); - } - } - } - } - private void pushSessionDestroyed() { synchronized (mLock) { // This is the only method that may be (and can only be) called @@ -887,30 +844,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } @Override - public void setRepeatMode(int repeatMode) { - boolean changed; - synchronized (mLock) { - changed = mRepeatMode != repeatMode; - mRepeatMode = repeatMode; - } - if (changed) { - mHandler.post(MessageHandler.MSG_UPDATE_REPEAT_MODE); - } - } - - @Override - public void setShuffleModeEnabled(boolean enabled) { - boolean changed; - synchronized (mLock) { - changed = mShuffleModeEnabled != enabled; - mShuffleModeEnabled = enabled; - } - if (changed) { - mHandler.post(MessageHandler.MSG_UPDATE_SHUFFLE_MODE); - } - } - - @Override public void setCurrentVolume(int volume) { mCurrentVolume = volume; mHandler.post(MessageHandler.MSG_UPDATE_VOLUME); @@ -1126,54 +1059,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } } - public void repeatMode(int repeatMode) { - try { - mCb.onRepeatMode(repeatMode); - } catch (RemoteException e) { - Slog.e(TAG, "Remote failure in repeatMode.", e); - } - } - - public void shuffleMode(boolean enabled) { - try { - mCb.onShuffleMode(enabled); - } catch (RemoteException e) { - Slog.e(TAG, "Remote failure in shuffleMode.", e); - } - } - - public void addQueueItem(MediaDescription description) { - try { - mCb.onAddQueueItem(description); - } catch (RemoteException e) { - Slog.e(TAG, "Remote failure in addQueueItem.", e); - } - } - - public void addQueueItemAt(MediaDescription description, int index) { - try { - mCb.onAddQueueItemAt(description, index); - } catch (RemoteException e) { - Slog.e(TAG, "Remote failure in addQueueItemAt.", e); - } - } - - public void removeQueueItem(MediaDescription description) { - try { - mCb.onRemoveQueueItem(description); - } catch (RemoteException e) { - Slog.e(TAG, "Remote failure in removeQueueItem.", e); - } - } - - public void removeQueueItemAt(int index) { - try { - mCb.onRemoveQueueItemAt(index); - } catch (RemoteException e) { - Slog.e(TAG, "Remote failure in removeQueueItem.", e); - } - } - public void adjustVolume(int direction) { try { mCb.onAdjustVolume(direction); @@ -1410,25 +1295,13 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } @Override - public void repeatMode(int repeatMode) { - updateCallingPackage(); - mSessionCb.repeatMode(repeatMode); - } - - @Override - public void shuffleMode(boolean enabled) throws RemoteException { - updateCallingPackage(); - mSessionCb.shuffleMode(enabled); - } - - - @Override public void sendCustomAction(String action, Bundle args) throws RemoteException { updateCallingPackage(); mSessionCb.sendCustomAction(action, args); } + @Override public MediaMetadata getMetadata() { synchronized (mLock) { @@ -1449,30 +1322,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } @Override - public void addQueueItem(MediaDescription description) { - updateCallingPackage(); - mSessionCb.addQueueItem(description); - } - - @Override - public void addQueueItemAt(MediaDescription description, int index) { - updateCallingPackage(); - mSessionCb.addQueueItemAt(description, index); - } - - @Override - public void removeQueueItem(MediaDescription description) { - updateCallingPackage(); - mSessionCb.removeQueueItem(description); - } - - @Override - public void removeQueueItemAt(int index) { - updateCallingPackage(); - mSessionCb.removeQueueItemAt(index); - } - - @Override public CharSequence getQueueTitle() { return mQueueTitle; } @@ -1490,16 +1339,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } @Override - public int getRepeatMode() { - return mRepeatMode; - } - - @Override - public boolean isShuffleModeEnabled() { - return mShuffleModeEnabled; - } - - @Override public boolean isTransportControlEnabled() { return MediaSessionRecord.this.isTransportControlEnabled(); } @@ -1524,9 +1363,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { private static final int MSG_SEND_EVENT = 6; private static final int MSG_UPDATE_SESSION_STATE = 7; private static final int MSG_UPDATE_VOLUME = 8; - private static final int MSG_UPDATE_REPEAT_MODE = 9; - private static final int MSG_UPDATE_SHUFFLE_MODE = 10; - private static final int MSG_DESTROYED = 11; + private static final int MSG_DESTROYED = 9; public MessageHandler(Looper looper) { super(looper); @@ -1558,12 +1395,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { case MSG_UPDATE_VOLUME: pushVolumeUpdate(); break; - case MSG_UPDATE_REPEAT_MODE: - pushRepeatModeUpdate(); - break; - case MSG_UPDATE_SHUFFLE_MODE: - pushShuffleModeUpdate(); - break; case MSG_DESTROYED: pushSessionDestroyed(); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 95b4903e49d7..312c310428a5 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -13202,7 +13202,7 @@ public class PackageManagerService extends IPackageManager.Stub if (dcsUid > 0) { am.backgroundWhitelistUid(dcsUid); } - am.startService(null, intent, null, -1, null, false, mContext.getOpPackageName(), + am.startService(null, intent, null, false, mContext.getOpPackageName(), UserHandle.USER_SYSTEM); } catch (RemoteException e) { } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 4f29bfa2829e..bcb4121a6d2f 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -222,9 +222,10 @@ import android.view.accessibility.AccessibilityManager; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.AnimationUtils; +import android.view.inputmethod.InputMethodManagerInternal; import android.widget.ImageView; - import com.android.internal.R; +import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.internal.policy.IKeyguardDismissCallback; import com.android.internal.policy.IShortcutService; @@ -279,6 +280,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2; static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3; static final int SHORT_PRESS_POWER_GO_HOME = 4; + static final int SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME = 5; static final int LONG_PRESS_POWER_NOTHING = 0; static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1; @@ -407,6 +409,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { PowerManager mPowerManager; ActivityManagerInternal mActivityManagerInternal; InputManagerInternal mInputManagerInternal; + InputMethodManagerInternal mInputMethodManagerInternal; DreamManagerInternal mDreamManagerInternal; PowerManagerInternal mPowerManagerInternal; IStatusBarService mStatusBarService; @@ -494,6 +497,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { WindowState mLastInputMethodWindow = null; WindowState mLastInputMethodTargetWindow = null; + @GuardedBy("mLock") + private boolean mDismissImeOnBackKeyPressed; + // FIXME This state is shared between the input reader and handler thread. // Technically it's broken and buggy but it has been like this for many years // and we have not yet seen any problems. Someday we'll rewrite this logic @@ -1396,6 +1402,27 @@ public class PhoneWindowManager implements WindowManagerPolicy { case SHORT_PRESS_POWER_GO_HOME: launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/); break; + case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME: { + final boolean dismissImeOnBackKeyPressed; + // We can be here on both the main thread (via mHandler) and native callback + // thread (from interceptPowerKeyUp via WindowManagerCallbacks). + synchronized (mLock) { + dismissImeOnBackKeyPressed = mDismissImeOnBackKeyPressed; + } + if (dismissImeOnBackKeyPressed) { + if (mInputMethodManagerInternal == null) { + mInputMethodManagerInternal = + LocalServices.getService(InputMethodManagerInternal.class); + } + if (mInputMethodManagerInternal != null) { + mInputMethodManagerInternal.hideCurrentInputMethod(); + } + } else { + launchHomeFromHotKey(true /* awakenFromDreams */, + false /*respectKeyguard*/); + } + break; + } } } } @@ -7955,6 +7982,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { } @Override + public void setDismissImeOnBackKeyPressed(boolean newValue) { + synchronized (mLock) { + mDismissImeOnBackKeyPressed = newValue; + } + } + + @Override public int getInputMethodWindowVisibleHeightLw() { return mDockBottom - mCurBottom; } @@ -8170,6 +8204,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(prefix); pw.print("mLastInputMethodTargetWindow="); pw.println(mLastInputMethodTargetWindow); } + pw.print(prefix); pw.print("mDismissImeOnBackKeyPressed="); + pw.println(mDismissImeOnBackKeyPressed); if (mStatusBar != null) { pw.print(prefix); pw.print("mStatusBar="); pw.print(mStatusBar); pw.print(" isStatusBarKeyguard="); diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java index 16848780fe47..82416ec513c4 100644 --- a/services/core/java/com/android/server/wm/PinnedStackController.java +++ b/services/core/java/com/android/server/wm/PinnedStackController.java @@ -26,7 +26,6 @@ import android.app.RemoteAction; import android.content.pm.ParceledListSlice; import android.content.res.Resources; import android.graphics.Point; -import android.graphics.PointF; import android.graphics.Rect; import android.os.Handler; import android.os.IBinder; @@ -123,6 +122,13 @@ class PinnedStackController { mSnapAlgorithm.setMinimized(isMinimized); }); } + + @Override + public int getDisplayRotation() { + synchronized (mService.mWindowMap) { + return mDisplayInfo.rotation; + } + } } /** @@ -221,22 +227,26 @@ class PinnedStackController { * @return the size of the PIP based on the given {@param aspectRatio}. */ Size getSize(float aspectRatio) { - return mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, mMinSize, - mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); + synchronized (mService.mWindowMap) { + return mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, mMinSize, + mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); + } } /** * @return the default bounds to show the PIP when there is no active PIP. */ Rect getDefaultBounds() { - final Rect insetBounds = new Rect(); - getInsetBounds(insetBounds); - - final Rect defaultBounds = new Rect(); - final Size size = getSize(mDefaultAspectRatio); - Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds, - 0, mIsImeShowing ? mImeHeight : 0, defaultBounds); - return defaultBounds; + synchronized (mService.mWindowMap) { + final Rect insetBounds = new Rect(); + getInsetBounds(insetBounds); + + final Rect defaultBounds = new Rect(); + final Size size = getSize(mDefaultAspectRatio); + Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds, + 0, mIsImeShowing ? mImeHeight : 0, defaultBounds); + return defaultBounds; + } } /** @@ -254,42 +264,44 @@ class PinnedStackController { * new orientation of the device if necessary. */ boolean onTaskStackBoundsChanged(Rect targetBounds, Rect outBounds) { - final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo(); - if (mDisplayInfo.equals(displayInfo)) { - // We are already in the right orientation, ignore - outBounds.setEmpty(); - return false; - } else if (targetBounds.isEmpty()) { - // The stack is null, we are just initializing the stack, so just store the display info - // and ignore + synchronized (mService.mWindowMap) { + final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo(); + if (mDisplayInfo.equals(displayInfo)) { + // We are already in the right orientation, ignore + outBounds.setEmpty(); + return false; + } else if (targetBounds.isEmpty()) { + // The stack is null, we are just initializing the stack, so just store the display + // info and ignore + mDisplayInfo.copyFrom(displayInfo); + outBounds.setEmpty(); + return false; + } + + mTmpRect.set(targetBounds); + final Rect postChangeStackBounds = mTmpRect; + + // Calculate the snap fraction of the current stack along the old movement bounds + final Rect preChangeMovementBounds = getMovementBounds(postChangeStackBounds); + final float snapFraction = mSnapAlgorithm.getSnapFraction(postChangeStackBounds, + preChangeMovementBounds); mDisplayInfo.copyFrom(displayInfo); - outBounds.setEmpty(); - return false; - } - mTmpRect.set(targetBounds); - final Rect postChangeStackBounds = mTmpRect; - - // Calculate the snap fraction of the current stack along the old movement bounds - final Rect preChangeMovementBounds = getMovementBounds(postChangeStackBounds); - final float snapFraction = mSnapAlgorithm.getSnapFraction(postChangeStackBounds, - preChangeMovementBounds); - mDisplayInfo.copyFrom(displayInfo); - - // Calculate the stack bounds in the new orientation to the same same fraction along the - // rotated movement bounds. - final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds, - false /* adjustForIme */); - mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds, - snapFraction); - if (mIsMinimized) { - applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds); - } + // Calculate the stack bounds in the new orientation to the same same fraction along the + // rotated movement bounds. + final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds, + false /* adjustForIme */); + mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds, + snapFraction); + if (mIsMinimized) { + applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds); + } - notifyMovementBoundsChanged(false /* fromImeAdjustment */); + notifyMovementBoundsChanged(false /* fromImeAdjustment */); - outBounds.set(postChangeStackBounds); - return true; + outBounds.set(postChangeStackBounds); + return true; + } } /** @@ -378,25 +390,27 @@ class PinnedStackController { * Notifies listeners that the PIP movement bounds have changed. */ private void notifyMovementBoundsChanged(boolean fromImeAdjustement) { - if (mPinnedStackListener != null) { - try { - final Rect insetBounds = new Rect(); - getInsetBounds(insetBounds); - final Rect normalBounds = getDefaultBounds(); - if (isValidPictureInPictureAspectRatio(mAspectRatio)) { - transformBoundsToAspectRatio(normalBounds, mAspectRatio); - } - final Rect animatingBounds = mTmpAnimatingBoundsRect; - final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID); - if (pinnedStack != null) { - pinnedStack.getAnimationOrCurrentBounds(animatingBounds); - } else { - animatingBounds.set(normalBounds); + synchronized (mService.mWindowMap) { + if (mPinnedStackListener != null) { + try { + final Rect insetBounds = new Rect(); + getInsetBounds(insetBounds); + final Rect normalBounds = getDefaultBounds(); + if (isValidPictureInPictureAspectRatio(mAspectRatio)) { + transformBoundsToAspectRatio(normalBounds, mAspectRatio); + } + final Rect animatingBounds = mTmpAnimatingBoundsRect; + final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID); + if (pinnedStack != null) { + pinnedStack.getAnimationOrCurrentBounds(animatingBounds); + } else { + animatingBounds.set(normalBounds); + } + mPinnedStackListener.onMovementBoundsChanged(insetBounds, normalBounds, + animatingBounds, fromImeAdjustement, mDisplayInfo.rotation); + } catch (RemoteException e) { + Slog.e(TAG_WM, "Error delivering actions changed event.", e); } - mPinnedStackListener.onMovementBoundsChanged(insetBounds, normalBounds, - animatingBounds, fromImeAdjustement); - } catch (RemoteException e) { - Slog.e(TAG_WM, "Error delivering actions changed event.", e); } } } @@ -405,11 +419,13 @@ class PinnedStackController { * @return the bounds on the screen that the PIP can be visible in. */ private void getInsetBounds(Rect outRect) { - mService.mPolicy.getStableInsetsLw(mDisplayInfo.rotation, mDisplayInfo.logicalWidth, - mDisplayInfo.logicalHeight, mTmpInsets); - outRect.set(mTmpInsets.left + mScreenEdgeInsets.x, mTmpInsets.top + mScreenEdgeInsets.y, - mDisplayInfo.logicalWidth - mTmpInsets.right - mScreenEdgeInsets.x, - mDisplayInfo.logicalHeight - mTmpInsets.bottom - mScreenEdgeInsets.y); + synchronized (mService.mWindowMap) { + mService.mPolicy.getStableInsetsLw(mDisplayInfo.rotation, mDisplayInfo.logicalWidth, + mDisplayInfo.logicalHeight, mTmpInsets); + outRect.set(mTmpInsets.left + mScreenEdgeInsets.x, mTmpInsets.top + mScreenEdgeInsets.y, + mDisplayInfo.logicalWidth - mTmpInsets.right - mScreenEdgeInsets.x, + mDisplayInfo.logicalHeight - mTmpInsets.bottom - mScreenEdgeInsets.y); + } } /** @@ -417,7 +433,9 @@ class PinnedStackController { * controller. */ private Rect getMovementBounds(Rect stackBounds) { - return getMovementBounds(stackBounds, true /* adjustForIme */); + synchronized (mService.mWindowMap) { + return getMovementBounds(stackBounds, true /* adjustForIme */); + } } /** @@ -425,23 +443,27 @@ class PinnedStackController { * controller. */ private Rect getMovementBounds(Rect stackBounds, boolean adjustForIme) { - final Rect movementBounds = new Rect(); - getInsetBounds(movementBounds); - - // Apply the movement bounds adjustments based on the current state - mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds, - (adjustForIme && mIsImeShowing) ? mImeHeight : 0); - return movementBounds; + synchronized (mService.mWindowMap) { + final Rect movementBounds = new Rect(); + getInsetBounds(movementBounds); + + // Apply the movement bounds adjustments based on the current state + mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds, + (adjustForIme && mIsImeShowing) ? mImeHeight : 0); + return movementBounds; + } } /** * Applies the minimized offsets to the given stack bounds. */ private void applyMinimizedOffset(Rect stackBounds, Rect movementBounds) { - mTmpDisplaySize.set(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); - mService.getStableInsetsLocked(mDisplayContent.getDisplayId(), mStableInsets); - mSnapAlgorithm.applyMinimizedOffset(stackBounds, movementBounds, mTmpDisplaySize, - mStableInsets); + synchronized (mService.mWindowMap) { + mTmpDisplaySize.set(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); + mService.getStableInsetsLocked(mDisplayContent.getDisplayId(), mStableInsets); + mSnapAlgorithm.applyMinimizedOffset(stackBounds, movementBounds, mTmpDisplaySize, + mStableInsets); + } } /** diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 0049585f5c52..252b4d4e0473 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -7267,13 +7267,16 @@ public class WindowManagerService extends IWindowManager.Stub @Override public void updateInputMethodWindowStatus(@NonNull IBinder imeToken, - boolean imeWindowVisible, @Nullable IBinder targetWindowToken) { + boolean imeWindowVisible, boolean dismissImeOnBackKeyPressed, + @Nullable IBinder targetWindowToken) { // TODO (b/34628091): Use this method to address the window animation issue. if (DEBUG_INPUT_METHOD) { Slog.w(TAG_WM, "updateInputMethodWindowStatus: imeToken=" + imeToken + + " dismissImeOnBackKeyPressed=" + dismissImeOnBackKeyPressed + " imeWindowVisible=" + imeWindowVisible + " targetWindowToken=" + targetWindowToken); } + mPolicy.setDismissImeOnBackKeyPressed(dismissImeOnBackKeyPressed); } @Override diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp index 86662b94302e..74ecd11d13f4 100644 --- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp @@ -68,12 +68,15 @@ static JavaVM* sJvm; using android::OK; using android::sp; +using android::wp; using android::status_t; using android::String16; using android::hardware::Return; using android::hardware::Void; using android::hardware::hidl_vec; +using android::hardware::hidl_death_recipient; +using android::hidl::base::V1_0::IBase; using android::hardware::gnss::V1_0::IAGnss; using android::hardware::gnss::V1_0::IAGnssCallback; @@ -97,7 +100,18 @@ using android::hardware::gnss::V1_0::IGnssNiCallback; using android::hardware::gnss::V1_0::IGnssXtra; using android::hardware::gnss::V1_0::IGnssXtraCallback; +struct GnssDeathRecipient : virtual public hidl_death_recipient +{ + // hidl_death_recipient interface + virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override { + // TODO(gomo): implement a better death recovery mechanism without + // crashing system server process as described in go//treble-gnss-death + LOG_ALWAYS_FATAL("Abort due to IGNSS hidl service failure," + " restarting system server"); + } +}; +sp<GnssDeathRecipient> gnssHalDeathRecipient = nullptr; sp<IGnss> gnssHal = nullptr; sp<IGnssXtra> gnssXtraIface = nullptr; sp<IAGnssRil> agnssRilIface = nullptr; @@ -1038,6 +1052,18 @@ static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, // TODO(b/31632518) gnssHal = IGnss::getService(); if (gnssHal != nullptr) { + gnssHalDeathRecipient = new GnssDeathRecipient(); + hardware::Return<bool> linked = gnssHal->linkToDeath( + gnssHalDeathRecipient, /*cookie*/ 0); + if (!linked.isOk()) { + ALOGE("Transaction error in linking to GnssHAL death: %s", + linked.description().c_str()); + } else if (!linked) { + ALOGW("Unable to link to GnssHal death notifications"); + } else { + ALOGD("Link to death notification successful"); + } + auto gnssXtra = gnssHal->getExtensionXtra(); if (!gnssXtra.isOk()) { ALOGD("Unable to get a handle to Xtra"); diff --git a/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java b/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java new file mode 100644 index 000000000000..243c1b379608 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.am; + +import android.content.Context; +import android.os.Handler; +import android.support.test.InstrumentationRegistry; +import android.support.test.annotation.UiThreadTest; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import com.android.server.AppOpsService; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; + +/** + * runtest -c com.android.server.am.AppErrorDialogTest frameworks-services + */ +@RunWith(AndroidJUnit4.class) +@SmallTest +public class AppErrorDialogTest { + + private Context mContext; + private ActivityManagerService mService; + + @Before + public void setUp() throws Exception { + mContext = InstrumentationRegistry.getTargetContext(); + mService = new ActivityManagerService(new ActivityManagerService.Injector() { + @Override + public AppOpsService getAppOpsService(File file, Handler handler) { + return null; + } + + @Override + public Handler getUiHandler(ActivityManagerService service) { + return null; + } + + @Override + public boolean isNetworkRestrictedForUid(int uid) { + return false; + } + }); + } + + @Test + @UiThreadTest + public void testCreateWorks() throws Exception { + AppErrorDialog.Data data = new AppErrorDialog.Data(); + data.proc = new ProcessRecord(null, mContext.getApplicationInfo(), "name", 12345); + data.result = new AppErrorResult(); + + AppErrorDialog dialog = new AppErrorDialog(mContext, mService, data); + + dialog.create(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java index eadece27087b..8f2f34ee77d9 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java @@ -71,17 +71,17 @@ public class PackageManagerServiceTest extends AndroidTestCase { "primaryCpuAbiString", "secondaryCpuAbiString", "cpuAbiOverrideString", 0, 0, 0, "parentPackageName", null, 0, null, null); - pri.removedUsers = new int[] {1, 2, 3, 4, 5}; - pri.populateUsers(pri.removedUsers, setting); + pri.populateUsers(new int[] {1, 2, 3, 4, 5}, setting); assertNotNull(pri.broadcastUsers); - assertEquals(pri.removedUsers.length, pri.broadcastUsers.length); + assertEquals(5, pri.broadcastUsers.length); // Exclude a user pri.broadcastUsers = null; - setting.setInstantApp(true, 4); - pri.populateUsers(pri.removedUsers, setting); + 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(pri.removedUsers.length - 1, pri.broadcastUsers.length); + assertEquals(5 - 1, pri.broadcastUsers.length); // TODO: test that sendApplicationHiddenForUser() actually fills in // broadcastUsers diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 397aa0020d13..3d51c4cd51ae 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -4393,7 +4393,7 @@ public class TelephonyManager { * Returns null if the query fails. * * - * <p>Requires that the caller has READ_PRIVILEGED_PHONE_STATE + * <p>Requires that the caller has READ_PHONE_STATE * * @return an array of forbidden PLMNs or null if not available */ @@ -4406,7 +4406,7 @@ public class TelephonyManager { * Returns null if the query fails. * * - * <p>Requires that the calling app has READ_PRIVILEGED_PHONE_STATE + * <p>Requires that the calling app has READ_PHONE_STATE * * @param subId subscription ID used for authentication * @param appType the icc application type, like {@link #APPTYPE_USIM} diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java index a8eb9862202d..b4e3a476425a 100644 --- a/test-runner/src/android/test/mock/MockContext.java +++ b/test-runner/src/android/test/mock/MockContext.java @@ -530,13 +530,6 @@ public class MockContext extends Context { throw new UnsupportedOperationException(); } - /** STOPSHIP remove when trial API is turned down */ - @Override - public ComponentName startServiceInForeground(Intent service, - int id, Notification notification) { - throw new UnsupportedOperationException(); - } - @Override public boolean stopService(Intent service) { throw new UnsupportedOperationException(); @@ -554,13 +547,6 @@ public class MockContext extends Context { throw new UnsupportedOperationException(); } - /** @hide STOPSHIP removed when trial API is turned down */ - @Override - public ComponentName startServiceInForegroundAsUser(Intent service, - int id, Notification notification, UserHandle user) { - throw new UnsupportedOperationException(); - } - /** @hide */ @Override public boolean stopServiceAsUser(Intent service, UserHandle user) { diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index 328fc0a1eaeb..1e77ac170028 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -1865,13 +1865,6 @@ public class BridgeContext extends Context { } @Override - public ComponentName startServiceInForeground(Intent service, - int id, Notification notification) { - // pass - return null; - } - - @Override public boolean stopService(Intent arg0) { // pass return false; @@ -1884,13 +1877,6 @@ public class BridgeContext extends Context { } @Override - public ComponentName startServiceInForegroundAsUser(Intent service, - int id, Notification notification, UserHandle user) { - // pass - return null; - } - - @Override public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) { // pass return false; |