Merge "Don't back up disabled apps" into oc-dev
diff --git a/api/current.txt b/api/current.txt
index 59367ee..0cc4361 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -211,6 +211,7 @@
ctor public R.attr();
field public static final int __removed1 = 16844099; // 0x1010543
field public static final int __removed2 = 16844104; // 0x1010548
+ field public static final int __removed3 = 16844116; // 0x1010554
field public static final int absListViewStyle = 16842858; // 0x101006a
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -313,7 +314,6 @@
field public static final int autoUrlDetect = 16843404; // 0x101028c
field public static final int autoVerify = 16844014; // 0x10104ee
field public static final int autofillHints = 16844121; // 0x1010559
- field public static final int autofillMode = 16844116; // 0x1010554
field public static final int background = 16842964; // 0x10100d4
field public static final int backgroundDimAmount = 16842802; // 0x1010032
field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -3615,6 +3615,7 @@
method public android.net.Uri getReferrer();
method public int getRequestedOrientation();
method public final android.view.SearchEvent getSearchEvent();
+ method public long getStartInitiatedTime();
method public int getTaskId();
method public final java.lang.CharSequence getTitle();
method public final int getTitleColor();
@@ -6091,6 +6092,17 @@
method public void onDetached();
}
+ public final class WallpaperColors implements android.os.Parcelable {
+ ctor public WallpaperColors(android.os.Parcel);
+ ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>);
+ ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>, boolean);
+ method public int describeContents();
+ method public java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>> getColors();
+ method public boolean supportsDarkText();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
+ }
+
public final class WallpaperInfo implements android.os.Parcelable {
ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public int describeContents();
@@ -6113,6 +6125,8 @@
}
public class WallpaperManager {
+ method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
+ method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler);
method public void clear() throws java.io.IOException;
method public void clear(int) throws java.io.IOException;
method public void clearWallpaperOffsets(android.os.IBinder);
@@ -6127,6 +6141,7 @@
method public android.graphics.drawable.Drawable getDrawable();
method public android.graphics.drawable.Drawable getFastDrawable();
method public static android.app.WallpaperManager getInstance(android.content.Context);
+ method public android.app.WallpaperColors getWallpaperColors(int);
method public android.os.ParcelFileDescriptor getWallpaperFile(int);
method public int getWallpaperId(int);
method public android.app.WallpaperInfo getWallpaperInfo();
@@ -6135,6 +6150,7 @@
method public boolean isWallpaperSupported();
method public android.graphics.drawable.Drawable peekDrawable();
method public android.graphics.drawable.Drawable peekFastDrawable();
+ method public void removeOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle);
method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException;
method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException;
@@ -6159,6 +6175,10 @@
field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview";
}
+ public static abstract interface WallpaperManager.OnColorsChangedListener {
+ method public abstract void onColorsChanged(android.app.WallpaperColors, int);
+ }
+
}
package android.app.admin {
@@ -6869,6 +6889,14 @@
field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_JOB_SERVICE";
}
+ public abstract class JobServiceEngine {
+ ctor public JobServiceEngine(android.content.Context);
+ 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);
+ method public abstract boolean onStopJob(android.app.job.JobParameters);
+ }
+
public final class JobWorkItem implements android.os.Parcelable {
ctor public JobWorkItem(android.content.Intent);
ctor public JobWorkItem(android.os.Parcel);
@@ -8069,7 +8097,12 @@
method public void flushPendingScanResults(android.bluetooth.le.ScanCallback);
method public void startScan(android.bluetooth.le.ScanCallback);
method public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
+ method public int startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.app.PendingIntent);
method public void stopScan(android.bluetooth.le.ScanCallback);
+ method public void stopScan(android.app.PendingIntent);
+ field public static final java.lang.String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
+ field public static final java.lang.String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
+ field public static final java.lang.String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT";
}
public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
@@ -8253,6 +8286,8 @@
method public void associate(android.companion.AssociationRequest, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
method public void disassociate(java.lang.String);
method public java.util.List<java.lang.String> getAssociations();
+ method public boolean hasNotificationAccess(android.content.ComponentName);
+ method public void requestNotificationAccess(android.content.ComponentName);
field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
}
@@ -9325,7 +9360,6 @@
field public static final java.lang.String ACTION_MANAGED_PROFILE_UNLOCKED = "android.intent.action.MANAGED_PROFILE_UNLOCKED";
field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
- field public static final deprecated java.lang.String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
field public static final java.lang.String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
field public static final java.lang.String ACTION_MEDIA_BUTTON = "android.intent.action.MEDIA_BUTTON";
field public static final java.lang.String ACTION_MEDIA_CHECKING = "android.intent.action.MEDIA_CHECKING";
@@ -21872,7 +21906,7 @@
method public deprecated java.nio.ByteBuffer[] getInputBuffers();
method public final android.media.MediaFormat getInputFormat();
method public android.media.Image getInputImage(int);
- method public android.media.MediaMetricsSet getMetrics();
+ method public android.os.PersistableBundle getMetrics();
method public final java.lang.String getName();
method public java.nio.ByteBuffer getOutputBuffer(int);
method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
@@ -21970,6 +22004,19 @@
method public void set(int, int);
}
+ public static final class MediaCodec.MetricsConstants {
+ field public static final java.lang.String CODEC = "android.media.mediacodec.codec";
+ field public static final java.lang.String ENCODER = "android.media.mediacodec.encoder";
+ field public static final java.lang.String HEIGHT = "android.media.mediacodec.height";
+ field public static final java.lang.String MIME_TYPE = "android.media.mediacodec.mime";
+ field public static final java.lang.String MODE = "android.media.mediacodec.mode";
+ field public static final java.lang.String MODE_AUDIO = "audio";
+ field public static final java.lang.String MODE_VIDEO = "video";
+ field public static final java.lang.String ROTATION = "android.media.mediacodec.rotation";
+ field public static final java.lang.String SECURE = "android.media.mediacodec.secure";
+ field public static final java.lang.String WIDTH = "android.media.mediacodec.width";
+ }
+
public static abstract interface MediaCodec.OnFrameRenderedListener {
method public abstract void onFrameRendered(android.media.MediaCodec, long, long);
}
@@ -22425,7 +22472,7 @@
method public long getCachedDuration();
method public android.media.MediaExtractor.CasInfo getCasInfo(int);
method public android.media.DrmInitData getDrmInitData();
- method public android.media.MediaMetricsSet getMetrics();
+ method public android.os.PersistableBundle getMetrics();
method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
method public int getSampleFlags();
@@ -22460,6 +22507,12 @@
method public int getSystemId();
}
+ public static final class MediaExtractor.MetricsConstants {
+ field public static final java.lang.String FORMAT = "android.media.mediaextractor.fmt";
+ field public static final java.lang.String MIME_TYPE = "android.media.mediaextractor.mime";
+ field public static final java.lang.String TRACKS = "android.media.mediaextractor.ntrk";
+ }
+
public final class MediaFormat {
ctor public MediaFormat();
method public final boolean containsKey(java.lang.String);
@@ -22685,69 +22738,6 @@
field public static final int OPTION_PREVIOUS_SYNC = 0; // 0x0
}
- public final class MediaMetricsSet {
- method public double getDouble(java.lang.String, double);
- method public int getInt(java.lang.String, int);
- method public long getLong(java.lang.String, long);
- method public java.lang.String getString(java.lang.String, java.lang.String);
- method public boolean isEmpty();
- method public java.util.Set<java.lang.String> keySet();
- method public int size();
- }
-
- public static final class MediaMetricsSet.MediaCodec {
- field public static final java.lang.String KEY_CODEC = "android.media.mediacodec.codec";
- field public static final java.lang.String KEY_ENCODER = "android.media.mediacodec.encoder";
- field public static final java.lang.String KEY_HEIGHT = "android.media.mediacodec.height";
- field public static final java.lang.String KEY_MIME = "android.media.mediacodec.mime";
- field public static final java.lang.String KEY_MODE = "android.media.mediacodec.mode";
- field public static final java.lang.String KEY_ROTATION = "android.media.mediacodec.rotation";
- field public static final java.lang.String KEY_SECURE = "android.media.mediacodec.secure";
- field public static final java.lang.String KEY_WIDTH = "android.media.mediacodec.width";
- field public static final java.lang.String MODE_AUDIO = "audio";
- field public static final java.lang.String MODE_VIDEO = "video";
- }
-
- public static final class MediaMetricsSet.MediaExtractor {
- field public static final java.lang.String KEY_FORMAT = "android.media.mediaextractor.fmt";
- field public static final java.lang.String KEY_MIME = "android.media.mediaextractor.mime";
- field public static final java.lang.String KEY_TRACKS = "android.media.mediaextractor.ntrk";
- }
-
- public static final class MediaMetricsSet.MediaPlayer {
- field public static final java.lang.String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
- field public static final java.lang.String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec";
- field public static final java.lang.String KEY_DURATION = "android.media.mediaplayer.durationMs";
- field public static final java.lang.String KEY_ERRORS = "android.media.mediaplayer.err";
- field public static final java.lang.String KEY_ERROR_CODE = "android.media.mediaplayer.errcode";
- field public static final java.lang.String KEY_FRAMES = "android.media.mediaplayer.frames";
- field public static final java.lang.String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped";
- field public static final java.lang.String KEY_HEIGHT = "android.media.mediaplayer.height";
- field public static final java.lang.String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime";
- field public static final java.lang.String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime";
- field public static final java.lang.String KEY_PLAYING = "android.media.mediaplayer.playingMs";
- field public static final java.lang.String KEY_WIDTH = "android.media.mediaplayer.width";
- }
-
- public static final class MediaMetricsSet.MediaRecorder {
- field public static final java.lang.String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
- field public static final java.lang.String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
- field public static final java.lang.String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
- field public static final java.lang.String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
- field public static final java.lang.String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
- field public static final java.lang.String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
- field public static final java.lang.String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate";
- field public static final java.lang.String KEY_HEIGHT = "android.media.mediarecorder.height";
- field public static final java.lang.String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
- field public static final java.lang.String KEY_ROTATION = "android.media.mediarecorder.rotation";
- field public static final java.lang.String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
- field public static final java.lang.String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
- field public static final java.lang.String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
- field public static final java.lang.String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
- field public static final java.lang.String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
- field public static final java.lang.String KEY_WIDTH = "android.media.mediarecorder.width";
- }
-
public final class MediaMuxer {
ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException;
@@ -22786,7 +22776,7 @@
method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
method public int getDuration();
method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
- method public android.media.MediaMetricsSet getMetrics();
+ method public android.os.PersistableBundle getMetrics();
method public android.media.PlaybackParams getPlaybackParams();
method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
method public android.media.SyncParams getSyncParams();
@@ -22881,6 +22871,21 @@
method public java.util.UUID[] getSupportedSchemes();
}
+ public static final class MediaPlayer.MetricsConstants {
+ field public static final java.lang.String CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
+ field public static final java.lang.String CODEC_VIDEO = "android.media.mediaplayer.video.codec";
+ field public static final java.lang.String DURATION = "android.media.mediaplayer.durationMs";
+ field public static final java.lang.String ERRORS = "android.media.mediaplayer.err";
+ field public static final java.lang.String ERROR_CODE = "android.media.mediaplayer.errcode";
+ field public static final java.lang.String FRAMES = "android.media.mediaplayer.frames";
+ field public static final java.lang.String FRAMES_DROPPED = "android.media.mediaplayer.dropped";
+ field public static final java.lang.String HEIGHT = "android.media.mediaplayer.height";
+ field public static final java.lang.String MIME_TYPE_AUDIO = "android.media.mediaplayer.audio.mime";
+ field public static final java.lang.String MIME_TYPE_VIDEO = "android.media.mediaplayer.video.mime";
+ field public static final java.lang.String PLAYING = "android.media.mediaplayer.playingMs";
+ field public static final java.lang.String WIDTH = "android.media.mediaplayer.width";
+ }
+
public static final class MediaPlayer.NoDrmSchemeException extends android.media.MediaDrmException {
ctor public MediaPlayer.NoDrmSchemeException(java.lang.String);
}
@@ -22955,7 +22960,7 @@
ctor public MediaRecorder();
method public static final int getAudioSourceMax();
method public int getMaxAmplitude() throws java.lang.IllegalStateException;
- method public android.media.MediaMetricsSet getMetrics();
+ method public android.os.PersistableBundle getMetrics();
method public android.view.Surface getSurface();
method public void pause() throws java.lang.IllegalStateException;
method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
@@ -22974,11 +22979,12 @@
method public void setMaxDuration(int) throws java.lang.IllegalArgumentException;
method public void setMaxFileSize(long) throws java.lang.IllegalArgumentException;
method public void setNextOutputFile(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalStateException;
- method public void setNextOutputFile(java.lang.String) throws java.io.IOException, java.lang.IllegalStateException;
+ method public void setNextOutputFile(java.io.File) throws java.io.IOException, java.lang.IllegalStateException;
method public void setOnErrorListener(android.media.MediaRecorder.OnErrorListener);
method public void setOnInfoListener(android.media.MediaRecorder.OnInfoListener);
method public void setOrientationHint(int);
method public void setOutputFile(java.io.FileDescriptor) throws java.lang.IllegalStateException;
+ method public void setOutputFile(java.io.File);
method public void setOutputFile(java.lang.String) throws java.lang.IllegalStateException;
method public void setOutputFormat(int) throws java.lang.IllegalStateException;
method public void setPreviewDisplay(android.view.Surface);
@@ -23023,6 +23029,25 @@
field public static final int VOICE_UPLINK = 2; // 0x2
}
+ public static final class MediaRecorder.MetricsConstants {
+ field public static final java.lang.String AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
+ field public static final java.lang.String AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
+ field public static final java.lang.String AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
+ field public static final java.lang.String AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
+ field public static final java.lang.String CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
+ field public static final java.lang.String CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
+ field public static final java.lang.String FRAMERATE = "android.media.mediarecorder.frame-rate";
+ field public static final java.lang.String HEIGHT = "android.media.mediarecorder.height";
+ field public static final java.lang.String MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
+ field public static final java.lang.String ROTATION = "android.media.mediarecorder.rotation";
+ field public static final java.lang.String VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
+ field public static final java.lang.String VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
+ field public static final java.lang.String VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
+ field public static final java.lang.String VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
+ field public static final java.lang.String VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
+ field public static final java.lang.String WIDTH = "android.media.mediarecorder.width";
+ }
+
public static abstract interface MediaRecorder.OnErrorListener {
method public abstract void onError(android.media.MediaRecorder, int, int);
}
@@ -25782,6 +25807,10 @@
method public android.net.NetworkRequest.Builder removeCapability(int);
method public android.net.NetworkRequest.Builder removeTransportType(int);
method public android.net.NetworkRequest.Builder setNetworkSpecifier(java.lang.String);
+ method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier);
+ }
+
+ public abstract class NetworkSpecifier {
}
public class ParseException extends java.lang.RuntimeException {
@@ -37035,8 +37064,10 @@
method public final android.os.IBinder onBind(android.content.Intent);
method public void onConnected();
method public void onDisconnected();
- method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback);
- method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
+ method public void onFillRequest(android.service.autofill.FillRequest, android.os.CancellationSignal, android.service.autofill.FillCallback);
+ method public abstract deprecated void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback);
+ method public void onSaveRequest(android.service.autofill.SaveRequest, android.service.autofill.SaveCallback);
+ method public abstract deprecated void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillService";
field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
}
@@ -37061,6 +37092,25 @@
method public void onSuccess(android.service.autofill.FillResponse);
}
+ public final class FillContext implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getRequestId();
+ method public android.app.assist.AssistStructure getStructure();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.autofill.FillContext> CREATOR;
+ }
+
+ public final class FillRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.os.Bundle getClientState();
+ method public int getFlags();
+ method public int getId();
+ method public android.app.assist.AssistStructure getStructure();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.autofill.FillRequest> CREATOR;
+ field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
+ }
+
public final class FillResponse implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
@@ -37072,7 +37122,8 @@
method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
method public android.service.autofill.FillResponse build();
method public android.service.autofill.FillResponse.Builder setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews);
- method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+ method public android.service.autofill.FillResponse.Builder setClientState(android.os.Bundle);
+ method public deprecated android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
}
@@ -37101,6 +37152,14 @@
method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
}
+ public final class SaveRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.os.Bundle getClientState();
+ method public java.util.List<android.service.autofill.FillContext> getFillContexts();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.autofill.SaveRequest> CREATOR;
+ }
+
}
package android.service.carrier {
@@ -37734,10 +37793,12 @@
method public int getDesiredMinimumHeight();
method public int getDesiredMinimumWidth();
method public android.view.SurfaceHolder getSurfaceHolder();
+ method public void invalidateColors();
method public boolean isPreview();
method public boolean isVisible();
method public void onApplyWindowInsets(android.view.WindowInsets);
method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
+ method public android.app.WallpaperColors onComputeWallpaperColors();
method public void onCreate(android.view.SurfaceHolder);
method public void onDesiredSizeChanged(int, int);
method public void onDestroy();
@@ -45368,7 +45429,6 @@
method public android.view.animation.Animation getAnimation();
method public android.os.IBinder getApplicationWindowToken();
method public java.lang.String[] getAutofillHints();
- method public int getAutofillMode();
method public int getAutofillType();
method public android.view.autofill.AutofillValue getAutofillValue();
method public android.graphics.drawable.Drawable getBackground();
@@ -45457,7 +45517,6 @@
method public float getPivotX();
method public float getPivotY();
method public android.view.PointerIcon getPointerIcon();
- method public int getResolvedAutofillMode();
method public android.content.res.Resources getResources();
method public final boolean getRevealOnFocusHint();
method public final int getRight();
@@ -45690,7 +45749,6 @@
method public void setAlpha(float);
method public void setAnimation(android.view.animation.Animation);
method public void setAutofillHints(java.lang.String...);
- method public void setAutofillMode(int);
method public void setBackground(android.graphics.drawable.Drawable);
method public void setBackgroundColor(int);
method public deprecated void setBackgroundDrawable(android.graphics.drawable.Drawable);
@@ -45846,9 +45904,6 @@
field public static final java.lang.String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
field public static final java.lang.String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
field public static final java.lang.String AUTOFILL_HINT_USERNAME = "username";
- field public static final int AUTOFILL_MODE_AUTO = 1; // 0x1
- field public static final int AUTOFILL_MODE_INHERIT = 0; // 0x0
- field public static final int AUTOFILL_MODE_MANUAL = 2; // 0x2
field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
@@ -46416,7 +46471,6 @@
method public abstract int getLayoutDirection();
method public abstract android.view.ViewParent getParent();
method public abstract android.view.ViewParent getParentForAccessibility();
- method public default int getResolvedAutofillMode();
method public abstract int getTextAlignment();
method public abstract int getTextDirection();
method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect);
@@ -47803,7 +47857,7 @@
field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
field public static final java.lang.String EXTRA_DATA_EXTRAS = "android.view.autofill.extra.DATA_EXTRAS";
- field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
+ field public static final deprecated int FLAG_MANUAL_REQUEST = 1; // 0x1
}
public static abstract class AutofillManager.AutofillCallback {
diff --git a/api/removed.txt b/api/removed.txt
index 82705fd..1e8370e 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -5,10 +5,6 @@
method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
}
- public static class Notification.Builder {
- method public deprecated android.app.Notification.Builder chooseBadgeIcon(int);
- }
-
public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
method public deprecated void showAsNotification(android.content.Context);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index fd176d0..21fce31 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -329,6 +329,7 @@
ctor public R.attr();
field public static final int __removed1 = 16844099; // 0x1010543
field public static final int __removed2 = 16844104; // 0x1010548
+ field public static final int __removed3 = 16844116; // 0x1010554
field public static final int absListViewStyle = 16842858; // 0x101006a
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -431,7 +432,6 @@
field public static final int autoUrlDetect = 16843404; // 0x101028c
field public static final int autoVerify = 16844014; // 0x10104ee
field public static final int autofillHints = 16844121; // 0x1010559
- field public static final int autofillMode = 16844116; // 0x1010554
field public static final int background = 16842964; // 0x10100d4
field public static final int backgroundDimAmount = 16842802; // 0x1010032
field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -3743,6 +3743,7 @@
method public android.net.Uri getReferrer();
method public int getRequestedOrientation();
method public final android.view.SearchEvent getSearchEvent();
+ method public long getStartInitiatedTime();
method public int getTaskId();
method public final java.lang.CharSequence getTitle();
method public final int getTitleColor();
@@ -6295,6 +6296,17 @@
method public void setPersistentVrModeEnabled(boolean);
}
+ public final class WallpaperColors implements android.os.Parcelable {
+ ctor public WallpaperColors(android.os.Parcel);
+ ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>);
+ ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>, boolean);
+ method public int describeContents();
+ method public java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>> getColors();
+ method public boolean supportsDarkText();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
+ }
+
public final class WallpaperInfo implements android.os.Parcelable {
ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public int describeContents();
@@ -6317,6 +6329,8 @@
}
public class WallpaperManager {
+ method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
+ method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler);
method public void clear() throws java.io.IOException;
method public void clear(int) throws java.io.IOException;
method public void clearWallpaper();
@@ -6333,6 +6347,7 @@
method public android.graphics.drawable.Drawable getDrawable();
method public android.graphics.drawable.Drawable getFastDrawable();
method public static android.app.WallpaperManager getInstance(android.content.Context);
+ method public android.app.WallpaperColors getWallpaperColors(int);
method public android.os.ParcelFileDescriptor getWallpaperFile(int);
method public int getWallpaperId(int);
method public android.app.WallpaperInfo getWallpaperInfo();
@@ -6341,6 +6356,7 @@
method public boolean isWallpaperSupported();
method public android.graphics.drawable.Drawable peekDrawable();
method public android.graphics.drawable.Drawable peekFastDrawable();
+ method public void removeOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle);
method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException;
method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException;
@@ -6368,6 +6384,10 @@
field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview";
}
+ public static abstract interface WallpaperManager.OnColorsChangedListener {
+ method public abstract void onColorsChanged(android.app.WallpaperColors, int);
+ }
+
}
package android.app.admin {
@@ -7303,6 +7323,14 @@
field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_JOB_SERVICE";
}
+ public abstract class JobServiceEngine {
+ ctor public JobServiceEngine(android.content.Context);
+ 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);
+ method public abstract boolean onStopJob(android.app.job.JobParameters);
+ }
+
public final class JobWorkItem implements android.os.Parcelable {
ctor public JobWorkItem(android.content.Intent);
ctor public JobWorkItem(android.os.Parcel);
@@ -8541,10 +8569,15 @@
method public void flushPendingScanResults(android.bluetooth.le.ScanCallback);
method public void startScan(android.bluetooth.le.ScanCallback);
method public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
+ method public int startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.app.PendingIntent);
method public void startScanFromSource(android.os.WorkSource, android.bluetooth.le.ScanCallback);
method public void startScanFromSource(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.os.WorkSource, android.bluetooth.le.ScanCallback);
method public void startTruncatedScan(java.util.List<android.bluetooth.le.TruncatedFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
method public void stopScan(android.bluetooth.le.ScanCallback);
+ method public void stopScan(android.app.PendingIntent);
+ field public static final java.lang.String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
+ field public static final java.lang.String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
+ field public static final java.lang.String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT";
}
public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
@@ -8747,6 +8780,8 @@
method public void associate(android.companion.AssociationRequest, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
method public void disassociate(java.lang.String);
method public java.util.List<java.lang.String> getAssociations();
+ method public boolean hasNotificationAccess(android.content.ComponentName);
+ method public void requestNotificationAccess(android.content.ComponentName);
field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
}
@@ -11239,6 +11274,7 @@
method public abstract byte[] getInstantAppCookie();
method public abstract int getInstantAppCookieMaxSize();
method public abstract android.graphics.drawable.Drawable getInstantAppIcon(java.lang.String);
+ method public abstract android.content.ComponentName getInstantAppInstallerComponent();
method public abstract android.content.ComponentName getInstantAppResolverSettingsComponent();
method public abstract java.util.List<android.content.pm.InstantAppInfo> getInstantApps();
method public abstract android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -23704,7 +23740,7 @@
method public deprecated java.nio.ByteBuffer[] getInputBuffers();
method public final android.media.MediaFormat getInputFormat();
method public android.media.Image getInputImage(int);
- method public android.media.MediaMetricsSet getMetrics();
+ method public android.os.PersistableBundle getMetrics();
method public final java.lang.String getName();
method public java.nio.ByteBuffer getOutputBuffer(int);
method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
@@ -23802,6 +23838,19 @@
method public void set(int, int);
}
+ public static final class MediaCodec.MetricsConstants {
+ field public static final java.lang.String CODEC = "android.media.mediacodec.codec";
+ field public static final java.lang.String ENCODER = "android.media.mediacodec.encoder";
+ field public static final java.lang.String HEIGHT = "android.media.mediacodec.height";
+ field public static final java.lang.String MIME_TYPE = "android.media.mediacodec.mime";
+ field public static final java.lang.String MODE = "android.media.mediacodec.mode";
+ field public static final java.lang.String MODE_AUDIO = "audio";
+ field public static final java.lang.String MODE_VIDEO = "video";
+ field public static final java.lang.String ROTATION = "android.media.mediacodec.rotation";
+ field public static final java.lang.String SECURE = "android.media.mediacodec.secure";
+ field public static final java.lang.String WIDTH = "android.media.mediacodec.width";
+ }
+
public static abstract interface MediaCodec.OnFrameRenderedListener {
method public abstract void onFrameRendered(android.media.MediaCodec, long, long);
}
@@ -24257,7 +24306,7 @@
method public long getCachedDuration();
method public android.media.MediaExtractor.CasInfo getCasInfo(int);
method public android.media.DrmInitData getDrmInitData();
- method public android.media.MediaMetricsSet getMetrics();
+ method public android.os.PersistableBundle getMetrics();
method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
method public int getSampleFlags();
@@ -24292,6 +24341,12 @@
method public int getSystemId();
}
+ public static final class MediaExtractor.MetricsConstants {
+ field public static final java.lang.String FORMAT = "android.media.mediaextractor.fmt";
+ field public static final java.lang.String MIME_TYPE = "android.media.mediaextractor.mime";
+ field public static final java.lang.String TRACKS = "android.media.mediaextractor.ntrk";
+ }
+
public final class MediaFormat {
ctor public MediaFormat();
method public final boolean containsKey(java.lang.String);
@@ -24517,69 +24572,6 @@
field public static final int OPTION_PREVIOUS_SYNC = 0; // 0x0
}
- public final class MediaMetricsSet {
- method public double getDouble(java.lang.String, double);
- method public int getInt(java.lang.String, int);
- method public long getLong(java.lang.String, long);
- method public java.lang.String getString(java.lang.String, java.lang.String);
- method public boolean isEmpty();
- method public java.util.Set<java.lang.String> keySet();
- method public int size();
- }
-
- public static final class MediaMetricsSet.MediaCodec {
- field public static final java.lang.String KEY_CODEC = "android.media.mediacodec.codec";
- field public static final java.lang.String KEY_ENCODER = "android.media.mediacodec.encoder";
- field public static final java.lang.String KEY_HEIGHT = "android.media.mediacodec.height";
- field public static final java.lang.String KEY_MIME = "android.media.mediacodec.mime";
- field public static final java.lang.String KEY_MODE = "android.media.mediacodec.mode";
- field public static final java.lang.String KEY_ROTATION = "android.media.mediacodec.rotation";
- field public static final java.lang.String KEY_SECURE = "android.media.mediacodec.secure";
- field public static final java.lang.String KEY_WIDTH = "android.media.mediacodec.width";
- field public static final java.lang.String MODE_AUDIO = "audio";
- field public static final java.lang.String MODE_VIDEO = "video";
- }
-
- public static final class MediaMetricsSet.MediaExtractor {
- field public static final java.lang.String KEY_FORMAT = "android.media.mediaextractor.fmt";
- field public static final java.lang.String KEY_MIME = "android.media.mediaextractor.mime";
- field public static final java.lang.String KEY_TRACKS = "android.media.mediaextractor.ntrk";
- }
-
- public static final class MediaMetricsSet.MediaPlayer {
- field public static final java.lang.String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
- field public static final java.lang.String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec";
- field public static final java.lang.String KEY_DURATION = "android.media.mediaplayer.durationMs";
- field public static final java.lang.String KEY_ERRORS = "android.media.mediaplayer.err";
- field public static final java.lang.String KEY_ERROR_CODE = "android.media.mediaplayer.errcode";
- field public static final java.lang.String KEY_FRAMES = "android.media.mediaplayer.frames";
- field public static final java.lang.String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped";
- field public static final java.lang.String KEY_HEIGHT = "android.media.mediaplayer.height";
- field public static final java.lang.String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime";
- field public static final java.lang.String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime";
- field public static final java.lang.String KEY_PLAYING = "android.media.mediaplayer.playingMs";
- field public static final java.lang.String KEY_WIDTH = "android.media.mediaplayer.width";
- }
-
- public static final class MediaMetricsSet.MediaRecorder {
- field public static final java.lang.String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
- field public static final java.lang.String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
- field public static final java.lang.String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
- field public static final java.lang.String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
- field public static final java.lang.String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
- field public static final java.lang.String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
- field public static final java.lang.String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate";
- field public static final java.lang.String KEY_HEIGHT = "android.media.mediarecorder.height";
- field public static final java.lang.String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
- field public static final java.lang.String KEY_ROTATION = "android.media.mediarecorder.rotation";
- field public static final java.lang.String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
- field public static final java.lang.String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
- field public static final java.lang.String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
- field public static final java.lang.String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
- field public static final java.lang.String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
- field public static final java.lang.String KEY_WIDTH = "android.media.mediarecorder.width";
- }
-
public final class MediaMuxer {
ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException;
@@ -24618,7 +24610,7 @@
method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
method public int getDuration();
method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
- method public android.media.MediaMetricsSet getMetrics();
+ method public android.os.PersistableBundle getMetrics();
method public android.media.PlaybackParams getPlaybackParams();
method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
method public android.media.SyncParams getSyncParams();
@@ -24713,6 +24705,21 @@
method public java.util.UUID[] getSupportedSchemes();
}
+ public static final class MediaPlayer.MetricsConstants {
+ field public static final java.lang.String CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
+ field public static final java.lang.String CODEC_VIDEO = "android.media.mediaplayer.video.codec";
+ field public static final java.lang.String DURATION = "android.media.mediaplayer.durationMs";
+ field public static final java.lang.String ERRORS = "android.media.mediaplayer.err";
+ field public static final java.lang.String ERROR_CODE = "android.media.mediaplayer.errcode";
+ field public static final java.lang.String FRAMES = "android.media.mediaplayer.frames";
+ field public static final java.lang.String FRAMES_DROPPED = "android.media.mediaplayer.dropped";
+ field public static final java.lang.String HEIGHT = "android.media.mediaplayer.height";
+ field public static final java.lang.String MIME_TYPE_AUDIO = "android.media.mediaplayer.audio.mime";
+ field public static final java.lang.String MIME_TYPE_VIDEO = "android.media.mediaplayer.video.mime";
+ field public static final java.lang.String PLAYING = "android.media.mediaplayer.playingMs";
+ field public static final java.lang.String WIDTH = "android.media.mediaplayer.width";
+ }
+
public static final class MediaPlayer.NoDrmSchemeException extends android.media.MediaDrmException {
ctor public MediaPlayer.NoDrmSchemeException(java.lang.String);
}
@@ -24787,7 +24794,7 @@
ctor public MediaRecorder();
method public static final int getAudioSourceMax();
method public int getMaxAmplitude() throws java.lang.IllegalStateException;
- method public android.media.MediaMetricsSet getMetrics();
+ method public android.os.PersistableBundle getMetrics();
method public android.view.Surface getSurface();
method public void pause() throws java.lang.IllegalStateException;
method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
@@ -24806,11 +24813,12 @@
method public void setMaxDuration(int) throws java.lang.IllegalArgumentException;
method public void setMaxFileSize(long) throws java.lang.IllegalArgumentException;
method public void setNextOutputFile(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalStateException;
- method public void setNextOutputFile(java.lang.String) throws java.io.IOException, java.lang.IllegalStateException;
+ method public void setNextOutputFile(java.io.File) throws java.io.IOException, java.lang.IllegalStateException;
method public void setOnErrorListener(android.media.MediaRecorder.OnErrorListener);
method public void setOnInfoListener(android.media.MediaRecorder.OnInfoListener);
method public void setOrientationHint(int);
method public void setOutputFile(java.io.FileDescriptor) throws java.lang.IllegalStateException;
+ method public void setOutputFile(java.io.File);
method public void setOutputFile(java.lang.String) throws java.lang.IllegalStateException;
method public void setOutputFormat(int) throws java.lang.IllegalStateException;
method public void setPreviewDisplay(android.view.Surface);
@@ -24857,6 +24865,25 @@
field public static final int VOICE_UPLINK = 2; // 0x2
}
+ public static final class MediaRecorder.MetricsConstants {
+ field public static final java.lang.String AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
+ field public static final java.lang.String AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
+ field public static final java.lang.String AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
+ field public static final java.lang.String AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
+ field public static final java.lang.String CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
+ field public static final java.lang.String CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
+ field public static final java.lang.String FRAMERATE = "android.media.mediarecorder.frame-rate";
+ field public static final java.lang.String HEIGHT = "android.media.mediarecorder.height";
+ field public static final java.lang.String MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
+ field public static final java.lang.String ROTATION = "android.media.mediarecorder.rotation";
+ field public static final java.lang.String VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
+ field public static final java.lang.String VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
+ field public static final java.lang.String VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
+ field public static final java.lang.String VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
+ field public static final java.lang.String VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
+ field public static final java.lang.String WIDTH = "android.media.mediarecorder.width";
+ }
+
public static abstract interface MediaRecorder.OnErrorListener {
method public abstract void onError(android.media.MediaRecorder, int, int);
}
@@ -28004,6 +28031,7 @@
method public android.net.NetworkRequest.Builder removeCapability(int);
method public android.net.NetworkRequest.Builder removeTransportType(int);
method public android.net.NetworkRequest.Builder setNetworkSpecifier(java.lang.String);
+ method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier);
}
public class NetworkScoreManager {
@@ -28022,6 +28050,9 @@
field public static final java.lang.String EXTRA_PACKAGE_NAME = "packageName";
}
+ public abstract class NetworkSpecifier {
+ }
+
public class ParseException extends java.lang.RuntimeException {
field public java.lang.String response;
}
@@ -28144,10 +28175,6 @@
field public static final java.lang.String ATTRIBUTES_KEY_BADGING_CURVE = "android.net.attributes.key.BADGING_CURVE";
field public static final java.lang.String ATTRIBUTES_KEY_HAS_CAPTIVE_PORTAL = "android.net.attributes.key.HAS_CAPTIVE_PORTAL";
field public static final java.lang.String ATTRIBUTES_KEY_RANKING_SCORE_OFFSET = "android.net.attributes.key.RANKING_SCORE_OFFSET";
- field public static final deprecated int BADGING_4K = 30; // 0x1e
- field public static final deprecated int BADGING_HD = 20; // 0x14
- field public static final deprecated int BADGING_NONE = 0; // 0x0
- field public static final deprecated int BADGING_SD = 10; // 0xa
field public static final android.os.Parcelable.Creator<android.net.ScoredNetwork> CREATOR;
field public final android.os.Bundle attributes;
field public final boolean meteredHint;
@@ -28155,9 +28182,6 @@
field public final android.net.RssiCurve rssiCurve;
}
- public static abstract deprecated class ScoredNetwork.Badging implements java.lang.annotation.Annotation {
- }
-
public class TrafficStats {
ctor public TrafficStats();
method public static void clearThreadStatsTag();
@@ -40151,8 +40175,10 @@
method public final android.os.IBinder onBind(android.content.Intent);
method public void onConnected();
method public void onDisconnected();
- method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback);
- method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
+ method public void onFillRequest(android.service.autofill.FillRequest, android.os.CancellationSignal, android.service.autofill.FillCallback);
+ method public abstract deprecated void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback);
+ method public void onSaveRequest(android.service.autofill.SaveRequest, android.service.autofill.SaveCallback);
+ method public abstract deprecated void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillService";
field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
}
@@ -40177,6 +40203,25 @@
method public void onSuccess(android.service.autofill.FillResponse);
}
+ public final class FillContext implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getRequestId();
+ method public android.app.assist.AssistStructure getStructure();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.autofill.FillContext> CREATOR;
+ }
+
+ public final class FillRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.os.Bundle getClientState();
+ method public int getFlags();
+ method public int getId();
+ method public android.app.assist.AssistStructure getStructure();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.autofill.FillRequest> CREATOR;
+ field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
+ }
+
public final class FillResponse implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
@@ -40188,7 +40233,8 @@
method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
method public android.service.autofill.FillResponse build();
method public android.service.autofill.FillResponse.Builder setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews);
- method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+ method public android.service.autofill.FillResponse.Builder setClientState(android.os.Bundle);
+ method public deprecated android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
}
@@ -40217,6 +40263,14 @@
method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
}
+ public final class SaveRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.os.Bundle getClientState();
+ method public java.util.List<android.service.autofill.FillContext> getFillContexts();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.autofill.SaveRequest> CREATOR;
+ }
+
}
package android.service.carrier {
@@ -40992,10 +41046,12 @@
method public int getDesiredMinimumHeight();
method public int getDesiredMinimumWidth();
method public android.view.SurfaceHolder getSurfaceHolder();
+ method public void invalidateColors();
method public boolean isPreview();
method public boolean isVisible();
method public void onApplyWindowInsets(android.view.WindowInsets);
method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
+ method public android.app.WallpaperColors onComputeWallpaperColors();
method public void onCreate(android.view.SurfaceHolder);
method public void onDesiredSizeChanged(int, int);
method public void onDestroy();
@@ -44520,6 +44576,7 @@
method public byte[] getInstantAppCookie();
method public int getInstantAppCookieMaxSize();
method public android.graphics.drawable.Drawable getInstantAppIcon(java.lang.String);
+ method public android.content.ComponentName getInstantAppInstallerComponent();
method public android.content.ComponentName getInstantAppResolverSettingsComponent();
method public java.util.List<android.content.pm.InstantAppInfo> getInstantApps();
method public android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -48948,7 +49005,6 @@
method public android.view.animation.Animation getAnimation();
method public android.os.IBinder getApplicationWindowToken();
method public java.lang.String[] getAutofillHints();
- method public int getAutofillMode();
method public int getAutofillType();
method public android.view.autofill.AutofillValue getAutofillValue();
method public android.graphics.drawable.Drawable getBackground();
@@ -49037,7 +49093,6 @@
method public float getPivotX();
method public float getPivotY();
method public android.view.PointerIcon getPointerIcon();
- method public int getResolvedAutofillMode();
method public android.content.res.Resources getResources();
method public final boolean getRevealOnFocusHint();
method public final int getRight();
@@ -49270,7 +49325,6 @@
method public void setAlpha(float);
method public void setAnimation(android.view.animation.Animation);
method public void setAutofillHints(java.lang.String...);
- method public void setAutofillMode(int);
method public void setBackground(android.graphics.drawable.Drawable);
method public void setBackgroundColor(int);
method public deprecated void setBackgroundDrawable(android.graphics.drawable.Drawable);
@@ -49426,9 +49480,6 @@
field public static final java.lang.String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
field public static final java.lang.String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
field public static final java.lang.String AUTOFILL_HINT_USERNAME = "username";
- field public static final int AUTOFILL_MODE_AUTO = 1; // 0x1
- field public static final int AUTOFILL_MODE_INHERIT = 0; // 0x0
- field public static final int AUTOFILL_MODE_MANUAL = 2; // 0x2
field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
@@ -49996,7 +50047,6 @@
method public abstract int getLayoutDirection();
method public abstract android.view.ViewParent getParent();
method public abstract android.view.ViewParent getParentForAccessibility();
- method public default int getResolvedAutofillMode();
method public abstract int getTextAlignment();
method public abstract int getTextDirection();
method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect);
@@ -51386,7 +51436,7 @@
field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
field public static final java.lang.String EXTRA_DATA_EXTRAS = "android.view.autofill.extra.DATA_EXTRAS";
- field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
+ field public static final deprecated int FLAG_MANUAL_REQUEST = 1; // 0x1
}
public static abstract class AutofillManager.AutofillCallback {
diff --git a/api/system-removed.txt b/api/system-removed.txt
index bdcafae..7bdb957 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -5,10 +5,6 @@
method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
}
- public static class Notification.Builder {
- method public deprecated android.app.Notification.Builder chooseBadgeIcon(int);
- }
-
public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
method public deprecated void showAsNotification(android.content.Context);
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 1504b29..18f86b8 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -211,6 +211,7 @@
ctor public R.attr();
field public static final int __removed1 = 16844099; // 0x1010543
field public static final int __removed2 = 16844104; // 0x1010548
+ field public static final int __removed3 = 16844116; // 0x1010554
field public static final int absListViewStyle = 16842858; // 0x101006a
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -313,7 +314,6 @@
field public static final int autoUrlDetect = 16843404; // 0x101028c
field public static final int autoVerify = 16844014; // 0x10104ee
field public static final int autofillHints = 16844121; // 0x1010559
- field public static final int autofillMode = 16844116; // 0x1010554
field public static final int background = 16842964; // 0x10100d4
field public static final int backgroundDimAmount = 16842802; // 0x1010032
field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -3617,6 +3617,7 @@
method public android.net.Uri getReferrer();
method public int getRequestedOrientation();
method public final android.view.SearchEvent getSearchEvent();
+ method public long getStartInitiatedTime();
method public int getTaskId();
method public final java.lang.CharSequence getTitle();
method public final int getTitleColor();
@@ -6111,6 +6112,17 @@
method public void onDetached();
}
+ public final class WallpaperColors implements android.os.Parcelable {
+ ctor public WallpaperColors(android.os.Parcel);
+ ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>);
+ ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>, boolean);
+ method public int describeContents();
+ method public java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>> getColors();
+ method public boolean supportsDarkText();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
+ }
+
public final class WallpaperInfo implements android.os.Parcelable {
ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public int describeContents();
@@ -6133,6 +6145,8 @@
}
public class WallpaperManager {
+ method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
+ method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler);
method public void clear() throws java.io.IOException;
method public void clear(int) throws java.io.IOException;
method public void clearWallpaperOffsets(android.os.IBinder);
@@ -6147,6 +6161,7 @@
method public android.graphics.drawable.Drawable getDrawable();
method public android.graphics.drawable.Drawable getFastDrawable();
method public static android.app.WallpaperManager getInstance(android.content.Context);
+ method public android.app.WallpaperColors getWallpaperColors(int);
method public android.os.ParcelFileDescriptor getWallpaperFile(int);
method public int getWallpaperId(int);
method public android.app.WallpaperInfo getWallpaperInfo();
@@ -6155,6 +6170,7 @@
method public boolean isWallpaperSupported();
method public android.graphics.drawable.Drawable peekDrawable();
method public android.graphics.drawable.Drawable peekFastDrawable();
+ method public void removeOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle);
method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException;
method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException;
@@ -6179,6 +6195,10 @@
field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview";
}
+ public static abstract interface WallpaperManager.OnColorsChangedListener {
+ method public abstract void onColorsChanged(android.app.WallpaperColors, int);
+ }
+
}
package android.app.admin {
@@ -6899,6 +6919,14 @@
field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_JOB_SERVICE";
}
+ public abstract class JobServiceEngine {
+ ctor public JobServiceEngine(android.content.Context);
+ 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);
+ method public abstract boolean onStopJob(android.app.job.JobParameters);
+ }
+
public final class JobWorkItem implements android.os.Parcelable {
ctor public JobWorkItem(android.content.Intent);
ctor public JobWorkItem(android.os.Parcel);
@@ -8100,7 +8128,12 @@
method public void flushPendingScanResults(android.bluetooth.le.ScanCallback);
method public void startScan(android.bluetooth.le.ScanCallback);
method public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
+ method public int startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.app.PendingIntent);
method public void stopScan(android.bluetooth.le.ScanCallback);
+ method public void stopScan(android.app.PendingIntent);
+ field public static final java.lang.String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
+ field public static final java.lang.String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
+ field public static final java.lang.String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT";
}
public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
@@ -8284,6 +8317,8 @@
method public void associate(android.companion.AssociationRequest, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
method public void disassociate(java.lang.String);
method public java.util.List<java.lang.String> getAssociations();
+ method public boolean hasNotificationAccess(android.content.ComponentName);
+ method public void requestNotificationAccess(android.content.ComponentName);
field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
}
@@ -9359,7 +9394,6 @@
field public static final java.lang.String ACTION_MANAGED_PROFILE_UNLOCKED = "android.intent.action.MANAGED_PROFILE_UNLOCKED";
field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
- field public static final deprecated java.lang.String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
field public static final java.lang.String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
field public static final java.lang.String ACTION_MEDIA_BUTTON = "android.intent.action.MEDIA_BUTTON";
field public static final java.lang.String ACTION_MEDIA_CHECKING = "android.intent.action.MEDIA_CHECKING";
@@ -21979,7 +22013,7 @@
method public deprecated java.nio.ByteBuffer[] getInputBuffers();
method public final android.media.MediaFormat getInputFormat();
method public android.media.Image getInputImage(int);
- method public android.media.MediaMetricsSet getMetrics();
+ method public android.os.PersistableBundle getMetrics();
method public final java.lang.String getName();
method public java.nio.ByteBuffer getOutputBuffer(int);
method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
@@ -22077,6 +22111,19 @@
method public void set(int, int);
}
+ public static final class MediaCodec.MetricsConstants {
+ field public static final java.lang.String CODEC = "android.media.mediacodec.codec";
+ field public static final java.lang.String ENCODER = "android.media.mediacodec.encoder";
+ field public static final java.lang.String HEIGHT = "android.media.mediacodec.height";
+ field public static final java.lang.String MIME_TYPE = "android.media.mediacodec.mime";
+ field public static final java.lang.String MODE = "android.media.mediacodec.mode";
+ field public static final java.lang.String MODE_AUDIO = "audio";
+ field public static final java.lang.String MODE_VIDEO = "video";
+ field public static final java.lang.String ROTATION = "android.media.mediacodec.rotation";
+ field public static final java.lang.String SECURE = "android.media.mediacodec.secure";
+ field public static final java.lang.String WIDTH = "android.media.mediacodec.width";
+ }
+
public static abstract interface MediaCodec.OnFrameRenderedListener {
method public abstract void onFrameRendered(android.media.MediaCodec, long, long);
}
@@ -22532,7 +22579,7 @@
method public long getCachedDuration();
method public android.media.MediaExtractor.CasInfo getCasInfo(int);
method public android.media.DrmInitData getDrmInitData();
- method public android.media.MediaMetricsSet getMetrics();
+ method public android.os.PersistableBundle getMetrics();
method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
method public int getSampleFlags();
@@ -22567,6 +22614,12 @@
method public int getSystemId();
}
+ public static final class MediaExtractor.MetricsConstants {
+ field public static final java.lang.String FORMAT = "android.media.mediaextractor.fmt";
+ field public static final java.lang.String MIME_TYPE = "android.media.mediaextractor.mime";
+ field public static final java.lang.String TRACKS = "android.media.mediaextractor.ntrk";
+ }
+
public final class MediaFormat {
ctor public MediaFormat();
method public final boolean containsKey(java.lang.String);
@@ -22792,69 +22845,6 @@
field public static final int OPTION_PREVIOUS_SYNC = 0; // 0x0
}
- public final class MediaMetricsSet {
- method public double getDouble(java.lang.String, double);
- method public int getInt(java.lang.String, int);
- method public long getLong(java.lang.String, long);
- method public java.lang.String getString(java.lang.String, java.lang.String);
- method public boolean isEmpty();
- method public java.util.Set<java.lang.String> keySet();
- method public int size();
- }
-
- public static final class MediaMetricsSet.MediaCodec {
- field public static final java.lang.String KEY_CODEC = "android.media.mediacodec.codec";
- field public static final java.lang.String KEY_ENCODER = "android.media.mediacodec.encoder";
- field public static final java.lang.String KEY_HEIGHT = "android.media.mediacodec.height";
- field public static final java.lang.String KEY_MIME = "android.media.mediacodec.mime";
- field public static final java.lang.String KEY_MODE = "android.media.mediacodec.mode";
- field public static final java.lang.String KEY_ROTATION = "android.media.mediacodec.rotation";
- field public static final java.lang.String KEY_SECURE = "android.media.mediacodec.secure";
- field public static final java.lang.String KEY_WIDTH = "android.media.mediacodec.width";
- field public static final java.lang.String MODE_AUDIO = "audio";
- field public static final java.lang.String MODE_VIDEO = "video";
- }
-
- public static final class MediaMetricsSet.MediaExtractor {
- field public static final java.lang.String KEY_FORMAT = "android.media.mediaextractor.fmt";
- field public static final java.lang.String KEY_MIME = "android.media.mediaextractor.mime";
- field public static final java.lang.String KEY_TRACKS = "android.media.mediaextractor.ntrk";
- }
-
- public static final class MediaMetricsSet.MediaPlayer {
- field public static final java.lang.String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
- field public static final java.lang.String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec";
- field public static final java.lang.String KEY_DURATION = "android.media.mediaplayer.durationMs";
- field public static final java.lang.String KEY_ERRORS = "android.media.mediaplayer.err";
- field public static final java.lang.String KEY_ERROR_CODE = "android.media.mediaplayer.errcode";
- field public static final java.lang.String KEY_FRAMES = "android.media.mediaplayer.frames";
- field public static final java.lang.String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped";
- field public static final java.lang.String KEY_HEIGHT = "android.media.mediaplayer.height";
- field public static final java.lang.String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime";
- field public static final java.lang.String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime";
- field public static final java.lang.String KEY_PLAYING = "android.media.mediaplayer.playingMs";
- field public static final java.lang.String KEY_WIDTH = "android.media.mediaplayer.width";
- }
-
- public static final class MediaMetricsSet.MediaRecorder {
- field public static final java.lang.String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
- field public static final java.lang.String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
- field public static final java.lang.String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
- field public static final java.lang.String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
- field public static final java.lang.String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
- field public static final java.lang.String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
- field public static final java.lang.String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate";
- field public static final java.lang.String KEY_HEIGHT = "android.media.mediarecorder.height";
- field public static final java.lang.String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
- field public static final java.lang.String KEY_ROTATION = "android.media.mediarecorder.rotation";
- field public static final java.lang.String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
- field public static final java.lang.String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
- field public static final java.lang.String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
- field public static final java.lang.String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
- field public static final java.lang.String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
- field public static final java.lang.String KEY_WIDTH = "android.media.mediarecorder.width";
- }
-
public final class MediaMuxer {
ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException;
@@ -22893,7 +22883,7 @@
method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
method public int getDuration();
method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
- method public android.media.MediaMetricsSet getMetrics();
+ method public android.os.PersistableBundle getMetrics();
method public android.media.PlaybackParams getPlaybackParams();
method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
method public android.media.SyncParams getSyncParams();
@@ -22988,6 +22978,21 @@
method public java.util.UUID[] getSupportedSchemes();
}
+ public static final class MediaPlayer.MetricsConstants {
+ field public static final java.lang.String CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
+ field public static final java.lang.String CODEC_VIDEO = "android.media.mediaplayer.video.codec";
+ field public static final java.lang.String DURATION = "android.media.mediaplayer.durationMs";
+ field public static final java.lang.String ERRORS = "android.media.mediaplayer.err";
+ field public static final java.lang.String ERROR_CODE = "android.media.mediaplayer.errcode";
+ field public static final java.lang.String FRAMES = "android.media.mediaplayer.frames";
+ field public static final java.lang.String FRAMES_DROPPED = "android.media.mediaplayer.dropped";
+ field public static final java.lang.String HEIGHT = "android.media.mediaplayer.height";
+ field public static final java.lang.String MIME_TYPE_AUDIO = "android.media.mediaplayer.audio.mime";
+ field public static final java.lang.String MIME_TYPE_VIDEO = "android.media.mediaplayer.video.mime";
+ field public static final java.lang.String PLAYING = "android.media.mediaplayer.playingMs";
+ field public static final java.lang.String WIDTH = "android.media.mediaplayer.width";
+ }
+
public static final class MediaPlayer.NoDrmSchemeException extends android.media.MediaDrmException {
ctor public MediaPlayer.NoDrmSchemeException(java.lang.String);
}
@@ -23062,7 +23067,7 @@
ctor public MediaRecorder();
method public static final int getAudioSourceMax();
method public int getMaxAmplitude() throws java.lang.IllegalStateException;
- method public android.media.MediaMetricsSet getMetrics();
+ method public android.os.PersistableBundle getMetrics();
method public android.view.Surface getSurface();
method public void pause() throws java.lang.IllegalStateException;
method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
@@ -23081,11 +23086,12 @@
method public void setMaxDuration(int) throws java.lang.IllegalArgumentException;
method public void setMaxFileSize(long) throws java.lang.IllegalArgumentException;
method public void setNextOutputFile(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalStateException;
- method public void setNextOutputFile(java.lang.String) throws java.io.IOException, java.lang.IllegalStateException;
+ method public void setNextOutputFile(java.io.File) throws java.io.IOException, java.lang.IllegalStateException;
method public void setOnErrorListener(android.media.MediaRecorder.OnErrorListener);
method public void setOnInfoListener(android.media.MediaRecorder.OnInfoListener);
method public void setOrientationHint(int);
method public void setOutputFile(java.io.FileDescriptor) throws java.lang.IllegalStateException;
+ method public void setOutputFile(java.io.File);
method public void setOutputFile(java.lang.String) throws java.lang.IllegalStateException;
method public void setOutputFormat(int) throws java.lang.IllegalStateException;
method public void setPreviewDisplay(android.view.Surface);
@@ -23130,6 +23136,25 @@
field public static final int VOICE_UPLINK = 2; // 0x2
}
+ public static final class MediaRecorder.MetricsConstants {
+ field public static final java.lang.String AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
+ field public static final java.lang.String AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
+ field public static final java.lang.String AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
+ field public static final java.lang.String AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
+ field public static final java.lang.String CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
+ field public static final java.lang.String CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
+ field public static final java.lang.String FRAMERATE = "android.media.mediarecorder.frame-rate";
+ field public static final java.lang.String HEIGHT = "android.media.mediarecorder.height";
+ field public static final java.lang.String MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
+ field public static final java.lang.String ROTATION = "android.media.mediarecorder.rotation";
+ field public static final java.lang.String VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
+ field public static final java.lang.String VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
+ field public static final java.lang.String VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
+ field public static final java.lang.String VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
+ field public static final java.lang.String VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
+ field public static final java.lang.String WIDTH = "android.media.mediarecorder.width";
+ }
+
public static abstract interface MediaRecorder.OnErrorListener {
method public abstract void onError(android.media.MediaRecorder, int, int);
}
@@ -25889,6 +25914,10 @@
method public android.net.NetworkRequest.Builder removeCapability(int);
method public android.net.NetworkRequest.Builder removeTransportType(int);
method public android.net.NetworkRequest.Builder setNetworkSpecifier(java.lang.String);
+ method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier);
+ }
+
+ public abstract class NetworkSpecifier {
}
public class ParseException extends java.lang.RuntimeException {
@@ -37188,8 +37217,10 @@
method public final android.os.IBinder onBind(android.content.Intent);
method public void onConnected();
method public void onDisconnected();
- method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback);
- method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
+ method public void onFillRequest(android.service.autofill.FillRequest, android.os.CancellationSignal, android.service.autofill.FillCallback);
+ method public abstract deprecated void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback);
+ method public void onSaveRequest(android.service.autofill.SaveRequest, android.service.autofill.SaveCallback);
+ method public abstract deprecated void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillService";
field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
}
@@ -37214,6 +37245,25 @@
method public void onSuccess(android.service.autofill.FillResponse);
}
+ public final class FillContext implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getRequestId();
+ method public android.app.assist.AssistStructure getStructure();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.autofill.FillContext> CREATOR;
+ }
+
+ public final class FillRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.os.Bundle getClientState();
+ method public int getFlags();
+ method public int getId();
+ method public android.app.assist.AssistStructure getStructure();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.autofill.FillRequest> CREATOR;
+ field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
+ }
+
public final class FillResponse implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
@@ -37225,7 +37275,8 @@
method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
method public android.service.autofill.FillResponse build();
method public android.service.autofill.FillResponse.Builder setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews);
- method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+ method public android.service.autofill.FillResponse.Builder setClientState(android.os.Bundle);
+ method public deprecated android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
}
@@ -37254,6 +37305,14 @@
method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
}
+ public final class SaveRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.os.Bundle getClientState();
+ method public java.util.List<android.service.autofill.FillContext> getFillContexts();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.autofill.SaveRequest> CREATOR;
+ }
+
}
package android.service.carrier {
@@ -37928,10 +37987,12 @@
method public int getDesiredMinimumHeight();
method public int getDesiredMinimumWidth();
method public android.view.SurfaceHolder getSurfaceHolder();
+ method public void invalidateColors();
method public boolean isPreview();
method public boolean isVisible();
method public void onApplyWindowInsets(android.view.WindowInsets);
method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
+ method public android.app.WallpaperColors onComputeWallpaperColors();
method public void onCreate(android.view.SurfaceHolder);
method public void onDesiredSizeChanged(int, int);
method public void onDestroy();
@@ -45734,7 +45795,6 @@
method public android.view.animation.Animation getAnimation();
method public android.os.IBinder getApplicationWindowToken();
method public java.lang.String[] getAutofillHints();
- method public int getAutofillMode();
method public int getAutofillType();
method public android.view.autofill.AutofillValue getAutofillValue();
method public android.graphics.drawable.Drawable getBackground();
@@ -45823,7 +45883,6 @@
method public float getPivotX();
method public float getPivotY();
method public android.view.PointerIcon getPointerIcon();
- method public int getResolvedAutofillMode();
method public android.content.res.Resources getResources();
method public final boolean getRevealOnFocusHint();
method public final int getRight();
@@ -46059,7 +46118,6 @@
method public void setAlpha(float);
method public void setAnimation(android.view.animation.Animation);
method public void setAutofillHints(java.lang.String...);
- method public void setAutofillMode(int);
method public void setAutofilled(boolean);
method public void setBackground(android.graphics.drawable.Drawable);
method public void setBackgroundColor(int);
@@ -46216,9 +46274,6 @@
field public static final java.lang.String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
field public static final java.lang.String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
field public static final java.lang.String AUTOFILL_HINT_USERNAME = "username";
- field public static final int AUTOFILL_MODE_AUTO = 1; // 0x1
- field public static final int AUTOFILL_MODE_INHERIT = 0; // 0x0
- field public static final int AUTOFILL_MODE_MANUAL = 2; // 0x2
field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
@@ -46790,7 +46845,6 @@
method public abstract int getLayoutDirection();
method public abstract android.view.ViewParent getParent();
method public abstract android.view.ViewParent getParentForAccessibility();
- method public default int getResolvedAutofillMode();
method public abstract int getTextAlignment();
method public abstract int getTextDirection();
method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect);
@@ -48181,7 +48235,7 @@
field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
field public static final java.lang.String EXTRA_DATA_EXTRAS = "android.view.autofill.extra.DATA_EXTRAS";
- field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
+ field public static final deprecated int FLAG_MANUAL_REQUEST = 1; // 0x1
}
public static abstract class AutofillManager.AutofillCallback {
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 82705fd..1e8370e 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -5,10 +5,6 @@
method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
}
- public static class Notification.Builder {
- method public deprecated android.app.Notification.Builder chooseBadgeIcon(int);
- }
-
public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
method public deprecated void showAsNotification(android.content.Context);
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 950991b..b36a160 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -18,6 +18,7 @@
import android.metrics.LogMaker;
import android.graphics.Rect;
+import android.os.SystemClock;
import android.view.ViewRootImpl.ActivityConfigCallback;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
@@ -7433,6 +7434,25 @@
}
}
+ /**
+ * Return the timestamp at which this activity start was last initiated by the system in the
+ * {@link SystemClock#uptimeMillis()} time base.
+ *
+ * This can be used to understand how much time is taken for an activity to be started and
+ * displayed to the user.
+ *
+ * @return timestamp at which this activity start was initiated by the system
+ * or {@code 0} if for any reason the timestamp could not be retrieved.
+ */
+ public long getStartInitiatedTime() {
+ try {
+ return ActivityManager.getService().getActivityStartInitiatedTime(mToken);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to call getActivityStartTime", e);
+ return 0;
+ }
+ }
+
class HostCallbacks extends FragmentHostCallback<Activity> {
public HostCallbacks() {
super(Activity.this /*activity*/);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index a6838f8b..e07b7e4 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -2639,4 +2639,13 @@
throw e.rethrowAsRuntimeException();
}
}
+
+ @Override
+ public ComponentName getInstantAppInstallerComponent() {
+ try {
+ return mPM.getInstantAppInstallerComponent();
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index fc827a9..4210d2e 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -632,6 +632,8 @@
*/
void backgroundWhitelistUid(int uid);
+ long getActivityStartInitiatedTime(IBinder token);
+
// WARNING: when these transactions are updated, check if they are any callers on the native
// side. If so, make sure they are using the correct transaction ids and arguments.
// If a transaction which will also be used on the native side is being inserted, add it
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 7f26f4f..ed316bd 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2339,7 +2339,9 @@
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
- sb.append("Notification(pri=");
+ sb.append("Notification(channel=");
+ sb.append(getChannel());
+ sb.append(" pri=");
sb.append(priority);
sb.append(" contentView=");
if (contentView != null) {
@@ -2729,21 +2731,6 @@
}
/**
- * @removed
- * Sets which icon to display as a badge for this notification.
- *
- * Must be one of {@link #BADGE_ICON_NONE}, {@link #BADGE_ICON_SMALL},
- * {@link #BADGE_ICON_LARGE}.
- *
- * Note: This value might be ignored, for launchers that don't support badge icons.
- */
- @Deprecated
- public Builder chooseBadgeIcon(int icon) {
- mN.mBadgeIcon = icon;
- return this;
- }
-
- /**
* Sets which icon to display as a badge for this notification.
*
* Must be one of {@link #BADGE_ICON_NONE}, {@link #BADGE_ICON_SMALL},
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 3191eec..6f326de 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -112,13 +112,6 @@
private final ArrayMap<Pair<Integer, DisplayAdjustments>, WeakReference<Display>>
mAdjustedDisplays = new ArrayMap<>();
- /**
- * A cache of DisplayId, Resources to Display. These display adjustments associated with these
- * {@link Display}s will change as the resources change.
- */
- private final ArrayMap<Pair<Integer, ResourcesKey>, WeakReference<Display>> mResourceDisplays =
- new ArrayMap<>();
-
public static ResourcesManager getInstance() {
synchronized (ResourcesManager.class) {
if (sResourcesManager == null) {
@@ -251,51 +244,16 @@
*/
public Display getAdjustedDisplay(final int displayId, Resources resources) {
synchronized (this) {
- // Note that the ResourcesKey might be {@code null} in the case that the
- // {@link Resources} is actually from {@link Resources#getSystem}. In this case, it is
- // not managed by {@link ResourcesManager}, but we still want to cache the display
- // object.
- final Pair<Integer, ResourcesKey> key = Pair.create(displayId,
- findKeyForResourceImplLocked(resources.getImpl()));
-
- WeakReference<Display> wd = mResourceDisplays.get(key);
- if (wd != null) {
- final Display display = wd.get();
- if (display != null) {
- return display;
- }
- }
final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
if (dm == null) {
// may be null early in system startup
return null;
}
- final Display display = dm.getCompatibleDisplay(displayId, resources);
- if (display != null) {
- mResourceDisplays.put(key, new WeakReference<>(display));
- }
- return display;
+ return dm.getCompatibleDisplay(displayId, resources);
}
}
private void cleanupResourceImpl(ResourcesKey removedKey) {
- // Remove any resource to display mapping based on this key.
- final Iterator<Map.Entry<Pair<Integer, ResourcesKey>, WeakReference<Display>>> iter =
- mResourceDisplays.entrySet().iterator();
- while (iter.hasNext()) {
- final Map.Entry<Pair<Integer, ResourcesKey>, WeakReference<Display>> entry =
- iter.next();
- final ResourcesKey key = entry.getKey().second;
-
- // Do not touch system resource displays (indicated by a {@code null} key) or
- // non-matching keys.
- if (key == null || !key.equals(removedKey)) {
- continue;
- }
-
- iter.remove();
- }
-
// Remove resource key to resource impl mapping and flush cache
final ResourcesImpl res = mResourceImpls.remove(removedKey).get();
@@ -887,7 +845,6 @@
int changes = mResConfiguration.updateFrom(config);
// Things might have changed in display manager, so clear the cached displays.
mAdjustedDisplays.clear();
- mResourceDisplays.clear();
DisplayMetrics defaultDisplayMetrics = getDisplayMetrics();
diff --git a/core/java/android/app/WallpaperColors.java b/core/java/android/app/WallpaperColors.java
new file mode 100644
index 0000000..5ed66ca
--- /dev/null
+++ b/core/java/android/app/WallpaperColors.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.app;
+
+import android.graphics.Color;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import android.util.Pair;
+
+import java.util.List;
+
+/**
+ * A class containing information about the colors of a wallpaper.
+ */
+public final class WallpaperColors implements Parcelable {
+
+ public WallpaperColors(Parcel parcel) {
+ }
+
+ /**
+ * Wallpaper color details containing a list of colors and their weights,
+ * as if it were an histogram.
+ * This list can be extracted from a bitmap by the Palette API.
+ *
+ * Dark text support will be calculated internally based on the histogram.
+ *
+ * @param colors list of pairs where each pair contains a color
+ * and number of occurrences/influence.
+ */
+ public WallpaperColors(List<Pair<Color, Integer>> colors) {
+ }
+
+ /**
+ * Wallpaper color details containing a list of colors and their weights,
+ * as if it were an histogram.
+ * Explicit dark text support.
+ *
+ * @param colors list of pairs where each pair contains a color
+ * and number of occurrences/influence.
+ * @param supportsDarkText can have dark text on top or not
+ */
+ public WallpaperColors(List<Pair<Color, Integer>> colors, boolean supportsDarkText) {
+ }
+
+ public static final Creator<WallpaperColors> CREATOR = new Creator<WallpaperColors>() {
+ @Override
+ public WallpaperColors createFromParcel(Parcel in) {
+ return new WallpaperColors(in);
+ }
+
+ @Override
+ public WallpaperColors[] newArray(int size) {
+ return new WallpaperColors[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ }
+
+ /**
+ * List of colors with their occurrences. The bigger the int, the more relevant the color.
+ * @return list of colors paired with their weights.
+ */
+ public List<Pair<Color, Integer>> getColors() {
+ return null;
+ }
+
+ /**
+ * Whether or not dark text is legible on top of this wallpaper.
+ *
+ * @return true if dark text is supported
+ */
+ public boolean supportsDarkText() {
+ return false;
+ }
+}
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index aa0eaae..0676bca 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -17,6 +17,8 @@
package android.app;
import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RawRes;
import android.annotation.SystemApi;
import android.content.ComponentName;
@@ -741,6 +743,43 @@
return getWallpaperFile(which, mContext.getUserId());
}
+
+ /**
+ * Registers a listener to get notified when the wallpaper colors change.
+ * Callback might be called from an arbitrary background thread.
+ *
+ * @param listener A listener to register
+ */
+ public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener) {
+ }
+
+ /**
+ * Registers a listener to get notified when the wallpaper colors change
+ * @param listener A listener to register
+ * @param handler Where to call it from. Might be called from a background thread
+ * if null.
+ */
+ public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener,
+ @Nullable Handler handler) {
+ }
+
+ /**
+ * Stop listening to color updates.
+ * @param callback A callback to unsubscribe
+ */
+ public void removeOnColorsChangedListener(@NonNull OnColorsChangedListener callback) {
+ }
+
+ /**
+ * Get the primary colors of a wallpaper
+ * @param which wallpaper type. Must be either {@link #FLAG_SYSTEM} or
+ * {@link #FLAG_LOCK}
+ * @return a list of colors ordered by priority
+ */
+ public @Nullable WallpaperColors getWallpaperColors(int which) {
+ return null;
+ }
+
/**
* Version of {@link #getWallpaperFile(int)} that can access the wallpaper data
* for a given user. The caller must hold the INTERACT_ACROSS_USERS_FULL
@@ -1732,4 +1771,19 @@
mLatch.countDown();
}
}
+
+ /**
+ * Interface definition for a callback to be invoked when colors change on a wallpaper.
+ */
+ public interface OnColorsChangedListener {
+ /**
+ * Called when colors change.
+ * A {@link android.app.WallpaperColors} object containing a simplified
+ * color histogram will be given.
+ *
+ * @param colors Wallpaper color info
+ * @param which A combination of {@link #FLAG_LOCK} and {@link #FLAG_SYSTEM}
+ */
+ void onColorsChanged(WallpaperColors colors, int which);
+ }
}
diff --git a/core/java/android/app/job/JobService.java b/core/java/android/app/job/JobService.java
index f4019ce..9096b47 100644
--- a/core/java/android/app/job/JobService.java
+++ b/core/java/android/app/job/JobService.java
@@ -60,161 +60,24 @@
public static final String PERMISSION_BIND =
"android.permission.BIND_JOB_SERVICE";
- /**
- * Identifier for a message that will result in a call to
- * {@link #onStartJob(android.app.job.JobParameters)}.
- */
- private static final int MSG_EXECUTE_JOB = 0;
- /**
- * Message that will result in a call to {@link #onStopJob(android.app.job.JobParameters)}.
- */
- private static final int MSG_STOP_JOB = 1;
- /**
- * Message that the client has completed execution of this job.
- */
- private static final int MSG_JOB_FINISHED = 2;
-
- /** Lock object for {@link #mHandler}. */
- private final Object mHandlerLock = new Object();
-
- /**
- * Handler we post jobs to. Responsible for calling into the client logic, and handling the
- * callback to the system.
- */
- @GuardedBy("mHandlerLock")
- JobHandler mHandler;
-
- static final class JobInterface extends IJobService.Stub {
- final WeakReference<JobService> mService;
-
- JobInterface(JobService service) {
- mService = new WeakReference<>(service);
- }
-
- @Override
- public void startJob(JobParameters jobParams) throws RemoteException {
- JobService service = mService.get();
- if (service != null) {
- service.ensureHandler();
- Message m = Message.obtain(service.mHandler, MSG_EXECUTE_JOB, jobParams);
- m.sendToTarget();
- }
- }
-
- @Override
- public void stopJob(JobParameters jobParams) throws RemoteException {
- JobService service = mService.get();
- if (service != null) {
- service.ensureHandler();
- Message m = Message.obtain(service.mHandler, MSG_STOP_JOB, jobParams);
- m.sendToTarget();
- }
-
- }
- }
-
- IJobService mBinder;
-
- /** @hide */
- void ensureHandler() {
- synchronized (mHandlerLock) {
- if (mHandler == null) {
- mHandler = new JobHandler(getMainLooper());
- }
- }
- }
-
- /**
- * Runs on application's main thread - callbacks are meant to offboard work to some other
- * (app-specified) mechanism.
- * @hide
- */
- class JobHandler extends Handler {
- JobHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- final JobParameters params = (JobParameters) msg.obj;
- switch (msg.what) {
- case MSG_EXECUTE_JOB:
- try {
- boolean workOngoing = JobService.this.onStartJob(params);
- ackStartMessage(params, workOngoing);
- } catch (Exception e) {
- Log.e(TAG, "Error while executing job: " + params.getJobId());
- throw new RuntimeException(e);
- }
- break;
- case MSG_STOP_JOB:
- try {
- boolean ret = JobService.this.onStopJob(params);
- ackStopMessage(params, ret);
- } catch (Exception e) {
- Log.e(TAG, "Application unable to handle onStopJob.", e);
- throw new RuntimeException(e);
- }
- break;
- case MSG_JOB_FINISHED:
- final boolean needsReschedule = (msg.arg2 == 1);
- IJobCallback callback = params.getCallback();
- if (callback != null) {
- try {
- callback.jobFinished(params.getJobId(), needsReschedule);
- } catch (RemoteException e) {
- Log.e(TAG, "Error reporting job finish to system: binder has gone" +
- "away.");
- }
- } else {
- Log.e(TAG, "finishJob() called for a nonexistent job id.");
- }
- break;
- default:
- Log.e(TAG, "Unrecognised message received.");
- break;
- }
- }
-
- private void ackStartMessage(JobParameters params, boolean workOngoing) {
- final IJobCallback callback = params.getCallback();
- final int jobId = params.getJobId();
- if (callback != null) {
- try {
- callback.acknowledgeStartMessage(jobId, workOngoing);
- } catch(RemoteException e) {
- Log.e(TAG, "System unreachable for starting job.");
- }
- } else {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Attempting to ack a job that has already been processed.");
- }
- }
- }
-
- private void ackStopMessage(JobParameters params, boolean reschedule) {
- final IJobCallback callback = params.getCallback();
- final int jobId = params.getJobId();
- if (callback != null) {
- try {
- callback.acknowledgeStopMessage(jobId, reschedule);
- } catch(RemoteException e) {
- Log.e(TAG, "System unreachable for stopping job.");
- }
- } else {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Attempting to ack a job that has already been processed.");
- }
- }
- }
- }
+ private JobServiceEngine mEngine;
/** @hide */
public final IBinder onBind(Intent intent) {
- if (mBinder == null) {
- mBinder = new JobInterface(this);
+ if (mEngine == null) {
+ mEngine = new JobServiceEngine(this) {
+ @Override
+ public boolean onStartJob(JobParameters params) {
+ return JobService.this.onStartJob(params);
+ }
+
+ @Override
+ public boolean onStopJob(JobParameters params) {
+ return JobService.this.onStopJob(params);
+ }
+ };
}
- return mBinder.asBinder();
+ return mEngine.getBinder();
}
/**
@@ -269,9 +132,6 @@
* criteria specified at schedule-time. False otherwise.
*/
public final void jobFinished(JobParameters params, boolean needsReschedule) {
- ensureHandler();
- Message m = Message.obtain(mHandler, MSG_JOB_FINISHED, params);
- m.arg2 = needsReschedule ? 1 : 0;
- m.sendToTarget();
+ mEngine.jobFinished(params, needsReschedule);
}
}
\ No newline at end of file
diff --git a/core/java/android/app/job/JobServiceEngine.java b/core/java/android/app/job/JobServiceEngine.java
new file mode 100644
index 0000000..879212e
--- /dev/null
+++ b/core/java/android/app/job/JobServiceEngine.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.app.job;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * Helper for implementing a {@link android.app.Service} that interacts with
+ * {@link JobScheduler}.
+ */
+public abstract class JobServiceEngine {
+ private static final String TAG = "JobServiceEngine";
+
+ /**
+ * Identifier for a message that will result in a call to
+ * {@link #onStartJob(android.app.job.JobParameters)}.
+ */
+ private static final int MSG_EXECUTE_JOB = 0;
+ /**
+ * Message that will result in a call to {@link #onStopJob(android.app.job.JobParameters)}.
+ */
+ private static final int MSG_STOP_JOB = 1;
+ /**
+ * Message that the client has completed execution of this job.
+ */
+ private static final int MSG_JOB_FINISHED = 2;
+
+ /**
+ * Context we are running in.
+ */
+ private final Context mContext;
+
+ private final IJobService mBinder;
+
+ /** Lock object for {@link #mHandler}. */
+ private final Object mHandlerLock = new Object();
+
+ /**
+ * Handler we post jobs to. Responsible for calling into the client logic, and handling the
+ * callback to the system.
+ */
+ @GuardedBy("mHandlerLock")
+ JobHandler mHandler;
+
+ static final class JobInterface extends IJobService.Stub {
+ final WeakReference<JobServiceEngine> mService;
+
+ JobInterface(JobServiceEngine service) {
+ mService = new WeakReference<>(service);
+ }
+
+ @Override
+ public void startJob(JobParameters jobParams) throws RemoteException {
+ JobServiceEngine service = mService.get();
+ if (service != null) {
+ Message m = Message.obtain(service.mHandler, MSG_EXECUTE_JOB, jobParams);
+ m.sendToTarget();
+ }
+ }
+
+ @Override
+ public void stopJob(JobParameters jobParams) throws RemoteException {
+ JobServiceEngine service = mService.get();
+ if (service != null) {
+ Message m = Message.obtain(service.mHandler, MSG_STOP_JOB, jobParams);
+ m.sendToTarget();
+ }
+ }
+ }
+
+ /**
+ * Runs on application's main thread - callbacks are meant to offboard work to some other
+ * (app-specified) mechanism.
+ * @hide
+ */
+ class JobHandler extends Handler {
+ JobHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ final JobParameters params = (JobParameters) msg.obj;
+ switch (msg.what) {
+ case MSG_EXECUTE_JOB:
+ try {
+ boolean workOngoing = JobServiceEngine.this.onStartJob(params);
+ ackStartMessage(params, workOngoing);
+ } catch (Exception e) {
+ Log.e(TAG, "Error while executing job: " + params.getJobId());
+ throw new RuntimeException(e);
+ }
+ break;
+ case MSG_STOP_JOB:
+ try {
+ boolean ret = JobServiceEngine.this.onStopJob(params);
+ ackStopMessage(params, ret);
+ } catch (Exception e) {
+ Log.e(TAG, "Application unable to handle onStopJob.", e);
+ throw new RuntimeException(e);
+ }
+ break;
+ case MSG_JOB_FINISHED:
+ final boolean needsReschedule = (msg.arg2 == 1);
+ IJobCallback callback = params.getCallback();
+ if (callback != null) {
+ try {
+ callback.jobFinished(params.getJobId(), needsReschedule);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error reporting job finish to system: binder has gone" +
+ "away.");
+ }
+ } else {
+ Log.e(TAG, "finishJob() called for a nonexistent job id.");
+ }
+ break;
+ default:
+ Log.e(TAG, "Unrecognised message received.");
+ break;
+ }
+ }
+
+ private void ackStartMessage(JobParameters params, boolean workOngoing) {
+ final IJobCallback callback = params.getCallback();
+ final int jobId = params.getJobId();
+ if (callback != null) {
+ try {
+ callback.acknowledgeStartMessage(jobId, workOngoing);
+ } catch(RemoteException e) {
+ Log.e(TAG, "System unreachable for starting job.");
+ }
+ } else {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Attempting to ack a job that has already been processed.");
+ }
+ }
+ }
+
+ private void ackStopMessage(JobParameters params, boolean reschedule) {
+ final IJobCallback callback = params.getCallback();
+ final int jobId = params.getJobId();
+ if (callback != null) {
+ try {
+ callback.acknowledgeStopMessage(jobId, reschedule);
+ } catch(RemoteException e) {
+ Log.e(TAG, "System unreachable for stopping job.");
+ }
+ } else {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Attempting to ack a job that has already been processed.");
+ }
+ }
+ }
+ }
+
+ /**
+ * Create a new engine, ready for use.
+ *
+ * @param context The {@link Service} that is creating this engine.
+ */
+ public JobServiceEngine(Context context) {
+ mContext = context;
+ mBinder = new JobInterface(this);
+ mHandler = new JobHandler(mContext.getMainLooper());
+ }
+
+ /**
+ * Retrieve the engine's IPC interface that should be returned by
+ * {@link Service#onBind(Intent)}.
+ */
+ public final IBinder getBinder() {
+ return mBinder.asBinder();
+ }
+
+ /**
+ * Engine's report that a job has started. See
+ * {@link JobService#onStartJob(JobParameters) JobService.onStartJob} for more information.
+ */
+ public abstract boolean onStartJob(JobParameters params);
+
+ /**
+ * Engine's report that a job has stopped. See
+ * {@link JobService#onStopJob(JobParameters) JobService.onStopJob} for more information.
+ */
+ public abstract boolean onStopJob(JobParameters params);
+
+ /**
+ * Call in to engine to report that a job has finished executing. See
+ * {@link JobService#jobFinished(JobParameters, boolean)} JobService.jobFinished} for more
+ * information.
+ */
+ public final void jobFinished(JobParameters params, boolean needsReschedule) {
+ Message m = Message.obtain(mHandler, MSG_JOB_FINISHED, params);
+ m.arg2 = needsReschedule ? 1 : 0;
+ m.sendToTarget();
+ }
+}
\ No newline at end of file
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 334e88b..582709c 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -16,6 +16,7 @@
package android.bluetooth;
+import android.app.PendingIntent;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.le.AdvertiseSettings;
@@ -47,6 +48,9 @@
void unregisterScanner(in int scannerId);
void startScan(in int scannerId, in ScanSettings settings, in List<ScanFilter> filters,
in WorkSource workSource, in List scanStorages, in String callingPackage);
+ void startScanForIntent(in PendingIntent intent, in ScanSettings settings, in List<ScanFilter> filters,
+ in String callingPackage);
+ void stopScanForIntent(in PendingIntent intent, in String callingPackage);
void stopScan(in int scannerId);
void flushPendingBatchResults(in int scannerId);
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index b63c614..b65a7ad 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -17,17 +17,18 @@
package android.bluetooth.le;
import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.app.ActivityThread;
+import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.IBluetoothGatt;
import android.bluetooth.IBluetoothManager;
-import android.bluetooth.le.IScannerCallback;
import android.os.Handler;
import android.os.Looper;
-import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.WorkSource;
import android.util.Log;
@@ -36,7 +37,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.UUID;
/**
* This class provides methods to perform scan related operations for Bluetooth LE devices. An
@@ -57,6 +57,27 @@
private static final boolean DBG = true;
private static final boolean VDBG = false;
+ /**
+ * Extra containing a list of ScanResults. It can have one or more results if there was no
+ * error. In case of error, {@link #EXTRA_ERROR_CODE} will contain the error code and this
+ * extra will not be available.
+ */
+ public static final String EXTRA_LIST_SCAN_RESULT
+ = "android.bluetooth.le.extra.LIST_SCAN_RESULT";
+
+ /**
+ * Optional extra indicating the error code, if any. The error code will be one of the
+ * SCAN_FAILED_* codes in {@link ScanCallback}.
+ */
+ public static final String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
+
+ /**
+ * Optional extra indicating the callback type, which will be one of
+ * ScanSettings.CALLBACK_TYPE_*.
+ * @see ScanCallback#onScanResult(int, ScanResult)
+ */
+ public static final String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
+
private final IBluetoothManager mBluetoothManager;
private final Handler mHandler;
private BluetoothAdapter mBluetoothAdapter;
@@ -110,7 +131,27 @@
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public void startScan(List<ScanFilter> filters, ScanSettings settings,
final ScanCallback callback) {
- startScan(filters, settings, null, callback, null);
+ startScan(filters, settings, null, callback, /*callbackIntent=*/ null, null);
+ }
+
+ /**
+ * Start Bluetooth LE scan using a {@link PendingIntent}. The scan results will be delivered via
+ * the PendingIntent. Use this method of scanning if your process is not always running and it
+ * should be started when scan results are available.
+ *
+ * @param filters Optional list of ScanFilters for finding exact BLE devices.
+ * @param settings Optional settings for the scan.
+ * @param callbackIntent The PendingIntent to deliver the result to.
+ * @return Returns 0 for success or an error code from {@link ScanCallback} if the scan request
+ * could not be sent.
+ * @see #stopScan(PendingIntent)
+ */
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ public int startScan(@Nullable List<ScanFilter> filters, @Nullable ScanSettings settings,
+ @NonNull PendingIntent callbackIntent) {
+ return startScan(filters,
+ settings != null ? settings : new ScanSettings.Builder().build(),
+ null, null, callbackIntent, null);
}
/**
@@ -145,23 +186,23 @@
Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.UPDATE_DEVICE_STATS })
public void startScanFromSource(List<ScanFilter> filters, ScanSettings settings,
final WorkSource workSource, final ScanCallback callback) {
- startScan(filters, settings, workSource, callback, null);
+ startScan(filters, settings, workSource, callback, null, null);
}
- private void startScan(List<ScanFilter> filters, ScanSettings settings,
+ private int startScan(List<ScanFilter> filters, ScanSettings settings,
final WorkSource workSource, final ScanCallback callback,
+ final PendingIntent callbackIntent,
List<List<ResultStorageDescriptor>> resultStorages) {
BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
- if (callback == null) {
+ if (callback == null && callbackIntent == null) {
throw new IllegalArgumentException("callback is null");
}
if (settings == null) {
throw new IllegalArgumentException("settings is null");
}
synchronized (mLeScanClients) {
- if (mLeScanClients.containsKey(callback)) {
+ if (callback != null && mLeScanClients.containsKey(callback)) {
postCallbackError(callback, ScanCallback.SCAN_FAILED_ALREADY_STARTED);
- return;
}
IBluetoothGatt gatt;
try {
@@ -170,28 +211,34 @@
gatt = null;
}
if (gatt == null) {
- postCallbackError(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR);
- return;
+ return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR);
}
if (!isSettingsConfigAllowedForScan(settings)) {
- postCallbackError(callback,
- ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
- return;
+ return postCallbackErrorOrReturn(callback,
+ ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
}
if (!isHardwareResourcesAvailableForScan(settings)) {
- postCallbackError(callback,
- ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES);
- return;
+ return postCallbackErrorOrReturn(callback,
+ ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES);
}
if (!isSettingsAndFilterComboAllowed(settings, filters)) {
- postCallbackError(callback,
+ return postCallbackErrorOrReturn(callback,
ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
- return;
}
- BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters,
- settings, workSource, callback, resultStorages);
- wrapper.startRegisteration();
+ if (callback != null) {
+ BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters,
+ settings, workSource, callback, resultStorages);
+ wrapper.startRegistration();
+ } else {
+ try {
+ gatt.startScanForIntent(callbackIntent, settings, filters,
+ ActivityThread.currentOpPackageName());
+ } catch (RemoteException e) {
+ return ScanCallback.SCAN_FAILED_INTERNAL_ERROR;
+ }
+ }
}
+ return ScanCallback.NO_ERROR;
}
/**
@@ -215,6 +262,25 @@
}
/**
+ * Stops an ongoing Bluetooth LE scan started using a PendingIntent.
+ * <p>
+ * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+ *
+ * @param callbackIntent The PendingIntent that was used to start the scan.
+ * @see #startScan(List, ScanSettings, PendingIntent)
+ */
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ public void stopScan(PendingIntent callbackIntent) {
+ BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
+ IBluetoothGatt gatt;
+ try {
+ gatt = mBluetoothManager.getBluetoothGatt();
+ gatt.stopScanForIntent(callbackIntent, ActivityThread.currentOpPackageName());
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
* Flush pending batch scan results stored in Bluetooth controller. This will return Bluetooth
* LE scan results batched on bluetooth controller. Returns immediately, batch scan results data
* will be delivered through the {@code callback}.
@@ -252,7 +318,7 @@
scanFilters.add(filter.getFilter());
scanStorages.add(filter.getStorageDescriptors());
}
- startScan(scanFilters, settings, null, callback, scanStorages);
+ startScan(scanFilters, settings, null, callback, null, scanStorages);
}
/**
@@ -295,7 +361,7 @@
mResultStorages = resultStorages;
}
- public void startRegisteration() {
+ public void startRegistration() {
synchronized (this) {
// Scan stopped.
if (mScannerId == -1) return;
@@ -399,7 +465,6 @@
mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult);
}
});
-
}
@Override
@@ -453,6 +518,15 @@
}
}
+ private int postCallbackErrorOrReturn(final ScanCallback callback, final int errorCode) {
+ if (callback == null) {
+ return errorCode;
+ } else {
+ postCallbackError(callback, errorCode);
+ return ScanCallback.NO_ERROR;
+ }
+ }
+
private void postCallbackError(final ScanCallback callback, final int errorCode) {
mHandler.post(new Runnable() {
@Override
diff --git a/core/java/android/bluetooth/le/ScanCallback.java b/core/java/android/bluetooth/le/ScanCallback.java
index 61b2e78..aff2e90 100644
--- a/core/java/android/bluetooth/le/ScanCallback.java
+++ b/core/java/android/bluetooth/le/ScanCallback.java
@@ -50,6 +50,8 @@
*/
public static final int SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES = 5;
+ static final int NO_ERROR = 0;
+
/**
* Callback when a BLE advertisement has been found.
*
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index 4d788e7..e50b2a9 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -22,11 +22,13 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
+import android.content.ComponentName;
import android.content.Context;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.RemoteException;
+import android.service.notification.NotificationListenerService;
import android.util.Log;
import java.util.Collections;
@@ -195,22 +197,47 @@
}
}
- /** @hide */
- public void requestNotificationAccess() {
+ /**
+ * Request notification access for the given component.
+ *
+ * The given component must follow the protocol specified in {@link NotificationListenerService}
+ *
+ * Only components from the same {@link ComponentName#getPackageName package} as the calling app
+ * are allowed.
+ *
+ * Your app must have an association with a device before calling this API
+ */
+ public void requestNotificationAccess(ComponentName component) {
if (!checkFeaturePresent()) {
return;
}
- //TODO implement
- throw new UnsupportedOperationException("Not yet implemented");
+ try {
+ mService.requestNotificationAccess(component).send();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (PendingIntent.CanceledException e) {
+ throw new RuntimeException(e);
+ }
}
- /** @hide */
- public boolean haveNotificationAccess() {
+ /**
+ * Check whether the given component can access the notifications via a
+ * {@link NotificationListenerService}
+ *
+ * Your app must have an association with a device before calling this API
+ *
+ * @param component the name of the component
+ * @return whether the given component has the notification listener permission
+ */
+ public boolean hasNotificationAccess(ComponentName component) {
if (!checkFeaturePresent()) {
return false;
}
- //TODO implement
- throw new UnsupportedOperationException("Not yet implemented");
+ try {
+ return mService.hasNotificationAccess(component);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
private boolean checkFeaturePresent() {
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index 7798406..d395208 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -16,8 +16,10 @@
package android.companion;
+import android.app.PendingIntent;
import android.companion.IFindDeviceCallback;
import android.companion.AssociationRequest;
+import android.content.ComponentName;
/**
* Interface for communication with the core companion device manager service.
@@ -32,7 +34,6 @@
List<String> getAssociations(String callingPackage, int userId);
void disassociate(String deviceMacAddress, String callingPackage);
- //TODO add these
-// boolean haveNotificationAccess(String packageName);
-// oneway void requestNotificationAccess(String packageName);
+ boolean hasNotificationAccess(in ComponentName component);
+ PendingIntent requestNotificationAccess(in ComponentName component);
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 0da4f8d..5ca4fa3 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3424,8 +3424,10 @@
/**
* Deprecated - use ACTION_FACTORY_RESET instead.
+ * @hide
*/
@Deprecated
+ @SystemApi
public static final String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
/**
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 147df76..bbc942a 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -632,4 +632,6 @@
void deletePreloadsFileCache();
ComponentName getInstantAppResolverSettingsComponent();
+
+ ComponentName getInstantAppInstallerComponent();
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index e5c8f0d..09906be 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -6275,9 +6275,19 @@
* Return the {@link ComponentName} of the activity providing Settings for the Instant App
* resolver.
*
- * @see {@link android.content.intent#ACTION_INSTANT_APP_RESOLVER_SETTINGS}
+ * @see {@link android.content.Intent#ACTION_INSTANT_APP_RESOLVER_SETTINGS}
* @hide
*/
@SystemApi
public abstract ComponentName getInstantAppResolverSettingsComponent();
+
+ /**
+ * Return the {@link ComponentName} of the activity responsible for installing instant
+ * applications.
+ *
+ * @see {@link android.content.Intent#ACTION_INSTALL_INSTANT_APP_PACKAGE}
+ * @hide
+ */
+ @SystemApi
+ public abstract ComponentName getInstantAppInstallerComponent();
}
diff --git a/core/java/android/net/MatchAllNetworkSpecifier.java b/core/java/android/net/MatchAllNetworkSpecifier.java
new file mode 100644
index 0000000..7aafc93
--- /dev/null
+++ b/core/java/android/net/MatchAllNetworkSpecifier.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * MatchAllNetworkSpecifier is a marker class used by NetworkFactory classes to indicate
+ * that they accept (match) any network specifier in requests.
+ *
+ * The class must never be used as part of a network request (those semantics aren't specified).
+ *
+ * @hide
+ */
+public final class MatchAllNetworkSpecifier extends NetworkSpecifier implements Parcelable {
+ /**
+ * Utility method which verifies that the ns argument is not a MatchAllNetworkSpecifier and
+ * throws an IllegalArgumentException if it is.
+ */
+ public static void checkNotMatchAllNetworkSpecifier(NetworkSpecifier ns) {
+ if (ns instanceof MatchAllNetworkSpecifier) {
+ throw new IllegalArgumentException("A MatchAllNetworkSpecifier is not permitted");
+ }
+ }
+
+ public boolean satisfiedBy(NetworkSpecifier other) {
+ /*
+ * The method is called by a NetworkRequest to see if it is satisfied by a proposed
+ * network (e.g. as offered by a network factory). Since MatchAllNetweorkSpecifier must
+ * not be used in network requests this method should never be called.
+ */
+ throw new IllegalStateException(
+ "MatchAllNetworkSpecifier must not be used in NetworkRequests");
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof MatchAllNetworkSpecifier;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ // Nothing to write.
+ }
+
+ public static final Parcelable.Creator<MatchAllNetworkSpecifier> CREATOR =
+ new Parcelable.Creator<MatchAllNetworkSpecifier>() {
+ public MatchAllNetworkSpecifier createFromParcel(Parcel in) {
+ return new MatchAllNetworkSpecifier();
+ }
+ public MatchAllNetworkSpecifier[] newArray(int size) {
+ return new MatchAllNetworkSpecifier[size];
+ }
+ };
+}
diff --git a/core/java/android/net/NetworkBadging.java b/core/java/android/net/NetworkBadging.java
index 4409d0a..b4ef695 100644
--- a/core/java/android/net/NetworkBadging.java
+++ b/core/java/android/net/NetworkBadging.java
@@ -56,7 +56,7 @@
*
* @param signalLevel The level returned by {@link WifiManager#calculateSignalLevel(int, int)}
* for a network. Must be between 0 and {@link WifiManager#RSSI_LEVELS}-1.
- * @param badging {@see ScoredNetwork#Badging}, retrieved from
+ * @param badging {@see NetworkBadging#Badging}, retrieved from
* {@link ScoredNetwork#calculateBadge(int)}.
* @param theme The theme for the current application, may be null.
* @return Drawable for the given icon
@@ -140,7 +140,7 @@
* <p>This badge should be displayed with the badge signal resource retrieved from
* {@link #getBadgedWifiSignalResource(int)}.
*
- * @param badging {@see ScoredNetwork#Badging} from {@link ScoredNetwork#calculateBadge(int)}.
+ * @param badging {@see NetworkBadging#Badging} from {@link ScoredNetwork#calculateBadge(int)}.
* @return the @DrawableRes for the icon or {@link View#NO_ID} for
* {@link NetworkBadging#BADGING_NONE}
* @throws IllegalArgumentException for an invalid badging value.
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index a594bef..afca0b0 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -18,9 +18,11 @@
import android.os.Parcel;
import android.os.Parcelable;
-import android.text.TextUtils;
+
import com.android.internal.util.BitUtils;
+import java.util.Objects;
+
/**
* This class represents the capabilities of a network. This is used both to specify
* needs to {@link ConnectivityManager} and when inspecting a network.
@@ -33,6 +35,8 @@
* all cellular based connections are metered and all Wi-Fi based connections are not.
*/
public final class NetworkCapabilities implements Parcelable {
+ private static final String TAG = "NetworkCapabilities";
+
/**
* @hide
*/
@@ -205,19 +209,6 @@
(1 << NET_CAPABILITY_FOREGROUND);
/**
- * Network specifier for factories which want to match any network specifier
- * (NS) in a request. Behavior:
- * <li>Empty NS in request matches any network factory NS</li>
- * <li>Empty NS in the network factory NS only matches a request with an
- * empty NS</li>
- * <li>"*" (this constant) NS in the network factory matches requests with
- * any NS</li>
- *
- * @hide
- */
- public static final String MATCH_ALL_REQUESTS_NETWORK_SPECIFIER = "*";
-
- /**
* Network capabilities that are not allowed in NetworkRequests. This exists because the
* NetworkFactory / NetworkAgent model does not deal well with the situation where a
* capability's presence cannot be known in advance. If such a capability is requested, then we
@@ -579,63 +570,56 @@
this.mLinkDownBandwidthKbps == nc.mLinkDownBandwidthKbps);
}
- private String mNetworkSpecifier;
+ private NetworkSpecifier mNetworkSpecifier = null;
+
/**
* Sets the optional bearer specific network specifier.
* This has no meaning if a single transport is also not specified, so calling
* this without a single transport set will generate an exception, as will
* subsequently adding or removing transports after this is set.
* </p>
- * The interpretation of this {@code String} is bearer specific and bearers that use
- * it should document their particulars. For example, Bluetooth may use some sort of
- * device id while WiFi could used SSID and/or BSSID. Cellular may use carrier SPN (name)
- * or Subscription ID.
*
- * @param networkSpecifier An {@code String} of opaque format used to specify the bearer
- * specific network specifier where the bearer has a choice of
- * networks.
+ * @param networkSpecifier A concrete, parcelable framework class that extends
+ * NetworkSpecifier.
* @return This NetworkCapabilities instance, to facilitate chaining.
* @hide
*/
- public NetworkCapabilities setNetworkSpecifier(String networkSpecifier) {
- if (TextUtils.isEmpty(networkSpecifier) == false && Long.bitCount(mTransportTypes) != 1) {
+ public NetworkCapabilities setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
+ if (networkSpecifier != null && Long.bitCount(mTransportTypes) != 1) {
throw new IllegalStateException("Must have a single transport specified to use " +
"setNetworkSpecifier");
}
+
mNetworkSpecifier = networkSpecifier;
+
return this;
}
/**
* Gets the optional bearer specific network specifier.
*
- * @return The optional {@code String} specifying the bearer specific network specifier.
- * See {@link #setNetworkSpecifier}.
+ * @return The optional {@link NetworkSpecifier} specifying the bearer specific network
+ * specifier. See {@link #setNetworkSpecifier}.
* @hide
*/
- public String getNetworkSpecifier() {
+ public NetworkSpecifier getNetworkSpecifier() {
return mNetworkSpecifier;
}
private void combineSpecifiers(NetworkCapabilities nc) {
- String otherSpecifier = nc.getNetworkSpecifier();
- if (TextUtils.isEmpty(otherSpecifier)) return;
- if (TextUtils.isEmpty(mNetworkSpecifier) == false) {
+ if (mNetworkSpecifier != null && !mNetworkSpecifier.equals(nc.mNetworkSpecifier)) {
throw new IllegalStateException("Can't combine two networkSpecifiers");
}
- setNetworkSpecifier(otherSpecifier);
+ setNetworkSpecifier(nc.mNetworkSpecifier);
}
+
private boolean satisfiedBySpecifier(NetworkCapabilities nc) {
- return (TextUtils.isEmpty(mNetworkSpecifier) ||
- mNetworkSpecifier.equals(nc.mNetworkSpecifier) ||
- MATCH_ALL_REQUESTS_NETWORK_SPECIFIER.equals(nc.mNetworkSpecifier));
+ return mNetworkSpecifier == null || mNetworkSpecifier.satisfiedBy(nc.mNetworkSpecifier)
+ || nc.mNetworkSpecifier instanceof MatchAllNetworkSpecifier;
}
+
private boolean equalsSpecifier(NetworkCapabilities nc) {
- if (TextUtils.isEmpty(mNetworkSpecifier)) {
- return TextUtils.isEmpty(nc.mNetworkSpecifier);
- } else {
- return mNetworkSpecifier.equals(nc.mNetworkSpecifier);
- }
+ return Objects.equals(mNetworkSpecifier, nc.mNetworkSpecifier);
}
/**
@@ -797,7 +781,7 @@
((int)(mTransportTypes >> 32) * 7) +
(mLinkUpBandwidthKbps * 11) +
(mLinkDownBandwidthKbps * 13) +
- (TextUtils.isEmpty(mNetworkSpecifier) ? 0 : mNetworkSpecifier.hashCode() * 17) +
+ Objects.hashCode(mNetworkSpecifier) * 17 +
(mSignalStrength * 19));
}
@@ -811,7 +795,7 @@
dest.writeLong(mTransportTypes);
dest.writeInt(mLinkUpBandwidthKbps);
dest.writeInt(mLinkDownBandwidthKbps);
- dest.writeString(mNetworkSpecifier);
+ dest.writeParcelable((Parcelable) mNetworkSpecifier, flags);
dest.writeInt(mSignalStrength);
}
@@ -825,7 +809,7 @@
netCap.mTransportTypes = in.readLong();
netCap.mLinkUpBandwidthKbps = in.readInt();
netCap.mLinkDownBandwidthKbps = in.readInt();
- netCap.mNetworkSpecifier = in.readString();
+ netCap.mNetworkSpecifier = in.readParcelable(null);
netCap.mSignalStrength = in.readInt();
return netCap;
}
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index cb78009..95a8bb4 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -18,6 +18,7 @@
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
import java.util.Objects;
@@ -259,10 +260,27 @@
* networks.
*/
public Builder setNetworkSpecifier(String networkSpecifier) {
- if (NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER.equals(networkSpecifier)) {
- throw new IllegalArgumentException("Invalid network specifier - must not be '"
- + NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER + "'");
- }
+ /*
+ * A StringNetworkSpecifier does not accept null or empty ("") strings. When network
+ * specifiers were strings a null string and an empty string were considered equivalent.
+ * Hence no meaning is attached to a null or empty ("") string.
+ */
+ return setNetworkSpecifier(TextUtils.isEmpty(networkSpecifier) ? null
+ : new StringNetworkSpecifier(networkSpecifier));
+ }
+
+ /**
+ * Sets the optional bearer specific network specifier.
+ * This has no meaning if a single transport is also not specified, so calling
+ * this without a single transport set will generate an exception, as will
+ * subsequently adding or removing transports after this is set.
+ * </p>
+ *
+ * @param networkSpecifier A concrete, parcelable framework class that extends
+ * NetworkSpecifier.
+ */
+ public Builder setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
+ MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(networkSpecifier);
mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
return this;
}
diff --git a/core/java/android/net/NetworkSpecifier.java b/core/java/android/net/NetworkSpecifier.java
new file mode 100644
index 0000000..87a2b05
--- /dev/null
+++ b/core/java/android/net/NetworkSpecifier.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+/**
+ * Describes specific properties of a network for use in a {@link NetworkRequest}.
+ *
+ * Applications cannot instantiate this class by themselves, but can obtain instances of
+ * subclasses of this class via other APIs.
+ */
+public abstract class NetworkSpecifier {
+ /** @hide */
+ public NetworkSpecifier() {}
+
+ /**
+ * Returns true if a request with this {@link NetworkSpecifier} is satisfied by a network
+ * with the given NetworkSpecifier.
+ *
+ * @hide
+ */
+ public abstract boolean satisfiedBy(NetworkSpecifier other);
+}
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
index a664a8b..666da0a 100644
--- a/core/java/android/net/ScoredNetwork.java
+++ b/core/java/android/net/ScoredNetwork.java
@@ -73,29 +73,6 @@
/** A {@link NetworkKey} uniquely identifying this network. */
public final NetworkKey networkKey;
- // TODO(b/35323372): Delete these once external references are switched.
- /** @deprecated Use {@link NetworkBadging#Badging} instead. */
- @Deprecated
- @IntDef({BADGING_NONE, BADGING_SD, BADGING_HD, BADGING_4K})
- @Retention(RetentionPolicy.SOURCE)
- public @interface Badging {}
-
- /** @deprecated Use {@link NetworkBadging#BADGING_NONE} instead. */
- @Deprecated
- public static final int BADGING_NONE = 0;
-
- /** @deprecated Use {@link NetworkBadging#BADGING_SD} instead. */
- @Deprecated
- public static final int BADGING_SD = 10;
-
- /** @deprecated Use {@link NetworkBadging#BADGING_HD} instead. */
- @Deprecated
- public static final int BADGING_HD = 20;
-
- /** @deprecated Use {@link NetworkBadging#BADGING_4K} instead. */
- @Deprecated
- public static final int BADGING_4K = 30;
-
/**
* The {@link RssiCurve} representing the scores for this network based on the RSSI.
*
diff --git a/core/java/android/net/StringNetworkSpecifier.java b/core/java/android/net/StringNetworkSpecifier.java
new file mode 100644
index 0000000..cb7f6bf
--- /dev/null
+++ b/core/java/android/net/StringNetworkSpecifier.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.Objects;
+
+/** @hide */
+public final class StringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
+ /**
+ * Arbitrary string used to pass (additional) information to the network factory.
+ */
+ public final String specifier;
+
+ public StringNetworkSpecifier(String specifier) {
+ Preconditions.checkStringNotEmpty(specifier);
+ this.specifier = specifier;
+ }
+
+ @Override
+ public boolean satisfiedBy(NetworkSpecifier other) {
+ return equals(other);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof StringNetworkSpecifier)) return false;
+ return TextUtils.equals(specifier, ((StringNetworkSpecifier) o).specifier);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(specifier);
+ }
+
+ @Override
+ public String toString() {
+ return specifier;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(specifier);
+ }
+
+ public static final Parcelable.Creator<StringNetworkSpecifier> CREATOR =
+ new Parcelable.Creator<StringNetworkSpecifier>() {
+ public StringNetworkSpecifier createFromParcel(Parcel in) {
+ return new StringNetworkSpecifier(in.readString());
+ }
+ public StringNetworkSpecifier[] newArray(int size) {
+ return new StringNetworkSpecifier[size];
+ }
+ };
+}
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 15bd175..ff0bc69 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -16,9 +16,15 @@
package android.os;
+import android.util.ExceptionUtils;
import android.util.Log;
import android.util.Slog;
+
import com.android.internal.util.FastPrintWriter;
+import com.android.internal.util.FunctionalUtils;
+import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
+import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
+
import libcore.io.IoUtils;
import java.io.FileDescriptor;
@@ -26,7 +32,6 @@
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.lang.reflect.Modifier;
-import java.util.function.Supplier;
/**
* Base class for a remotable object, the core part of a lightweight
@@ -251,14 +256,23 @@
* Convenience method for running the provided action enclosed in
* {@link #clearCallingIdentity}/{@link #restoreCallingIdentity}
*
+ * Any exception thrown by the given action will be caught and rethrown after the call to
+ * {@link #restoreCallingIdentity}
+ *
* @hide
*/
- public static final void withCleanCallingIdentity(Runnable action) {
+ public static final void withCleanCallingIdentity(ThrowingRunnable action) {
long callingIdentity = clearCallingIdentity();
+ Throwable throwableToPropagate = null;
try {
action.run();
+ } catch (Throwable throwable) {
+ throwableToPropagate = throwable;
} finally {
restoreCallingIdentity(callingIdentity);
+ if (throwableToPropagate != null) {
+ throw ExceptionUtils.propagate(throwableToPropagate);
+ }
}
}
@@ -266,14 +280,24 @@
* Convenience method for running the provided action enclosed in
* {@link #clearCallingIdentity}/{@link #restoreCallingIdentity} returning the result
*
+ * Any exception thrown by the given action will be caught and rethrown after the call to
+ * {@link #restoreCallingIdentity}
+ *
* @hide
*/
- public static final <T> T withCleanCallingIdentity(Supplier<T> action) {
+ public static final <T> T withCleanCallingIdentity(ThrowingSupplier<T> action) {
long callingIdentity = clearCallingIdentity();
+ Throwable throwableToPropagate = null;
try {
return action.get();
+ } catch (Throwable throwable) {
+ throwableToPropagate = throwable;
+ return null; // overridden by throwing in finally block
} finally {
restoreCallingIdentity(callingIdentity);
+ if (throwableToPropagate != null) {
+ throw ExceptionUtils.propagate(throwableToPropagate);
+ }
}
}
diff --git a/core/java/android/provider/SettingsStringUtil.java b/core/java/android/provider/SettingsStringUtil.java
index 3dfedea..a3dc947 100644
--- a/core/java/android/provider/SettingsStringUtil.java
+++ b/core/java/android/provider/SettingsStringUtil.java
@@ -23,6 +23,7 @@
import com.android.internal.util.ArrayUtils;
+import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.function.Function;
@@ -80,6 +81,12 @@
return s;
}
+ public static String addAll(String delimitedElements, Collection<String> elements) {
+ final ColonDelimitedSet<String> set
+ = new ColonDelimitedSet.OfStrings(delimitedElements);
+ return set.addAll(elements) ? set.toString() : delimitedElements;
+ }
+
public static String add(String delimitedElements, String element) {
final ColonDelimitedSet<String> set
= new ColonDelimitedSet.OfStrings(delimitedElements);
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index a4d3fb2..5e49b8f 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -34,6 +34,8 @@
import com.android.internal.os.SomeArgs;
+import java.util.List;
+
//TODO(b/33197203): improve javadoc (of both class and methods); in particular, make sure the
//life-cycle (and how state could be maintained on server-side) is well documented.
@@ -103,24 +105,22 @@
}
@Override
- public void onFillRequest(AssistStructure structure, Bundle extras,
- IFillCallback callback, int flags) {
+ public void onFillRequest(FillRequest request, IFillCallback callback) {
ICancellationSignal transport = CancellationSignal.createTransport();
try {
callback.onCancellable(transport);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
- mHandlerCaller.obtainMessageIIOOOO(MSG_ON_FILL_REQUEST, flags, UNUSED_ARG, structure,
- CancellationSignal.fromTransport(transport), extras, callback)
+ mHandlerCaller.obtainMessageOOO(MSG_ON_FILL_REQUEST, request,
+ CancellationSignal.fromTransport(transport), callback)
.sendToTarget();
}
@Override
- public void onSaveRequest(AssistStructure structure, Bundle extras,
- ISaveCallback callback) {
- mHandlerCaller.obtainMessageOOO(MSG_ON_SAVE_REQUEST, structure,
- extras, callback).sendToTarget();
+ public void onSaveRequest(SaveRequest request, ISaveCallback callback) {
+ mHandlerCaller.obtainMessageOO(MSG_ON_SAVE_REQUEST, request,
+ callback).sendToTarget();
}
};
@@ -131,23 +131,20 @@
break;
} case MSG_ON_FILL_REQUEST: {
final SomeArgs args = (SomeArgs) msg.obj;
- final AssistStructure structure = (AssistStructure) args.arg1;
+ final FillRequest request = (FillRequest) args.arg1;
final CancellationSignal cancellation = (CancellationSignal) args.arg2;
- final Bundle extras = (Bundle) args.arg3;
- final IFillCallback callback = (IFillCallback) args.arg4;
- final FillCallback fillCallback = new FillCallback(callback);
- final int flags = msg.arg1;
+ final IFillCallback callback = (IFillCallback) args.arg3;
+ final FillCallback fillCallback = new FillCallback(callback, request.getId());
args.recycle();
- onFillRequest(structure, extras, flags, cancellation, fillCallback);
+ onFillRequest(request, cancellation, fillCallback);
break;
} case MSG_ON_SAVE_REQUEST: {
final SomeArgs args = (SomeArgs) msg.obj;
- final AssistStructure structure = (AssistStructure) args.arg1;
- final Bundle extras = (Bundle) args.arg2;
- final ISaveCallback callback = (ISaveCallback) args.arg3;
+ final SaveRequest request = (SaveRequest) args.arg1;
+ final ISaveCallback callback = (ISaveCallback) args.arg2;
final SaveCallback saveCallback = new SaveCallback(callback);
args.recycle();
- onSaveRequest(structure, extras, saveCallback);
+ onSaveRequest(request, saveCallback);
break;
} case MSG_DISCONNECT: {
onDisconnected();
@@ -198,6 +195,28 @@
* or {@link FillCallback#onFailure(CharSequence)})
* to notify the result of the request.
*
+ * @param request the {@link FillRequest request} to handle.
+ * See {@link FillResponse} for examples of multiple-sections requests.
+ * @param cancellationSignal signal for observing cancellation requests. The system will use
+ * this to notify you that the fill result is no longer needed and you should stop
+ * handling this fill request in order to save resources.
+ * @param callback object used to notify the result of the request.
+ */
+ public void onFillRequest(@NonNull FillRequest request,
+ @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback) {
+ onFillRequest(request.getStructure(), request.getClientState(), request.getFlags(),
+ cancellationSignal, callback);
+ }
+
+ /**
+ * Called by the Android system do decide if an {@link Activity} can be autofilled by the
+ * service.
+ *
+ * <p>Service must call one of the {@link FillCallback} methods (like
+ * {@link FillCallback#onSuccess(FillResponse)}
+ * or {@link FillCallback#onFailure(CharSequence)})
+ * to notify the result of the request.
+ *
* @param structure {@link Activity}'s view structure.
* @param data bundle containing data passed by the service in a last call to
* {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your
@@ -211,6 +230,7 @@
* handling this fill request in order to save resources.
* @param callback object used to notify the result of the request.
*/
+ @Deprecated
public abstract void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
int flags, @NonNull CancellationSignal cancellationSignal,
@NonNull FillCallback callback);
@@ -222,6 +242,23 @@
* {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
* to notify the result of the request.
*
+ * @param request the {@link SaveRequest request} to handle.
+ * See {@link FillResponse} for examples of multiple-sections requests.
+ * @param callback object used to notify the result of the request.
+ */
+ public void onSaveRequest(@NonNull SaveRequest request, @NonNull SaveCallback callback) {
+ List<FillContext> contexts = request.getFillContexts();
+ onSaveRequest(contexts.get(contexts.size() - 1).getStructure(),
+ request.getClientState(), callback);
+ }
+
+ /**
+ * Called when user requests service to save the fields of an {@link Activity}.
+ *
+ * <p>Service must call one of the {@link SaveCallback} methods (like
+ * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
+ * to notify the result of the request.
+ *
* @param structure {@link Activity}'s view structure.
* @param data bundle containing data passed by the service in a last call to
* {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your
@@ -231,6 +268,7 @@
* See {@link FillResponse} for examples of multiple-sections requests.
* @param callback object used to notify the result of the request.
*/
+ @Deprecated
public abstract void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
@NonNull SaveCallback callback);
diff --git a/core/java/android/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java
index e8ad14f..a009be8 100644
--- a/core/java/android/service/autofill/FillCallback.java
+++ b/core/java/android/service/autofill/FillCallback.java
@@ -27,11 +27,13 @@
*/
public final class FillCallback {
private final IFillCallback mCallback;
+ private final int mRequestId;
private boolean mCalled;
/** @hide */
- public FillCallback(IFillCallback callback) {
+ public FillCallback(IFillCallback callback, int requestId) {
mCallback = callback;
+ mRequestId = requestId;
}
/**
@@ -47,7 +49,7 @@
assertNotCalled();
mCalled = true;
try {
- mCallback.onSuccess(response);
+ mCallback.onSuccess(response, mRequestId);
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
}
diff --git a/core/java/android/service/autofill/FillContext.java b/core/java/android/service/autofill/FillContext.java
new file mode 100644
index 0000000..2efa08c
--- /dev/null
+++ b/core/java/android/service/autofill/FillContext.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill;
+
+import android.annotation.NonNull;
+import android.app.assist.AssistStructure;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class represents a context for each fill request made via {@link
+ * AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)}.
+ * It contains a snapshot of the UI state, the view ids that were returned by
+ * the {@link AutofillService autofill service} as both required to trigger a save
+ * and optional that can be saved, and the id of the corresponding {@link
+ * FillRequest}.
+ * <p>
+ * This context allows you to inspect the values for the interesting views
+ * in the context they appeared. Also a reference to the corresponding fill
+ * request is useful to store meta-data in the client state bundle passed
+ * to {@link FillResponse.Builder#setClientState(Bundle)} to avoid interpreting
+ * the UI state again while saving.
+ */
+public final class FillContext implements Parcelable {
+ private final int mRequestId;
+ private final @NonNull AssistStructure mStructure;
+
+ /** @hide */
+ public FillContext(int requestId, @NonNull AssistStructure structure) {
+ mRequestId = requestId;
+ mStructure = structure;
+ }
+
+ private FillContext(Parcel parcel) {
+ this(parcel.readInt(), parcel.readParcelable(null));
+ }
+
+ /**
+ * Gets the id of the {@link FillRequest fill request} this context
+ * corresponds to. This is useful to associate your custom client
+ * state with every request to avoid reinterpreting the UI when saving
+ * user data.
+ *
+ * @return The request id.
+ */
+ public int getRequestId() {
+ return mRequestId;
+ }
+
+ /**
+ * @return The screen content.
+ */
+ public AssistStructure getStructure() {
+ return mStructure;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeInt(mRequestId);
+ parcel.writeParcelable(mStructure, flags);
+ }
+
+ public static final Parcelable.Creator<FillContext> CREATOR =
+ new Parcelable.Creator<FillContext>() {
+ @Override
+ public FillContext createFromParcel(Parcel parcel) {
+ return new FillContext(parcel);
+ }
+
+ @Override
+ public FillContext[] newArray(int size) {
+ return new FillContext[size];
+ }
+ };
+}
diff --git a/core/java/android/service/autofill/FillRequest.aidl b/core/java/android/service/autofill/FillRequest.aidl
new file mode 100644
index 0000000..2b1a8fe
--- /dev/null
+++ b/core/java/android/service/autofill/FillRequest.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill;
+
+parcelable FillRequest;
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
new file mode 100644
index 0000000..aa6db4d
--- /dev/null
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.assist.AssistStructure;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.Parcel;
+import android.os.Parcelable;
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * This class represents a request to an {@link AutofillService autofill provider}
+ * to interpret the screen and provide information to the system which views are
+ * interesting for saving and what are the possible ways to fill the inputs on
+ * the screen if applicable.
+ *
+ * @see AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)
+ */
+public final class FillRequest implements Parcelable {
+ private static AtomicInteger sIdCounter = new AtomicInteger();
+
+ /**
+ * Indicates autofill was explicitly requested by the user.
+ */
+ public static final int FLAG_MANUAL_REQUEST = 0x1;
+
+ /** @hide */
+ @IntDef(
+ flag = true,
+ value = {FLAG_MANUAL_REQUEST})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface RequestFlags{}
+
+ private final int mId;
+ private final @RequestFlags int mFlags;
+ private final @NonNull AssistStructure mStructure;
+ private final @Nullable Bundle mClientState;
+
+ /** @hide */
+ public FillRequest(@NonNull AssistStructure structure,
+ @Nullable Bundle clientState, @RequestFlags int flags) {
+ this(sIdCounter.incrementAndGet(), structure, clientState, flags);
+ }
+
+ private FillRequest(@NonNull Parcel parcel) {
+ mId = parcel.readInt();
+ mStructure = parcel.readParcelable(null);
+ mClientState = parcel.readBundle();
+ mFlags = parcel.readInt();
+ }
+
+ private FillRequest(int id, @NonNull AssistStructure structure,
+ @Nullable Bundle clientState, @RequestFlags int flags) {
+ mId = id;
+ mFlags = Preconditions.checkFlagsArgument(flags, FLAG_MANUAL_REQUEST);
+ mStructure = Preconditions.checkNotNull(structure, "structure");
+ mClientState = clientState;
+ }
+
+ /**
+ * @return The unique id of this request.
+ */
+ public int getId() {
+ return mId;
+ }
+
+ /**
+ * @return The flags associated with this request.
+ *
+ * @see #FLAG_MANUAL_REQUEST
+ */
+ public @RequestFlags int getFlags() {
+ return mFlags;
+ }
+
+ /**
+ * @return The structure capturing the UI state.
+ */
+ public @NonNull AssistStructure getStructure() {
+ return mStructure;
+ }
+
+ /**
+ * Gets the extra client state returned from the last {@link
+ * AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)
+ * fill request}.
+ * <p>
+ * Once a {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)
+ * save request} is made the client state is cleared.
+ *
+ * @return The client state.
+ */
+ public @Nullable Bundle getClientState() {
+ return mClientState;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeInt(mId);
+ parcel.writeParcelable(mStructure, flags);
+ parcel.writeBundle(mClientState);
+ parcel.writeInt(mFlags);
+ }
+
+ public static final Parcelable.Creator<FillRequest> CREATOR =
+ new Parcelable.Creator<FillRequest>() {
+ @Override
+ public FillRequest createFromParcel(Parcel parcel) {
+ return new FillRequest(parcel);
+ }
+
+ @Override
+ public FillRequest[] newArray(int size) {
+ return new FillRequest[size];
+ }
+ };
+}
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index eab0d4c..8c8060a 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -132,25 +132,25 @@
*/
public final class FillResponse implements Parcelable {
- private final ArrayList<Dataset> mDatasets;
- private final SaveInfo mSaveInfo;
- private final Bundle mExtras;
- private final RemoteViews mPresentation;
- private final IntentSender mAuthentication;
- private AutofillId[] mAuthenticationIds;
+ private final @Nullable ArrayList<Dataset> mDatasets;
+ private final @Nullable SaveInfo mSaveInfo;
+ private final @Nullable Bundle mClientState;
+ private final @Nullable RemoteViews mPresentation;
+ private final @Nullable IntentSender mAuthentication;
+ private final @Nullable AutofillId[] mAuthenticationIds;
private FillResponse(@NonNull Builder builder) {
mDatasets = builder.mDatasets;
mSaveInfo = builder.mSaveInfo;
- mExtras = builder.mExtras;
+ mClientState = builder.mCLientState;
mPresentation = builder.mPresentation;
mAuthentication = builder.mAuthentication;
mAuthenticationIds = builder.mAuthenticationIds;
}
/** @hide */
- public @Nullable Bundle getExtras() {
- return mExtras;
+ public @Nullable Bundle getClientState() {
+ return mClientState;
}
/** @hide */
@@ -185,7 +185,7 @@
public static final class Builder {
private ArrayList<Dataset> mDatasets;
private SaveInfo mSaveInfo;
- private Bundle mExtras;
+ private Bundle mCLientState;
private RemoteViews mPresentation;
private IntentSender mAuthentication;
private AutofillId[] mAuthenticationIds;
@@ -289,23 +289,35 @@
return this;
}
+ @Deprecated
+ public Builder setExtras(@Nullable Bundle extras) {
+ throwIfDestroyed();
+ mCLientState = extras;
+ return this;
+ }
+
/**
- * Sets a {@link Bundle} that will be passed to subsequent APIs that
+ * Sets a {@link Bundle state} that will be passed to subsequent APIs that
* manipulate this response. For example, they are passed to subsequent
* calls to {@link AutofillService#onFillRequest(
* android.app.assist.AssistStructure, Bundle, int,
* android.os.CancellationSignal, FillCallback)} and {@link AutofillService#onSaveRequest(
- * android.app.assist.AssistStructure, Bundle, SaveCallback)}.
+ * android.app.assist.AssistStructure, Bundle, SaveCallback)}. You can use
+ * this to store intermediate state that is persistent across multiple
+ * fill requests and the subsequent save request.
*
* <p>If this method is called on multiple {@link FillResponse} objects for the same
* activity, just the latest bundle is passed back to the service.
*
- * @param extras The response extras.
+ * <p>Once a {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)
+ * save request} is made the client state is cleared.
+ *
+ * @param clientState The custom client state.
* @return This builder.
*/
- public Builder setExtras(Bundle extras) {
+ public Builder setClientState(@Nullable Bundle clientState) {
throwIfDestroyed();
- mExtras = extras;
+ mCLientState = clientState;
return this;
}
@@ -344,7 +356,7 @@
return new StringBuilder(
"FillResponse: [datasets=").append(mDatasets)
.append(", saveInfo=").append(mSaveInfo)
- .append(", hasExtras=").append(mExtras != null)
+ .append(", clientState=").append(mClientState != null)
.append(", hasPresentation=").append(mPresentation != null)
.append(", hasAuthentication=").append(mAuthentication != null)
.append(", authenticationSize=").append(mAuthenticationIds != null
@@ -365,7 +377,7 @@
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeTypedArrayList(mDatasets, flags);
parcel.writeParcelable(mSaveInfo, flags);
- parcel.writeParcelable(mExtras, flags);
+ parcel.writeParcelable(mClientState, flags);
parcel.writeParcelableArray(mAuthenticationIds, flags);
parcel.writeParcelable(mAuthentication, flags);
parcel.writeParcelable(mPresentation, flags);
diff --git a/core/java/android/service/autofill/IAutoFillService.aidl b/core/java/android/service/autofill/IAutoFillService.aidl
index a8d86ca..23a1a3f 100644
--- a/core/java/android/service/autofill/IAutoFillService.aidl
+++ b/core/java/android/service/autofill/IAutoFillService.aidl
@@ -16,10 +16,10 @@
package android.service.autofill;
-import android.app.assist.AssistStructure;
-import android.os.Bundle;
+import android.service.autofill.FillRequest;
import android.service.autofill.IFillCallback;
import android.service.autofill.ISaveCallback;
+import android.service.autofill.SaveRequest;
import com.android.internal.os.IResultReceiver;
/**
@@ -29,8 +29,6 @@
*/
oneway interface IAutoFillService {
void onConnectedStateChanged(boolean connected);
- void onFillRequest(in AssistStructure structure, in Bundle extras,
- in IFillCallback callback, int flags);
- void onSaveRequest(in AssistStructure structure, in Bundle extras,
- in ISaveCallback callback);
+ void onFillRequest(in FillRequest request, in IFillCallback callback);
+ void onSaveRequest(in SaveRequest request, in ISaveCallback callback);
}
diff --git a/core/java/android/service/autofill/IFillCallback.aidl b/core/java/android/service/autofill/IFillCallback.aidl
index 2bb3e9a..688ac84 100644
--- a/core/java/android/service/autofill/IFillCallback.aidl
+++ b/core/java/android/service/autofill/IFillCallback.aidl
@@ -27,6 +27,6 @@
*/
interface IFillCallback {
void onCancellable(in ICancellationSignal cancellation);
- void onSuccess(in FillResponse response);
+ void onSuccess(in FillResponse response, int requestId);
void onFailure(CharSequence message);
}
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 4ad0f08..258d257 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -140,7 +140,19 @@
*/
public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 0x10;
- private final int mType;
+ /** @hide */
+ @IntDef(
+ flag = true,
+ value = {
+ SAVE_DATA_TYPE_GENERIC,
+ SAVE_DATA_TYPE_PASSWORD,
+ SAVE_DATA_TYPE_ADDRESS,
+ SAVE_DATA_TYPE_CREDIT_CARD,
+ SAVE_DATA_TYPE_EMAIL_ADDRESS})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface SaveDataType{}
+
+ private final @SaveDataType int mType;
private final CharSequence mNegativeActionTitle;
private final IntentSender mNegativeActionListener;
private final AutofillId[] mRequiredIds;
@@ -177,7 +189,7 @@
}
/** @hide */
- public int getType() {
+ public @SaveDataType int getType() {
return mType;
}
@@ -191,7 +203,7 @@
*/
public static final class Builder {
- private final int mType;
+ private final @SaveDataType int mType;
private CharSequence mNegativeActionTitle;
private IntentSender mNegativeActionListener;
// TODO(b/33197203): make mRequiredIds final once addSavableIds() is gone
@@ -215,7 +227,7 @@
*
* @throws IllegalArgumentException if {@code requiredIds} is {@code null} or empty.
*/
- public Builder(int type, @NonNull AutofillId[] requiredIds) {
+ public Builder(@SaveDataType int type, @NonNull AutofillId[] requiredIds) {
if (false) {// TODO(b/33197203): re-move when clients use it
Preconditions.checkArgument(requiredIds != null && requiredIds.length > 0,
"must have at least one required id: " + Arrays.toString(requiredIds));
@@ -230,7 +242,7 @@
* // TODO(b/33197203): make sure is removed when clients migrated
*/
@Deprecated
- public Builder(int type) {
+ public Builder(@SaveDataType int type) {
this(type, null);
}
diff --git a/core/java/android/service/autofill/SaveRequest.aidl b/core/java/android/service/autofill/SaveRequest.aidl
new file mode 100644
index 0000000..7789b577
--- /dev/null
+++ b/core/java/android/service/autofill/SaveRequest.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill;
+
+parcelable SaveRequest;
diff --git a/core/java/android/service/autofill/SaveRequest.java b/core/java/android/service/autofill/SaveRequest.java
new file mode 100644
index 0000000..9de9315
--- /dev/null
+++ b/core/java/android/service/autofill/SaveRequest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.Parcel;
+import android.os.Parcelable;
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class represents a request to an {@link AutofillService
+ * autofill provider} to save applicable data entered by the user.
+ *
+ * @see AutofillService#onSaveRequest(SaveRequest, SaveCallback)
+ */
+public final class SaveRequest implements Parcelable {
+ private final @NonNull ArrayList<FillContext> mFillContexts;
+ private final @Nullable Bundle mClientState;
+
+ /** @hide */
+ public SaveRequest(@NonNull ArrayList<FillContext> fillContexts,
+ @Nullable Bundle clientState) {
+ mFillContexts = Preconditions.checkNotNull(fillContexts, "fillContexts");
+ mClientState = clientState;
+ }
+
+ private SaveRequest(@NonNull Parcel parcel) {
+ this(parcel.readTypedArrayList(null), parcel.readBundle());
+ }
+
+ /**
+ * @return The contexts associated with each previous fill request.
+ */
+ public @NonNull List<FillContext> getFillContexts() {
+ return mFillContexts;
+ }
+
+ /**
+ * Gets the extra client state returned from the last {@link
+ * AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)}
+ * fill request}.
+ *
+ * @return The client state.
+ */
+ public @Nullable Bundle getClientState() {
+ return mClientState;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeTypedArrayList(mFillContexts, flags);
+ parcel.writeBundle(mClientState);
+ }
+
+ public static final Creator<SaveRequest> CREATOR =
+ new Creator<SaveRequest>() {
+ @Override
+ public SaveRequest createFromParcel(Parcel parcel) {
+ return new SaveRequest(parcel);
+ }
+
+ @Override
+ public SaveRequest[] newArray(int size) {
+ return new SaveRequest[size];
+ }
+ };
+}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 6bbb0ff..98780a7 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -16,6 +16,8 @@
package android.service.wallpaper;
+import android.annotation.Nullable;
+import android.app.WallpaperColors;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.util.MergedConfiguration;
@@ -542,6 +544,24 @@
*/
public void onSurfaceDestroyed(SurfaceHolder holder) {
}
+
+ /**
+ * Notifies the engine that wallpaper colors changed significantly.
+ * This will trigger a {@link #onComputeWallpaperColors()} call.
+ */
+ public void invalidateColors() {
+ }
+
+ /**
+ * Notifies the system about what colors the wallpaper is using.
+ * You might return null if no color information is available at the moment. In that case
+ * you might want to call {@link #invalidateColors()} in a near future.
+ *
+ * @return List of wallpaper colors and their weights.
+ */
+ public @Nullable WallpaperColors onComputeWallpaperColors() {
+ return null;
+ }
protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
out.print(prefix); out.print("mInitializing="); out.print(mInitializing);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a522652..172ad8d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -109,7 +109,6 @@
import android.widget.ScrollBarDrawable;
import com.android.internal.R;
-import com.android.internal.util.Preconditions;
import com.android.internal.view.TooltipPopup;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.widget.ScrollBarUtils;
@@ -954,41 +953,6 @@
private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
- /** @hide */
- @IntDef({
- AUTOFILL_MODE_INHERIT,
- AUTOFILL_MODE_AUTO,
- AUTOFILL_MODE_MANUAL
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface AutofillMode {}
-
- /**
- * This view inherits the autofill state from it's parent. If there is no parent it is
- * {@link #AUTOFILL_MODE_AUTO}.
- * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode">
- * {@code android:autofillMode}.
- */
- public static final int AUTOFILL_MODE_INHERIT = 0;
-
- /**
- * Allows this view to automatically trigger an autofill request when it get focus.
- * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode">
- * {@code android:autofillMode}.
- */
- public static final int AUTOFILL_MODE_AUTO = 1;
-
- /**
- * Do not trigger an autofill request if this view is focused. The user can still force
- * an autofill request.
- * <p>This does not prevent this field from being autofilled if an autofill operation is
- * triggered from a different view.</p>
- *
- * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode">{@code
- * android:autofillMode}.
- */
- public static final int AUTOFILL_MODE_MANUAL = 2;
-
/**
* This view contains an email address.
*
@@ -2762,7 +2726,7 @@
* 1 PFLAG3_IS_AUTOFILLED
* 1 PFLAG3_FINGER_DOWN
* 1 PFLAG3_FOCUSED_BY_DEFAULT
- * 11 PFLAG3_AUTO_FILL_MODE_MASK
+ * __ unused
* 11 PFLAG3_IMPORTANT_FOR_AUTOFILL
* 1 PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
* 1 PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
@@ -2992,23 +2956,6 @@
private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
/**
- * Shift for the place where the autofill mode is stored in the pflags
- *
- * @see #getAutofillMode()
- * @see #setAutofillMode(int)
- */
- private static final int PFLAG3_AUTOFILL_MODE_SHIFT = 19;
-
- /**
- * Mask for autofill modes
- *
- * @see #getAutofillMode()
- * @see #setAutofillMode(int)
- */
- private static final int PFLAG3_AUTOFILL_MODE_MASK = (AUTOFILL_MODE_INHERIT
- | AUTOFILL_MODE_AUTO | AUTOFILL_MODE_MANUAL) << PFLAG3_AUTOFILL_MODE_SHIFT;
-
- /**
* Shift for the bits in {@link #mPrivateFlags3} related to the
* "importantForAutofill" attribute.
*/
@@ -5055,11 +5002,6 @@
setFocusedByDefault(a.getBoolean(attr, true));
}
break;
- case R.styleable.View_autofillMode:
- if (a.peekValue(attr) != null) {
- setAutofillMode(a.getInt(attr, AUTOFILL_MODE_INHERIT));
- }
- break;
case R.styleable.View_autofillHints:
if (a.peekValue(attr) != null) {
CharSequence[] rawHints = null;
@@ -6849,8 +6791,7 @@
}
private void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
- if (isAutofillable() && isAttachedToWindow()
- && getResolvedAutofillMode() == AUTOFILL_MODE_AUTO) {
+ if (isAutofillable() && isAttachedToWindow()) {
AutofillManager afm = getAutofillManager();
if (afm != null) {
if (enter && hasWindowFocus() && isFocused()) {
@@ -9159,21 +9100,6 @@
}
/**
- * Set autofill mode for the view.
- *
- * @param autofillMode One of {@link #AUTOFILL_MODE_INHERIT}, {@link #AUTOFILL_MODE_AUTO},
- * or {@link #AUTOFILL_MODE_MANUAL}.
- * @attr ref android.R.styleable#View_autofillMode
- */
- public void setAutofillMode(@AutofillMode int autofillMode) {
- Preconditions.checkArgumentInRange(autofillMode, AUTOFILL_MODE_INHERIT,
- AUTOFILL_MODE_MANUAL, "autofillMode");
-
- mPrivateFlags3 &= ~PFLAG3_AUTOFILL_MODE_MASK;
- mPrivateFlags3 |= autofillMode << PFLAG3_AUTOFILL_MODE_SHIFT;
- }
-
- /**
* Sets the hints that helps the autofill service to select the appropriate data to fill the
* view.
*
@@ -9810,48 +9736,6 @@
}
/**
- * Returns the autofill mode for this view.
- *
- * @return One of {@link #AUTOFILL_MODE_INHERIT}, {@link #AUTOFILL_MODE_AUTO}, or
- * {@link #AUTOFILL_MODE_MANUAL}.
- * @attr ref android.R.styleable#View_autofillMode
- */
- @ViewDebug.ExportedProperty(mapping = {
- @ViewDebug.IntToString(from = AUTOFILL_MODE_INHERIT, to = "AUTOFILL_MODE_INHERIT"),
- @ViewDebug.IntToString(from = AUTOFILL_MODE_AUTO, to = "AUTOFILL_MODE_AUTO"),
- @ViewDebug.IntToString(from = AUTOFILL_MODE_MANUAL, to = "AUTOFILL_MODE_MANUAL")
- })
- @AutofillMode
- public int getAutofillMode() {
- return (mPrivateFlags3 & PFLAG3_AUTOFILL_MODE_MASK) >> PFLAG3_AUTOFILL_MODE_SHIFT;
- }
-
- /**
- * Returns the resolved autofill mode for this view.
- *
- * This is the same as {@link #getAutofillMode()} but if the mode is
- * {@link #AUTOFILL_MODE_INHERIT} the parents autofill mode will be returned.
- *
- * @return One of {@link #AUTOFILL_MODE_AUTO}, or {@link #AUTOFILL_MODE_MANUAL}. If the auto-
- * fill mode can not be resolved e.g. {@link #getAutofillMode()} is
- * {@link #AUTOFILL_MODE_INHERIT} and the {@link View} is detached
- * {@link #AUTOFILL_MODE_AUTO} is returned.
- */
- public @AutofillMode int getResolvedAutofillMode() {
- @AutofillMode int autofillMode = getAutofillMode();
-
- if (autofillMode == AUTOFILL_MODE_INHERIT) {
- if (mParent == null) {
- return AUTOFILL_MODE_AUTO;
- } else {
- return mParent.getResolvedAutofillMode();
- }
- } else {
- return autofillMode;
- }
- }
-
- /**
* Find the nearest view in the specified direction that can take focus.
* This does not actually give focus to that view.
*
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index d5aab48..cc11cb8 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -659,17 +659,4 @@
* @return true if the action was consumed by this ViewParent
*/
public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle arguments);
-
- /**
- * Return the resolved autofill mode.
- *
- * @return One of {@link View#AUTOFILL_MODE_AUTO}, {@link View#AUTOFILL_MODE_MANUAL} if the
- * autofill mode can be resolved. If the autofill mode cannot be resolved
- * {@link View#AUTOFILL_MODE_AUTO}.
- *
- * @see View#getResolvedAutofillMode()
- */
- default @View.AutofillMode int getResolvedAutofillMode() {
- return View.AUTOFILL_MODE_AUTO;
- }
}
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 570f968..ec6559c 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -101,7 +101,10 @@
// Public flags start from the lowest bit
/**
* Indicates autofill was explicitly requested by the user.
+ *
+ * @deprecated Use {@link android.service.autofill.FillRequest#FLAG_MANUAL_REQUEST}
*/
+ @Deprecated
public static final int FLAG_MANUAL_REQUEST = 0x1;
// Private flags start from the highest bit
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index 2f12e9b..28d9fcf 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -155,7 +155,7 @@
public static final int IME_ACTION_PREVIOUS = 0x00000007;
/**
- * Flag of {@link #imeOptions}: used to request that the IME does not update any personalized
+ * Flag of {@link #imeOptions}: used to request that the IME should not update any personalized
* data such as typing history and personalized language model based on what the user typed on
* this text editing object. Typical use cases are:
* <ul>
diff --git a/core/java/com/android/internal/app/AlertActivity.java b/core/java/com/android/internal/app/AlertActivity.java
index 35ffa71..999a908 100644
--- a/core/java/com/android/internal/app/AlertActivity.java
+++ b/core/java/com/android/internal/app/AlertActivity.java
@@ -67,10 +67,15 @@
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- event.setClassName(Dialog.class.getName());
- event.setPackageName(getPackageName());
+ return dispatchPopulateAccessibilityEvent(this, event);
+ }
- ViewGroup.LayoutParams params = getWindow().getAttributes();
+ public static boolean dispatchPopulateAccessibilityEvent(Activity act,
+ AccessibilityEvent event) {
+ event.setClassName(Dialog.class.getName());
+ event.setPackageName(act.getPackageName());
+
+ ViewGroup.LayoutParams params = act.getWindow().getAttributes();
boolean isFullScreen = (params.width == ViewGroup.LayoutParams.MATCH_PARENT) &&
(params.height == ViewGroup.LayoutParams.MATCH_PARENT);
event.setFullScreen(isFullScreen);
@@ -86,8 +91,7 @@
* @see #mAlertParams
*/
protected void setupAlert() {
- mAlertParams.apply(mAlert);
- mAlert.installContent();
+ mAlert.installContent(mAlertParams);
}
@Override
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 95c291a..46cb546 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -247,6 +247,11 @@
return false;
}
+ public void installContent(AlertParams params) {
+ params.apply(this);
+ installContent();
+ }
+
public void installContent() {
int contentView = selectContentView();
mWindow.setContentView(contentView);
diff --git a/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java b/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java
new file mode 100644
index 0000000..4ce6f60
--- /dev/null
+++ b/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.notification;
+
+import android.content.ComponentName;
+import android.content.Intent;
+
+public final class NotificationAccessConfirmationActivityContract {
+ private static final ComponentName COMPONENT_NAME = new ComponentName(
+ "com.android.settings",
+ "com.android.settings.notification.NotificationAccessConfirmationActivity");
+ public static final String EXTRA_USER_ID = "user_id";
+ public static final String EXTRA_COMPONENT_NAME = "component_name";
+ public static final String EXTRA_PACKAGE_TITLE = "package_title";
+
+ public static Intent launcherIntent(int userId, ComponentName component, String packageTitle) {
+ return new Intent()
+ .setComponent(COMPONENT_NAME)
+ .putExtra(EXTRA_USER_ID, userId)
+ .putExtra(EXTRA_COMPONENT_NAME, component)
+ .putExtra(EXTRA_PACKAGE_TITLE, packageTitle);
+ }
+}
diff --git a/core/java/com/android/internal/util/CollectionUtils.java b/core/java/com/android/internal/util/CollectionUtils.java
index 183945c..96b443d 100644
--- a/core/java/com/android/internal/util/CollectionUtils.java
+++ b/core/java/com/android/internal/util/CollectionUtils.java
@@ -16,6 +16,8 @@
package com.android.internal.util;
+import static com.android.internal.util.ArrayUtils.isEmpty;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -64,7 +66,7 @@
*/
public static @NonNull <I, O> List<O> map(@Nullable List<I> cur,
Function<? super I, ? extends O> f) {
- if (cur == null || cur.isEmpty()) return Collections.emptyList();
+ if (isEmpty(cur)) return Collections.emptyList();
final ArrayList<O> result = new ArrayList<>();
for (int i = 0; i < cur.size(); i++) {
result.add(f.apply(cur.get(i)));
@@ -73,6 +75,30 @@
}
/**
+ * {@link #map(List, Function)} + {@link #filter(List, java.util.function.Predicate)}
+ *
+ * Calling this is equivalent (but more memory efficient) to:
+ *
+ * {@code
+ * filter(
+ * map(cur, f),
+ * i -> { i != null })
+ * }
+ */
+ public static @NonNull <I, O> List<O> mapNotNull(@Nullable List<I> cur,
+ Function<? super I, ? extends O> f) {
+ if (isEmpty(cur)) return Collections.emptyList();
+ final ArrayList<O> result = new ArrayList<>();
+ for (int i = 0; i < cur.size(); i++) {
+ O transformed = f.apply(cur.get(i));
+ if (transformed != null) {
+ result.add(transformed);
+ }
+ }
+ return result;
+ }
+
+ /**
* Returns the given list, or an immutable empty list if the provided list is null
*
* This can be used to guaranty null-safety without paying the price of extra allocations
@@ -94,7 +120,7 @@
* Returns the elements of the given list that are of type {@code c}
*/
public static @NonNull <T> List<T> filter(@Nullable List<?> list, Class<T> c) {
- if (ArrayUtils.isEmpty(list)) return Collections.emptyList();
+ if (isEmpty(list)) return Collections.emptyList();
ArrayList<T> result = null;
for (int i = 0; i < list.size(); i++) {
final Object item = list.get(i);
@@ -120,7 +146,7 @@
*/
public static @Nullable <T> T find(@Nullable List<T> items,
java.util.function.Predicate<T> predicate) {
- if (ArrayUtils.isEmpty(items)) return null;
+ if (isEmpty(items)) return null;
for (int i = 0; i < items.size(); i++) {
final T item = items.get(i);
if (predicate.test(item)) return item;
@@ -145,11 +171,17 @@
* {@link Collections#emptyList}
*/
public static @NonNull <T> List<T> remove(@Nullable List<T> cur, T val) {
- if (cur == null || cur == Collections.emptyList()) {
- return Collections.emptyList();
+ if (isEmpty(cur)) {
+ return emptyIfNull(cur);
}
cur.remove(val);
return cur;
}
+ /**
+ * @return a list that will not be affected by mutations to the given original list.
+ */
+ public static @NonNull <T> List<T> copyOf(@Nullable List<T> cur) {
+ return isEmpty(cur) ? Collections.emptyList() : new ArrayList<>(cur);
+ }
}
diff --git a/core/java/com/android/internal/util/FunctionalUtils.java b/core/java/com/android/internal/util/FunctionalUtils.java
new file mode 100644
index 0000000..9aeb041
--- /dev/null
+++ b/core/java/com/android/internal/util/FunctionalUtils.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import java.util.function.Supplier;
+
+/**
+ * Utilities specific to functional programming
+ */
+public class FunctionalUtils {
+ private FunctionalUtils() {}
+
+ /**
+ * An equivalent of {@link Runnable} that allows throwing checked exceptions
+ *
+ * This can be used to specify a lambda argument without forcing all the checked exceptions
+ * to be handled within it
+ */
+ @FunctionalInterface
+ public interface ThrowingRunnable {
+ void run() throws Exception;
+ }
+
+ /**
+ * An equivalent of {@link Supplier} that allows throwing checked exceptions
+ *
+ * This can be used to specify a lambda argument without forcing all the checked exceptions
+ * to be handled within it
+ */
+ @FunctionalInterface
+ public interface ThrowingSupplier<T> {
+ T get() throws Exception;
+ }
+}
diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java
index 4e6857a..e5d5716 100644
--- a/core/java/com/android/internal/util/Preconditions.java
+++ b/core/java/com/android/internal/util/Preconditions.java
@@ -49,6 +49,23 @@
}
/**
+ * Ensures that an expression checking an argument is true.
+ *
+ * @param expression the expression to check
+ * @param messageTemplate a printf-style message template to use if the check fails; will
+ * be converted to a string using {@link String#format(String, Object...)}
+ * @param messageArgs arguments for {@code messageTemplate}
+ * @throws IllegalArgumentException if {@code expression} is false
+ */
+ public static void checkArgument(boolean expression,
+ final String messageTemplate,
+ final Object... messageArgs) {
+ if (!expression) {
+ throw new IllegalArgumentException(String.format(messageTemplate, messageArgs));
+ }
+ }
+
+ /**
* Ensures that an string reference passed as a parameter to the calling
* method is not empty.
*
diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp
index 1883ecb..9491a1e 100644
--- a/core/jni/android_os_VintfObject.cpp
+++ b/core/jni/android_os_VintfObject.cpp
@@ -59,7 +59,7 @@
cPackageInfo[i] = cString;
env->ReleaseStringUTFChars(element, cString);
}
- int32_t status = VintfObject::CheckCompatibility(cPackageInfo, false /* mount */);
+ int32_t status = VintfObject::CheckCompatibility(cPackageInfo);
return status;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 000c8c4..8869593 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3556,6 +3556,11 @@
android:process=":ui">
</activity>
+ <activity android:name="com.android.settings.notification.NotificationAccessConfirmationActivity"
+ android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert"
+ android:excludeFromRecents="true">
+ </activity>
+
<receiver android:name="com.android.server.BootReceiver"
android:systemUserOnly="true">
<intent-filter android:priority="1000">
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 67f6d19..4fb21fa 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1371,6 +1371,22 @@
Corresponds to
{@link android.view.inputmethod.EditorInfo#IME_ACTION_PREVIOUS}. -->
<flag name="actionPrevious" value="0x00000007" />
+ <!-- Used to request that the IME should not update any personalized data such as typing
+ history and personalized language model based on what the user typed on this text
+ editing object. Typical use cases are:
+ <ul>
+ <li>When the application is in a special mode, where user's activities are expected
+ to be not recorded in the application's history. Some web browsers and chat
+ applications may have this kind of modes.</li>
+ <li>When storing typing history does not make much sense. Specifying this flag in
+ typing games may help to avoid typing history from being filled up with words that
+ the user is less likely to type in their daily life. Another example is that when
+ the application already knows that the expected input is not a valid word (e.g. a
+ promotion code that is not a valid word in any natural language).</li>
+ </ul>
+ <p>Applications need to be aware that the flag is not a guarantee, and some IMEs may
+ not respect it.</p> -->
+ <flag name="flagNoPersonalizedLearning" value="0x1000000" />
<!-- Used to request that the IME never go
into fullscreen mode. Applications need to be aware that the flag is not
a guarantee, and not all IMEs will respect it.
@@ -2304,18 +2320,7 @@
<enum name="auto" value="0x00000010" />
</attr>
- <!-- Controls the autofill behavior for this view. -->
- <attr name="autofillMode">
- <!-- Inherit the behavior from the parent. If there is no parent it is auto. This is the
- default value for this attribute.-->
- <enum name="inherit" value="0" />
- <!-- Allows this view to automatically trigger an autofill request when it get focus.
- -->
- <enum name="auto" value="1" />
- <!-- Do not trigger an autofill request when this view is focused. The user can still
- manually force an autofill request for this view. -->
- <enum name="manual" value="2" />
- </attr>
+ <attr name="__removed3" />
<!-- Describes the content of a view so that a autofill service can fill in the appropriate
data. Multiple hints can be combined in a comma separated list or an array of strings
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index d6ed178..213d6ca 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2797,7 +2797,7 @@
<public name="numericModifiers" />
<public name="fontProviderAuthority" />
<public name="fontProviderQuery" />
- <public name="autofillMode" />
+ <public name="__removed3" />
<public name="primaryContentAlpha" />
<public name="secondaryContentAlpha" />
<public name="requiredFeature" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0821674..bd35073 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3000,6 +3000,8 @@
<!-- Do not translate. Default access point SSID used for tethering -->
<string name="wifi_tether_configure_ssid_default" translatable="false">AndroidAP</string>
+ <!-- Do not translate. Default access point SSID used for local only hotspot -->
+ <string name="wifi_localhotspot_configure_ssid_default" translatable="false">AndroidShare</string>
<!-- A notification is shown the first time a connection is attempted on an app owned AP -->
<!-- title for this message -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 603e376..f2da845 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -19,6 +19,9 @@
<!-- Private symbols that we need to reference from framework code. See
frameworks/base/core/res/MakeJavaSymbols.sed for how to easily generate
this.
+
+ Can be referenced in java code as: com.android.internal.R.<type>.<name>
+ and in layout xml as: "@*android:<type>/<name>"
-->
<java-symbol type="id" name="account_name" />
<java-symbol type="id" name="account_row_icon" />
@@ -1003,6 +1006,7 @@
<java-symbol type="string" name="wifi_p2p_turnon_message" />
<java-symbol type="string" name="wifi_p2p_frequency_conflict_message" />
<java-symbol type="string" name="wifi_tether_configure_ssid_default" />
+ <java-symbol type="string" name="wifi_localhotspot_configure_ssid_default" />
<java-symbol type="string" name="wifi_watchdog_network_disabled" />
<java-symbol type="string" name="wifi_watchdog_network_disabled_detailed" />
<java-symbol type="string" name="imei" />
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index ec653d0..7f07f03 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -40,6 +40,7 @@
<privapp-permissions package="com.android.defcontainer">
<permission name="android.permission.ACCESS_CACHE_FILESYSTEM"/>
+ <permission name="android.permission.ALLOCATE_AGGRESSIVE"/>
<permission name="android.permission.INTERACT_ACROSS_USERS"/>
<permission name="android.permission.WRITE_MEDIA_STORAGE"/>
</privapp-permissions>
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index e628d18..6cab56c 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -23,12 +23,12 @@
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.media.MediaCodecInfo.CodecCapabilities;
-import android.media.MediaMetricsSet;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.PersistableBundle;
import android.view.Surface;
import java.io.IOException;
@@ -3188,20 +3188,19 @@
/**
* Return Metrics data about the current codec instance.
*
- * @return a MediaMetricsSet containing the set of attributes and values
+ * @return a {@link PersistableBundle} containing the set of attributes and values
* available for the media being handled by this instance of MediaCodec
- * The attributes are descibed in {@link MediaMetricsSet.MediaCodec}.
+ * The attributes are descibed in {@link MetricsConstants}.
*
- * Additional vendor-specific fields may also be present in
- * the return value.
+ * Additional vendor-specific fields may also be present in
+ * the return value.
*/
- public MediaMetricsSet getMetrics() {
- Bundle bundle = native_getMetrics();
- MediaMetricsSet mSet = new MediaMetricsSet(bundle);
- return mSet;
+ public PersistableBundle getMetrics() {
+ PersistableBundle bundle = native_getMetrics();
+ return bundle;
}
- private native Bundle native_getMetrics();
+ private native PersistableBundle native_getMetrics();
/**
* Change a video encoder's target bitrate on the fly. The value is an
@@ -3660,4 +3659,80 @@
private final ByteBuffer mData;
}
}
+
+ public final static class MetricsConstants
+ {
+ private MetricsConstants() {}
+
+ /**
+ * Key to extract the codec being used
+ * from the {@link MediaCodec#getMetrics} return value.
+ * The value is a String.
+ */
+ public static final String CODEC = "android.media.mediacodec.codec";
+
+ /**
+ * Key to extract the MIME type
+ * from the {@link MediaCodec#getMetrics} return value.
+ * The value is a String.
+ */
+ public static final String MIME_TYPE = "android.media.mediacodec.mime";
+
+ /**
+ * Key to extract what the codec mode
+ * from the {@link MediaCodec#getMetrics} return value.
+ * The value is a String. Values will be one of the constants
+ * {@link #MODE_AUDIO} or {@link #MODE_VIDEO}.
+ */
+ public static final String MODE = "android.media.mediacodec.mode";
+
+ /**
+ * The value returned for the key {@link #MODE} when the
+ * codec is a audio codec.
+ */
+ public static final String MODE_AUDIO = "audio";
+
+ /**
+ * The value returned for the key {@link #MODE} when the
+ * codec is a video codec.
+ */
+ public static final String MODE_VIDEO = "video";
+
+ /**
+ * Key to extract the flag indicating whether the codec is running
+ * as an encoder or decoder from the {@link MediaCodec#getMetrics} return value.
+ * The value is an integer.
+ * A 0 indicates decoder; 1 indicates encoder.
+ */
+ public static final String ENCODER = "android.media.mediacodec.encoder";
+
+ /**
+ * Key to extract the flag indicating whether the codec is running
+ * in secure (DRM) mode from the {@link MediaCodec#getMetrics} return value.
+ * The value is an integer.
+ */
+ public static final String SECURE = "android.media.mediacodec.secure";
+
+ /**
+ * Key to extract the width (in pixels) of the video track
+ * from the {@link MediaCodec#getMetrics} return value.
+ * The value is an integer.
+ */
+ public static final String WIDTH = "android.media.mediacodec.width";
+
+ /**
+ * Key to extract the height (in pixels) of the video track
+ * from the {@link MediaCodec#getMetrics} return value.
+ * The value is an integer.
+ */
+ public static final String HEIGHT = "android.media.mediacodec.height";
+
+ /**
+ * Key to extract the rotation (in degrees) to properly orient the video
+ * from the {@link MediaCodec#getMetrics} return.
+ * The value is a integer.
+ */
+ public static final String ROTATION = "android.media.mediacodec.rotation";
+
+ }
}
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index a0a6a1e..fe461be 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -25,10 +25,10 @@
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.media.MediaHTTPService;
-import android.media.MediaMetricsSet;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.PersistableBundle;
import com.android.internal.util.Preconditions;
@@ -689,22 +689,21 @@
/**
* Return Metrics data about the current media container.
*
- * @return a MediaMetricsSet containing the set of attributes and values
+ * @return a {@link PersistableBundle} containing the set of attributes and values
* available for the media container being handled by this instance
* of MediaExtractor.
- * The attributes are descibed in {@link MediaMetricsSet.MediaExtractor}.
+ * The attributes are descibed in {@link MetricsConstants}.
*
* Additional vendor-specific fields may also be present in
* the return value.
*/
- public MediaMetricsSet getMetrics() {
- Bundle bundle = native_getMetrics();
- MediaMetricsSet mSet = new MediaMetricsSet(bundle);
- return mSet;
+ public PersistableBundle getMetrics() {
+ PersistableBundle bundle = native_getMetrics();
+ return bundle;
}
- private native Bundle native_getMetrics();
+ private native PersistableBundle native_getMetrics();
private static native final void native_init();
private native final void native_setup();
@@ -718,4 +717,32 @@
private MediaCas mMediaCas;
private long mNativeContext;
+
+ public final static class MetricsConstants
+ {
+ private MetricsConstants() {}
+
+ /**
+ * Key to extract the container format
+ * from the {@link MediaExtractor#getMetrics} return value.
+ * The value is a String.
+ */
+ public static final String FORMAT = "android.media.mediaextractor.fmt";
+
+ /**
+ * Key to extract the container MIME type
+ * from the {@link MediaExtractor#getMetrics} return value.
+ * The value is a String.
+ */
+ public static final String MIME_TYPE = "android.media.mediaextractor.mime";
+
+ /**
+ * Key to extract the number of tracks in the container
+ * from the {@link MediaExtractor#getMetrics} return value.
+ * The value is an integer.
+ */
+ public static final String TRACKS = "android.media.mediaextractor.ntrk";
+
+ }
+
}
diff --git a/media/java/android/media/MediaMetricsSet.java b/media/java/android/media/MediaMetricsSet.java
deleted file mode 100644
index 5ecbee2..0000000
--- a/media/java/android/media/MediaMetricsSet.java
+++ /dev/null
@@ -1,491 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.os.Bundle;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.Runnable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.ref.WeakReference;
-import java.net.HttpCookie;
-import java.net.HttpURLConnection;
-import java.net.InetSocketAddress;
-import java.net.URL;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-import java.util.BitSet;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Scanner;
-import java.util.Set;
-import java.util.UUID;
-import java.util.Vector;
-
-
-/**
- * MediaMetricsSet contains the results returned by the getMetrics()
- * methods defined in other Media classes such as
- * {@link MediaCodec}, {@link MediaExtractor}, {@link MediaPlayer},
- * and {@link MediaRecorder}.
- *
- * MediaMetricsSet behaves similarly to a {@link Bundle}. It contains
- * a set of keys and values.
- * Methods such as {@link #getInt} and {@link #getString} are provided
- * to extract values of the corresponding types.
- * The {@link #keySet} method can be used to discover all of the keys
- * that are present in the particular instance.
- *
- */
-public final class MediaMetricsSet
-{
-
- /**
- * This MediaCodec class holds the constants defining keys related to
- * the metrics for a MediaCodec.
- */
- public final static class MediaCodec
- {
- private MediaCodec() {}
-
- /**
- * Key to extract the codec being used
- * from the {@link MediaCodec#getMetrics} return value.
- * The value is a String.
- */
- public static final String KEY_CODEC = "android.media.mediacodec.codec";
-
- /**
- * Key to extract the MIME type
- * from the {@link MediaCodec#getMetrics} return value.
- * The value is a String.
- */
- public static final String KEY_MIME = "android.media.mediacodec.mime";
-
- /**
- * Key to extract what the codec mode
- * from the {@link MediaCodec#getMetrics} return value.
- * The value is a String. Values will be one of the constants
- * MODE_AUDIO or MODE_VIDEO.
- */
- public static final String KEY_MODE = "android.media.mediacodec.mode";
-
- /**
- * The value returned for the key {@link #KEY_MODE} when the
- * codec is a audio codec.
- */
- public static final String MODE_AUDIO = "audio";
-
- /**
- * The value returned for the key {@link #KEY_MODE} when the
- * codec is a video codec.
- */
- public static final String MODE_VIDEO = "video";
-
- /**
- * Key to extract the flag indicating whether the codec is running
- * as an encoder or decoder from the {@link MediaCodec#getMetrics} return value.
- * The value is an integer.
- * A 0 indicates decoder; 1 indicates encoder.
- */
- public static final String KEY_ENCODER = "android.media.mediacodec.encoder";
-
- /**
- * Key to extract the flag indicating whether the codec is running
- * in secure (DRM) mode from the {@link MediaCodec#getMetrics} return value.
- * The value is an integer.
- */
- public static final String KEY_SECURE = "android.media.mediacodec.secure";
-
- /**
- * Key to extract the width (in pixels) of the video track
- * from the {@link MediaCodec#getMetrics} return value.
- * The value is an integer.
- */
- public static final String KEY_WIDTH = "android.media.mediacodec.width";
-
- /**
- * Key to extract the height (in pixels) of the video track
- * from the {@link MediaCodec#getMetrics} return value.
- * The value is an integer.
- */
- public static final String KEY_HEIGHT = "android.media.mediacodec.height";
-
- /**
- * Key to extract the rotation (in degrees) to properly orient the video
- * from the {@link MediaCodec#getMetrics} return.
- * The value is a integer.
- */
- public static final String KEY_ROTATION = "android.media.mediacodec.rotation";
-
- }
-
- /**
- * This class holds the constants defining keys related to
- * the metrics for a MediaExtractor.
- */
- public final static class MediaExtractor
- {
- private MediaExtractor() {}
-
- /**
- * Key to extract the container format
- * from the {@link MediaExtractor#getMetrics} return value.
- * The value is a String.
- */
- public static final String KEY_FORMAT = "android.media.mediaextractor.fmt";
-
- /**
- * Key to extract the container MIME type
- * from the {@link MediaExtractor#getMetrics} return value.
- * The value is a String.
- */
- public static final String KEY_MIME = "android.media.mediaextractor.mime";
-
- /**
- * Key to extract the number of tracks in the container
- * from the {@link MediaExtractor#getMetrics} return value.
- * The value is an integer.
- */
- public static final String KEY_TRACKS = "android.media.mediaextractor.ntrk";
-
- }
-
- /**
- * This class holds the constants defining keys related to
- * the metrics for a MediaPlayer.
- */
- public final static class MediaPlayer
- {
- private MediaPlayer() {}
-
- /**
- * Key to extract the MIME type of the video track
- * from the {@link MediaPlayer#getMetrics} return value.
- * The value is a String.
- */
- public static final String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime";
-
- /**
- * Key to extract the codec being used to decode the video track
- * from the {@link MediaPlayer#getMetrics} return value.
- * The value is a String.
- */
- public static final String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec";
-
- /**
- * Key to extract the width (in pixels) of the video track
- * from the {@link MediaPlayer#getMetrics} return value.
- * The value is an integer.
- */
- public static final String KEY_WIDTH = "android.media.mediaplayer.width";
-
- /**
- * Key to extract the height (in pixels) of the video track
- * from the {@link MediaPlayer#getMetrics} return value.
- * The value is an integer.
- */
- public static final String KEY_HEIGHT = "android.media.mediaplayer.height";
-
- /**
- * Key to extract the count of video frames played
- * from the {@link MediaPlayer#getMetrics} return value.
- * The value is an integer.
- */
- public static final String KEY_FRAMES = "android.media.mediaplayer.frames";
-
- /**
- * Key to extract the count of video frames dropped
- * from the {@link MediaPlayer#getMetrics} return value.
- * The value is an integer.
- */
- public static final String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped";
-
- /**
- * Key to extract the MIME type of the audio track
- * from the {@link MediaPlayer#getMetrics} return value.
- * The value is a String.
- */
- public static final String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime";
-
- /**
- * Key to extract the codec being used to decode the audio track
- * from the {@link MediaPlayer#getMetrics} return value.
- * The value is a String.
- */
- public static final String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
-
- /**
- * Key to extract the duration (in milliseconds) of the
- * media being played
- * from the {@link MediaPlayer#getMetrics} return value.
- * The value is a long.
- */
- public static final String KEY_DURATION = "android.media.mediaplayer.durationMs";
-
- /**
- * Key to extract the playing time (in milliseconds) of the
- * media being played
- * from the {@link MediaPlayer#getMetrics} return value.
- * The value is a long.
- */
- public static final String KEY_PLAYING = "android.media.mediaplayer.playingMs";
-
- /**
- * Key to extract the count of errors encountered while
- * playing the media
- * from the {@link MediaPlayer#getMetrics} return value.
- * The value is an integer.
- */
- public static final String KEY_ERRORS = "android.media.mediaplayer.err";
-
- /**
- * Key to extract an (optional) error code detected while
- * playing the media
- * from the {@link MediaPlayer#getMetrics} return value.
- * The value is an integer.
- */
- public static final String KEY_ERROR_CODE = "android.media.mediaplayer.errcode";
-
- }
-
- /**
- * This class holds the constants defining keys related to
- * the metrics for a MediaRecorder.
- */
- public final static class MediaRecorder
- {
- private MediaRecorder() {}
-
- /**
- * Key to extract the audio bitrate
- * from the {@link MediaRecorder#getMetrics} return.
- * The value is an integer.
- */
- public static final String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
-
- /**
- * Key to extract the number of audio channels
- * from the {@link MediaRecorder#getMetrics} return.
- * The value is an integer.
- */
- public static final String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
-
- /**
- * Key to extract the audio samplerate
- * from the {@link MediaRecorder#getMetrics} return.
- * The value is an integer.
- */
- public static final String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
-
- /**
- * Key to extract the audio timescale
- * from the {@link MediaRecorder#getMetrics} return.
- * The value is an integer.
- */
- public static final String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
-
- /**
- * Key to extract the video capture frame rate
- * from the {@link MediaRecorder#getMetrics} return.
- * The value is a double.
- */
- public static final String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
-
- /**
- * Key to extract the video capture framerate enable value
- * from the {@link MediaRecorder#getMetrics} return.
- * The value is an integer.
- */
- public static final String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
-
- /**
- * Key to extract the intended playback frame rate
- * from the {@link MediaRecorder#getMetrics} return.
- * The value is an integer.
- */
- public static final String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate";
-
- /**
- * Key to extract the height (in pixels) of the captured video
- * from the {@link MediaRecorder#getMetrics} return.
- * The value is an integer.
- */
- public static final String KEY_HEIGHT = "android.media.mediarecorder.height";
-
- /**
- * Key to extract the recorded movies time units
- * from the {@link MediaRecorder#getMetrics} return.
- * The value is an integer.
- * A value of 1000 indicates that the movie's timing is in milliseconds.
- */
- public static final String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
-
- /**
- * Key to extract the rotation (in degrees) to properly orient the video
- * from the {@link MediaRecorder#getMetrics} return.
- * The value is an integer.
- */
- public static final String KEY_ROTATION = "android.media.mediarecorder.rotation";
-
- /**
- * Key to extract the video bitrate from being used
- * from the {@link MediaRecorder#getMetrics} return.
- * The value is an integer.
- */
- public static final String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
-
- /**
- * Key to extract the value for how often video iframes are generated
- * from the {@link MediaRecorder#getMetrics} return.
- * The value is an integer.
- */
- public static final String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
-
- /**
- * Key to extract the video encoding level
- * from the {@link MediaRecorder#getMetrics} return.
- * The value is an integer.
- */
- public static final String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
-
- /**
- * Key to extract the video encoding profile
- * from the {@link MediaRecorder#getMetrics} return.
- * The value is an integer.
- */
- public static final String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
-
- /**
- * Key to extract the recorded video time units
- * from the {@link MediaRecorder#getMetrics} return.
- * The value is an integer.
- * A value of 1000 indicates that the video's timing is in milliseconds.
- */
- public static final String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
-
- /**
- * Key to extract the width (in pixels) of the captured video
- * from the {@link MediaRecorder#getMetrics} return.
- * The value is an integer.
- */
- public static final String KEY_WIDTH = "android.media.mediarecorder.width";
-
- }
-
- /*
- * Methods that we want
- */
-
- private Bundle mBundle;
-
- MediaMetricsSet(Bundle bundle) {
- mBundle = bundle;
- }
-
- /**
- * Returns the number of mappings contained in this Bundle.
- *
- * @return the number of mappings as an int.
- */
- public int size() {
- return mBundle.size();
- }
-
- /**
- * Returns true if the mapping of this MediaMetricsSet is empty,
- * false otherwise.
- */
- public boolean isEmpty() {
- return mBundle.isEmpty();
- }
-
- /**
- * Returns the value associated with the given key, or defaultValue if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @param defaultValue Value to return if key does not exist
- * @return a double value
- */
- public double getDouble(String key, double defaultValue) {
- return mBundle.getDouble(key, defaultValue);
- }
-
- /**
- * Returns the value associated with the given key, or defaultValue if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @param defaultValue Value to return if key does not exist
- * @return an int value
- */
- public int getInt(String key, int defaultValue) {
- return mBundle.getInt(key, defaultValue);
- }
-
- /**
- * Returns the value associated with the given key, or defaultValue if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @param defaultValue Value to return if key does not exist
- * @return a long value
- */
- public long getLong(String key, long defaultValue) {
- return mBundle.getLong(key, defaultValue);
- }
-
- /**
- * Returns the value associated with the given key, or defaultValue if
- * no mapping of the desired type exists for the given key or if a null
- * value is explicitly associated with the given key.
- *
- * @param key a String
- * @param defaultValue Value to return if key does not exist or if a null
- * value is associated with the given key.
- * @return the String value associated with the given key, or defaultValue
- * if no valid String object is currently mapped to that key.
- */
- public String getString(String key, String defaultValue) {
- return mBundle.getString(key, defaultValue);
- }
-
- /**
- * Returns a Set containing the Strings used as keys in this Bundle.
- *
- * @return a Set of String keys
- */
- public Set<String> keySet() {
- return mBundle.keySet();
- }
-
-
-
- public String toString() {
- return mBundle.toString();
- }
-
-}
-
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 71a968b..9386246 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -33,6 +33,7 @@
import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.PersistableBundle;
import android.os.Process;
import android.os.PowerManager;
import android.os.SystemProperties;
@@ -48,7 +49,6 @@
import android.media.AudioManager;
import android.media.MediaDrm;
import android.media.MediaFormat;
-import android.media.MediaMetricsSet;
import android.media.MediaTimeProvider;
import android.media.PlaybackParams;
import android.media.SubtitleController;
@@ -1491,20 +1491,19 @@
/**
* Return Metrics data about the current player.
*
- * @return a MediaMetricsSet containing the set of attributes and values
+ * @return a {@link PersistableBundle} containing the set of attributes and values
* available for the media being handled by this instance of MediaPlayer
- * The attributes are descibed in {@link MediaMetricsSet.MediaPlayer}.
+ * The attributes are descibed in {@link MetricsConstants}.
*
* Additional vendor-specific fields may also be present in
* the return value.
*/
- public MediaMetricsSet getMetrics() {
- Bundle bundle = native_getMetrics();
- MediaMetricsSet mSet = new MediaMetricsSet(bundle);
- return mSet;
+ public PersistableBundle getMetrics() {
+ PersistableBundle bundle = native_getMetrics();
+ return bundle;
}
- private native Bundle native_getMetrics();
+ private native PersistableBundle native_getMetrics();
/**
* Checks whether the MediaPlayer is playing.
@@ -5418,4 +5417,98 @@
}
}
}
+
+ public final static class MetricsConstants
+ {
+ private MetricsConstants() {}
+
+ /**
+ * Key to extract the MIME type of the video track
+ * from the {@link MediaPlayer#getMetrics} return value.
+ * The value is a String.
+ */
+ public static final String MIME_TYPE_VIDEO = "android.media.mediaplayer.video.mime";
+
+ /**
+ * Key to extract the codec being used to decode the video track
+ * from the {@link MediaPlayer#getMetrics} return value.
+ * The value is a String.
+ */
+ public static final String CODEC_VIDEO = "android.media.mediaplayer.video.codec";
+
+ /**
+ * Key to extract the width (in pixels) of the video track
+ * from the {@link MediaPlayer#getMetrics} return value.
+ * The value is an integer.
+ */
+ public static final String WIDTH = "android.media.mediaplayer.width";
+
+ /**
+ * Key to extract the height (in pixels) of the video track
+ * from the {@link MediaPlayer#getMetrics} return value.
+ * The value is an integer.
+ */
+ public static final String HEIGHT = "android.media.mediaplayer.height";
+
+ /**
+ * Key to extract the count of video frames played
+ * from the {@link MediaPlayer#getMetrics} return value.
+ * The value is an integer.
+ */
+ public static final String FRAMES = "android.media.mediaplayer.frames";
+
+ /**
+ * Key to extract the count of video frames dropped
+ * from the {@link MediaPlayer#getMetrics} return value.
+ * The value is an integer.
+ */
+ public static final String FRAMES_DROPPED = "android.media.mediaplayer.dropped";
+
+ /**
+ * Key to extract the MIME type of the audio track
+ * from the {@link MediaPlayer#getMetrics} return value.
+ * The value is a String.
+ */
+ public static final String MIME_TYPE_AUDIO = "android.media.mediaplayer.audio.mime";
+
+ /**
+ * Key to extract the codec being used to decode the audio track
+ * from the {@link MediaPlayer#getMetrics} return value.
+ * The value is a String.
+ */
+ public static final String CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
+
+ /**
+ * Key to extract the duration (in milliseconds) of the
+ * media being played
+ * from the {@link MediaPlayer#getMetrics} return value.
+ * The value is a long.
+ */
+ public static final String DURATION = "android.media.mediaplayer.durationMs";
+
+ /**
+ * Key to extract the playing time (in milliseconds) of the
+ * media being played
+ * from the {@link MediaPlayer#getMetrics} return value.
+ * The value is a long.
+ */
+ public static final String PLAYING = "android.media.mediaplayer.playingMs";
+
+ /**
+ * Key to extract the count of errors encountered while
+ * playing the media
+ * from the {@link MediaPlayer#getMetrics} return value.
+ * The value is an integer.
+ */
+ public static final String ERRORS = "android.media.mediaplayer.err";
+
+ /**
+ * Key to extract an (optional) error code detected while
+ * playing the media
+ * from the {@link MediaPlayer#getMetrics} return value.
+ * The value is an integer.
+ */
+ public static final String ERROR_CODE = "android.media.mediaplayer.errcode";
+
+ }
}
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 4675e32..997d562 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -20,14 +20,15 @@
import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.hardware.Camera;
-import android.media.MediaMetricsSet;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.PersistableBundle;
import android.util.Log;
import android.view.Surface;
+import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.RandomAccessFile;
@@ -92,6 +93,7 @@
private String mPath;
private FileDescriptor mFd;
+ private File mFile;
private EventHandler mEventHandler;
private OnErrorListener mOnErrorListener;
private OnInfoListener mOnInfoListener;
@@ -804,10 +806,26 @@
public void setOutputFile(FileDescriptor fd) throws IllegalStateException
{
mPath = null;
+ mFile = null;
mFd = fd;
}
/**
+ * Pass in the file object to be written. Call this after setOutputFormat() but before prepare().
+ * File should be seekable. After setting the next output file, application should not use the
+ * file until {@link #stop}. Application is responsible for cleaning up unused files after
+ * {@link #stop} is called.
+ *
+ * @param file the file object to be written into.
+ */
+ public void setOutputFile(File file)
+ {
+ mPath = null;
+ mFd = null;
+ mFile = file;
+ }
+
+ /**
* Sets the next output file descriptor to be used when the maximum filesize is reached
* on the prior output {@link #setOutputFile} or {@link #setNextOutputFile}). File descriptor
* must be seekable and writable. After setting the next output file, application should not
@@ -842,15 +860,16 @@
public void setOutputFile(String path) throws IllegalStateException
{
mFd = null;
+ mFile = null;
mPath = path;
}
/**
- * Sets the next output file path to be used when the maximum filesize is reached
- * on the prior output {@link #setOutputFile} or {@link #setNextOutputFile}). File should
- * be seekable. After setting the next output file, application should not use the file
- * referenced by this file descriptor until {@link #stop}. Application must call this
- * after receiving on the {@link android.media.MediaRecorder.OnInfoListener} a "what" code of
+ * Sets the next output file to be used when the maximum filesize is reached on the prior
+ * output {@link #setOutputFile} or {@link #setNextOutputFile}). File should be seekable.
+ * After setting the next output file, application should not use the file until {@link #stop}.
+ * Application must call this after receiving on the
+ * {@link android.media.MediaRecorder.OnInfoListener} a "what" code of
* {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING} and before receiving a "what" code of
* {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}. The file is not used until switching to
* that output. Application will receive {@link #MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED}
@@ -858,19 +877,17 @@
* the previous one has not been used. Application is responsible for cleaning up unused files
* after {@link #stop} is called.
*
- * @param path The pathname to use.
+ * @param file The file to use.
* @throws IllegalStateException if it is called before prepare().
* @throws IOException if setNextOutputFile fails otherwise.
*/
- public void setNextOutputFile(String path) throws IllegalStateException, IOException
+ public void setNextOutputFile(File file) throws IllegalStateException, IOException
{
- if (path != null) {
- RandomAccessFile file = new RandomAccessFile(path, "rws");
- try {
- _setNextOutputFile(file.getFD());
- } finally {
- file.close();
- }
+ RandomAccessFile f = new RandomAccessFile(file, "rws");
+ try {
+ _setNextOutputFile(f.getFD());
+ } finally {
+ f.close();
}
}
@@ -899,6 +916,13 @@
}
} else if (mFd != null) {
_setOutputFile(mFd);
+ } else if (mFile != null) {
+ RandomAccessFile file = new RandomAccessFile(mFile, "rws");
+ try {
+ _setOutputFile(file.getFD());
+ } finally {
+ file.close();
+ }
} else {
throw new IOException("No valid output file");
}
@@ -1267,23 +1291,142 @@
/**
* Return Metrics data about the current Mediarecorder instance.
*
- * @return a MediaMetricsSet containing the set of attributes and values
+ * @return a {@link PersistableBundle} containing the set of attributes and values
* available for the media being generated by this instance of
* MediaRecorder.
- * The attributes are descibed in {@link MediaMetricsSet.MediaRecorder}.
+ * The attributes are descibed in {@link MetricsConstants}.
*
* Additional vendor-specific fields may also be present in
* the return value.
*/
- public MediaMetricsSet getMetrics() {
- Bundle bundle = native_getMetrics();
- MediaMetricsSet mSet = new MediaMetricsSet(bundle);
- return mSet;
+ public PersistableBundle getMetrics() {
+ PersistableBundle bundle = native_getMetrics();
+ return bundle;
}
- private native Bundle native_getMetrics();
+ private native PersistableBundle native_getMetrics();
@Override
protected void finalize() { native_finalize(); }
+
+ public final static class MetricsConstants
+ {
+ private MetricsConstants() {}
+
+ /**
+ * Key to extract the audio bitrate
+ * from the {@link MediaRecorder#getMetrics} return.
+ * The value is an integer.
+ */
+ public static final String AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
+
+ /**
+ * Key to extract the number of audio channels
+ * from the {@link MediaRecorder#getMetrics} return.
+ * The value is an integer.
+ */
+ public static final String AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
+
+ /**
+ * Key to extract the audio samplerate
+ * from the {@link MediaRecorder#getMetrics} return.
+ * The value is an integer.
+ */
+ public static final String AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
+
+ /**
+ * Key to extract the audio timescale
+ * from the {@link MediaRecorder#getMetrics} return.
+ * The value is an integer.
+ */
+ public static final String AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
+
+ /**
+ * Key to extract the video capture frame rate
+ * from the {@link MediaRecorder#getMetrics} return.
+ * The value is a double.
+ */
+ public static final String CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
+
+ /**
+ * Key to extract the video capture framerate enable value
+ * from the {@link MediaRecorder#getMetrics} return.
+ * The value is an integer.
+ */
+ public static final String CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
+
+ /**
+ * Key to extract the intended playback frame rate
+ * from the {@link MediaRecorder#getMetrics} return.
+ * The value is an integer.
+ */
+ public static final String FRAMERATE = "android.media.mediarecorder.frame-rate";
+
+ /**
+ * Key to extract the height (in pixels) of the captured video
+ * from the {@link MediaRecorder#getMetrics} return.
+ * The value is an integer.
+ */
+ public static final String HEIGHT = "android.media.mediarecorder.height";
+
+ /**
+ * Key to extract the recorded movies time units
+ * from the {@link MediaRecorder#getMetrics} return.
+ * The value is an integer.
+ * A value of 1000 indicates that the movie's timing is in milliseconds.
+ */
+ public static final String MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
+
+ /**
+ * Key to extract the rotation (in degrees) to properly orient the video
+ * from the {@link MediaRecorder#getMetrics} return.
+ * The value is an integer.
+ */
+ public static final String ROTATION = "android.media.mediarecorder.rotation";
+
+ /**
+ * Key to extract the video bitrate from being used
+ * from the {@link MediaRecorder#getMetrics} return.
+ * The value is an integer.
+ */
+ public static final String VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
+
+ /**
+ * Key to extract the value for how often video iframes are generated
+ * from the {@link MediaRecorder#getMetrics} return.
+ * The value is an integer.
+ */
+ public static final String VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
+
+ /**
+ * Key to extract the video encoding level
+ * from the {@link MediaRecorder#getMetrics} return.
+ * The value is an integer.
+ */
+ public static final String VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
+
+ /**
+ * Key to extract the video encoding profile
+ * from the {@link MediaRecorder#getMetrics} return.
+ * The value is an integer.
+ */
+ public static final String VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
+
+ /**
+ * Key to extract the recorded video time units
+ * from the {@link MediaRecorder#getMetrics} return.
+ * The value is an integer.
+ * A value of 1000 indicates that the video's timing is in milliseconds.
+ */
+ public static final String VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
+
+ /**
+ * Key to extract the width (in pixels) of the captured video
+ * from the {@link MediaRecorder#getMetrics} return.
+ * The value is an integer.
+ */
+ public static final String WIDTH = "android.media.mediarecorder.width";
+
+ }
}
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index a8dd313..2178607 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -2002,7 +2002,7 @@
{ "getName", "()Ljava/lang/String;",
(void *)android_media_MediaCodec_getName },
- { "native_getMetrics", "()Landroid/os/Bundle;",
+ { "native_getMetrics", "()Landroid/os/PersistableBundle;",
(void *)android_media_MediaCodec_native_getMetrics},
{ "setParameters", "([Ljava/lang/String;[Ljava/lang/Object;)V",
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index c2cfed9..9e5d3d1 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -905,7 +905,7 @@
{ "hasCacheReachedEndOfStream", "()Z",
(void *)android_media_MediaExtractor_hasCacheReachedEOS },
- {"native_getMetrics", "()Landroid/os/Bundle;",
+ {"native_getMetrics", "()Landroid/os/PersistableBundle;",
(void *)android_media_MediaExtractor_native_getMetrics},
};
diff --git a/media/jni/android_media_MediaMetricsJNI.cpp b/media/jni/android_media_MediaMetricsJNI.cpp
index fb606ba..8979cec 100644
--- a/media/jni/android_media_MediaMetricsJNI.cpp
+++ b/media/jni/android_media_MediaMetricsJNI.cpp
@@ -24,15 +24,12 @@
namespace android {
-// place the attributes into a java Bundle object
-// decide whether this is appropriately scoped here.
-// if we do it somewhere else, we have to figure a "give me all the attrs"
-// access to the inside of MediaAnalyticsItem
+// place the attributes into a java PersistableBundle object
jobject MediaMetricsJNI::writeMetricsToBundle(JNIEnv* env, MediaAnalyticsItem *item, jobject mybundle) {
- jclass clazzBundle = env->FindClass("android/os/Bundle");
+ jclass clazzBundle = env->FindClass("android/os/PersistableBundle");
if (clazzBundle==NULL) {
- ALOGD("can't find android/os/Bundle");
+ ALOGD("can't find android/os/PersistableBundle");
return NULL;
}
// sometimes the caller provides one for us to fill
@@ -58,7 +55,7 @@
// -- get name, get type, get value
// -- insert appropriately into the bundle
for (size_t i = 0 ; i < item->mPropCount; i++ ) {
- MediaAnalyticsItem::Prop *prop = &item->mProps[i];
+ MediaAnalyticsItem::Prop *prop = &item->mProps[i];
// build the key parameter from prop->mName
jstring keyName = env->NewStringUTF(prop->mName);
// invoke the appropriate method to insert
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 1b52cf5..2fc4afd 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -1393,7 +1393,7 @@
{"_stop", "()V", (void *)android_media_MediaPlayer_stop},
{"getVideoWidth", "()I", (void *)android_media_MediaPlayer_getVideoWidth},
{"getVideoHeight", "()I", (void *)android_media_MediaPlayer_getVideoHeight},
- {"native_getMetrics", "()Landroid/os/Bundle;", (void *)android_media_MediaPlayer_native_getMetrics},
+ {"native_getMetrics", "()Landroid/os/PersistableBundle;", (void *)android_media_MediaPlayer_native_getMetrics},
{"setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer_setPlaybackParams},
{"getPlaybackParams", "()Landroid/media/PlaybackParams;", (void *)android_media_MediaPlayer_getPlaybackParams},
{"setSyncParams", "(Landroid/media/SyncParams;)V", (void *)android_media_MediaPlayer_setSyncParams},
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 7a63e00..2c1e834 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -688,7 +688,7 @@
{"native_finalize", "()V", (void *)android_media_MediaRecorder_native_finalize},
{"native_setInputSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaRecorder_setInputSurface },
- {"native_getMetrics", "()Landroid/os/Bundle;", (void *)android_media_MediaRecorder_native_getMetrics},
+ {"native_getMetrics", "()Landroid/os/PersistableBundle;", (void *)android_media_MediaRecorder_native_getMetrics},
};
// This function only registers the native methods, and is called from
diff --git a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java
index 444705c..ece700d 100644
--- a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java
+++ b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java
@@ -100,8 +100,8 @@
int newState) {
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED) {
- Log.i(TAG, "Connected to GATT server.");
- Log.i(TAG, "Attempting to start service discovery:" +
+ Log.d(TAG, "Connected to GATT server.");
+ Log.d(TAG, "Attempting to start service discovery:" +
mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.i(TAG, "Disconnected from GATT server.");
@@ -112,24 +112,24 @@
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
- List<BluetoothGattService> services = mBluetoothGatt.getServices();
- for (BluetoothGattService service : services) {
- if (MIDI_SERVICE.equals(service.getUuid())) {
- Log.d(TAG, "found MIDI_SERVICE");
- List<BluetoothGattCharacteristic> characteristics
- = service.getCharacteristics();
- for (BluetoothGattCharacteristic characteristic : characteristics) {
- if (MIDI_CHARACTERISTIC.equals(characteristic.getUuid())) {
- Log.d(TAG, "found MIDI_CHARACTERISTIC");
- mCharacteristic = characteristic;
+ BluetoothGattService service = gatt.getService(MIDI_SERVICE);
+ if (service != null) {
+ Log.d(TAG, "found MIDI_SERVICE");
+ BluetoothGattCharacteristic characteristic
+ = service.getCharacteristic(MIDI_CHARACTERISTIC);
+ if (characteristic != null) {
+ Log.d(TAG, "found MIDI_CHARACTERISTIC");
+ mCharacteristic = characteristic;
- // Specification says to read the characteristic first and then
- // switch to receiving notifications
- mBluetoothGatt.readCharacteristic(characteristic);
- break;
- }
- }
- break;
+ // Request a lower Connection Interval for better latency.
+ boolean result = gatt.requestConnectionPriority(
+ BluetoothGatt.CONNECTION_PRIORITY_HIGH);
+ Log.d(TAG, "requestConnectionPriority(CONNECTION_PRIORITY_HIGH):"
+ + result);
+
+ // Specification says to read the characteristic first and then
+ // switch to receiving notifications
+ mBluetoothGatt.readCharacteristic(characteristic);
}
}
} else {
diff --git a/packages/DefaultContainerService/AndroidManifest.xml b/packages/DefaultContainerService/AndroidManifest.xml
index 55d000c..e399fb1 100644
--- a/packages/DefaultContainerService/AndroidManifest.xml
+++ b/packages/DefaultContainerService/AndroidManifest.xml
@@ -1,5 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.defcontainer" coreApp="true">
+ <uses-permission android:name="android.permission.ALLOCATE_AGGRESSIVE"/>
<uses-permission android:name="android.permission.ASEC_ACCESS"/>
<uses-permission android:name="android.permission.ASEC_CREATE"/>
<uses-permission android:name="android.permission.ASEC_DESTROY"/>
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 37a68e0..9347877 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -30,6 +30,7 @@
import android.content.pm.PackageParser.PackageParserException;
import android.content.res.ObbInfo;
import android.content.res.ObbScanner;
+import android.os.Binder;
import android.os.Environment;
import android.os.Environment.UserEnvironment;
import android.os.FileUtils;
@@ -179,6 +180,15 @@
return ret;
}
+ final int recommendedInstallLocation;
+ final long token = Binder.clearCallingIdentity();
+ try {
+ recommendedInstallLocation = PackageHelper.resolveInstallLocation(context,
+ pkg.packageName, pkg.installLocation, sizeBytes, flags);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+
ret.packageName = pkg.packageName;
ret.splitNames = pkg.splitNames;
ret.versionCode = pkg.versionCode;
@@ -186,8 +196,7 @@
ret.splitRevisionCodes = pkg.splitRevisionCodes;
ret.installLocation = pkg.installLocation;
ret.verifiers = pkg.verifiers;
- ret.recommendedInstallLocation = PackageHelper.resolveInstallLocation(context,
- pkg.packageName, pkg.installLocation, sizeBytes, flags);
+ ret.recommendedInstallLocation = recommendedInstallLocation;
ret.multiArch = pkg.multiArch;
return ret;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index f277165..314791e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -234,10 +234,19 @@
}
/**
- * Forces an update of the wifi networks when not scanning.
+ * Synchronously update the list of access points with the latest information.
*/
public void forceUpdate() {
+ mWorkHandler.removeMessages(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
+
+ mLastInfo = mWifiManager.getConnectionInfo();
+ mLastNetworkInfo = mConnectivityManager.getNetworkInfo(mWifiManager.getCurrentNetwork());
updateAccessPoints();
+
+ // Synchronously copy access points
+ mMainHandler.removeMessages(MainHandler.MSG_ACCESS_POINT_CHANGED);
+ mMainHandler.handleMessage(
+ Message.obtain(mMainHandler, MainHandler.MSG_ACCESS_POINT_CHANGED));
}
/**
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index f9e695d..b938fe2 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -20,7 +20,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.atLeast;
@@ -33,12 +32,13 @@
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
+import android.net.Network;
import android.net.NetworkBadging;
import android.net.NetworkInfo;
import android.net.NetworkKey;
import android.net.NetworkScoreManager;
-import android.net.ScoredNetwork;
import android.net.RssiCurve;
+import android.net.ScoredNetwork;
import android.net.WifiKey;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
@@ -47,10 +47,10 @@
import android.net.wifi.WifiNetworkScoreCache;
import android.net.wifi.WifiSsid;
import android.os.Bundle;
-import android.os.SystemClock;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
+import android.os.SystemClock;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
@@ -62,8 +62,8 @@
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
-import org.mockito.Matchers;
import org.mockito.Captor;
+import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
@@ -666,4 +666,29 @@
verify(mockWifiManager, atLeast(2)).getConnectionInfo();
assertThat(tracker.getAccessPoints().get(0).getRssi()).isEqualTo(newRssi);
}
+
+ @Test
+ public void forceUpdateShouldSynchronouslyFetchLatestInformation() throws Exception {
+ when(mockWifiManager.getConnectionInfo()).thenReturn(CONNECTED_AP_1_INFO);
+
+ WifiConfiguration configuration = new WifiConfiguration();
+ configuration.SSID = SSID_1;
+ configuration.BSSID = BSSID_1;
+ configuration.networkId = CONNECTED_NETWORK_ID;
+ when(mockWifiManager.getConfiguredNetworks()).thenReturn(Arrays.asList(configuration));
+
+ NetworkInfo networkInfo = new NetworkInfo(
+ ConnectivityManager.TYPE_WIFI, 0, "Type Wifi", "subtype");
+ networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "connected", "test");
+ when(mockConnectivityManager.getNetworkInfo(any(Network.class))).thenReturn(networkInfo);
+
+
+ WifiTracker tracker = createMockedWifiTracker();
+ startTracking(tracker);
+ tracker.forceUpdate();
+
+ verify(mockWifiListener).onAccessPointsChanged();
+ assertThat(tracker.getAccessPoints().size()).isEqualTo(2);
+ assertThat(tracker.getAccessPoints().get(0).isActive()).isTrue();
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/styles_tv.xml b/packages/SystemUI/res/values/styles_tv.xml
index 3f0caab..0c4fd23 100644
--- a/packages/SystemUI/res/values/styles_tv.xml
+++ b/packages/SystemUI/res/values/styles_tv.xml
@@ -21,5 +21,6 @@
<style name="PipTheme" parent="@android:style/Theme.Translucent.NoTitleBar.Fullscreen">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:backgroundDimEnabled">false</item>
+ <item name="android:windowDisablePreview">true</item>
</style>
</resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index f8d1bfb..7a6ac57 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -165,11 +165,6 @@
private int mPhoneState;
private boolean mKeyguardIsVisible;
- /**
- * If true, fingerprint was already authenticated and we don't need to start listening again
- * until the Keyguard has been dismissed.
- */
- private boolean mFingerprintAlreadyAuthenticated;
private boolean mGoingToSleep;
private boolean mBouncer;
private boolean mBootCompleted;
@@ -409,11 +404,8 @@
private void onFingerprintAuthenticated(int userId) {
Trace.beginSection("KeyGuardUpdateMonitor#onFingerPrintAuthenticated");
mUserFingerprintAuthenticated.put(userId, true);
-
- // If fingerprint unlocking is allowed, this event will lead to a Keyguard dismiss or to a
- // wake-up (if Keyguard is not showing), so we don't need to listen until Keyguard is
- // fully gone.
- mFingerprintAlreadyAuthenticated = isUnlockingWithFingerprintAllowed();
+ // Don't send cancel if authentication succeeds
+ mFingerprintCancelSignal = null;
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -922,7 +914,6 @@
}
}
mGoingToSleep = true;
- mFingerprintAlreadyAuthenticated = false;
updateFingerprintListeningState();
}
@@ -1092,8 +1083,7 @@
private boolean shouldListenForFingerprint() {
return (mKeyguardIsVisible || !mDeviceInteractive || mBouncer || mGoingToSleep)
- && !mSwitchingUser && !mFingerprintAlreadyAuthenticated
- && !isFingerprintDisabled(getCurrentUser());
+ && !mSwitchingUser && !isFingerprintDisabled(getCurrentUser());
}
private void startListeningForFingerprint() {
@@ -1416,9 +1406,6 @@
cb.onKeyguardVisibilityChangedRaw(showing);
}
}
- if (!showing) {
- mFingerprintAlreadyAuthenticated = false;
- }
updateFingerprintListeningState();
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
index f3fb1ef..ec56e15 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
@@ -33,6 +33,8 @@
boolean isPulsingBlocked();
void startPendingIntentDismissingKeyguard(PendingIntent intent);
+ void abortPulsing();
+ void extendPulse();
interface Callback {
default void onNotificationHeadsUp() {}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index f27521e..1cc5fb9 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -58,12 +58,15 @@
/** Pulse is done showing. Followed by transition to DOZE or DOZE_AOD. */
DOZE_PULSE_DONE,
/** Doze is done. DozeService is finished. */
- FINISH;
+ FINISH,
+ /** AOD, but the display is temporarily off. */
+ DOZE_AOD_PAUSED;
boolean canPulse() {
switch (this) {
case DOZE:
case DOZE_AOD:
+ case DOZE_AOD_PAUSED:
return true;
default:
return false;
@@ -85,6 +88,7 @@
case UNINITIALIZED:
case INITIALIZED:
case DOZE:
+ case DOZE_AOD_PAUSED:
return Display.STATE_OFF;
case DOZE_PULSING:
case DOZE_AOD:
@@ -241,6 +245,11 @@
if (mState == State.FINISH) {
return State.FINISH;
}
+ if ((mState == State.DOZE_AOD_PAUSED || mState == State.DOZE_AOD || mState == State.DOZE)
+ && requestedState == State.DOZE_PULSE_DONE) {
+ Log.i(TAG, "Dropping pulse done because current state is already done: " + mState);
+ return mState;
+ }
if (requestedState == State.DOZE_REQUEST_PULSE && !mState.canPulse()) {
Log.i(TAG, "Dropping pulse request because current state can't pulse: " + mState);
return mState;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 2ac0657..73f5222 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -22,6 +22,8 @@
import android.content.Context;
import android.database.ContentObserver;
import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.TriggerEvent;
import android.hardware.TriggerEventListener;
@@ -40,6 +42,7 @@
import java.io.PrintWriter;
import java.util.List;
+import java.util.function.Consumer;
public class DozeSensors {
@@ -55,18 +58,22 @@
private final DozeParameters mDozeParameters;
private final AmbientDisplayConfiguration mConfig;
private final WakeLock mWakeLock;
+ private final Consumer<Boolean> mProxCallback;
private final Callback mCallback;
private final Handler mHandler = new Handler();
+ private final ProxSensor mProxSensor;
public DozeSensors(Context context, SensorManager sensorManager, DozeParameters dozeParameters,
- AmbientDisplayConfiguration config, WakeLock wakeLock, Callback callback) {
+ AmbientDisplayConfiguration config, WakeLock wakeLock, Callback callback,
+ Consumer<Boolean> proxCallback) {
mContext = context;
mSensorManager = sensorManager;
mDozeParameters = dozeParameters;
mConfig = config;
mWakeLock = wakeLock;
+ mProxCallback = proxCallback;
mResolver = mContext.getContentResolver();
mSensors = new TriggerSensor[] {
@@ -86,6 +93,8 @@
true /* configured */,
DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP)
};
+
+ mProxSensor = new ProxSensor();
mCallback = callback;
}
@@ -129,6 +138,10 @@
}
}
+ public void setProxListening(boolean listen) {
+ mProxSensor.setRegistered(listen);
+ }
+
private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange, Uri uri, int userId) {
@@ -152,6 +165,43 @@
}
}
+ private class ProxSensor implements SensorEventListener {
+
+ boolean mRegistered;
+ Boolean mCurrentlyFar;
+
+ void setRegistered(boolean register) {
+ if (mRegistered == register) {
+ // Send an update even if we don't re-register.
+ mHandler.post(() -> {
+ if (mCurrentlyFar != null) {
+ mProxCallback.accept(mCurrentlyFar);
+ }
+ });
+ return;
+ }
+ if (register) {
+ mRegistered = mSensorManager.registerListener(this,
+ mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY),
+ SensorManager.SENSOR_DELAY_NORMAL, mHandler);
+ } else {
+ mSensorManager.unregisterListener(this);
+ mRegistered = false;
+ mCurrentlyFar = null;
+ }
+ }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ mCurrentlyFar = event.values[0] >= event.sensor.getMaximumRange();
+ mProxCallback.accept(mCurrentlyFar);
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+ }
+
private class TriggerSensor extends TriggerEventListener {
final Sensor mSensor;
final boolean mConfigured;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 1b9bf73..9b3593b 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -46,6 +46,7 @@
public class DozeTriggers implements DozeMachine.Part {
private static final String TAG = "DozeTriggers";
+ private static final boolean DEBUG = DozeService.DEBUG;
/** adb shell am broadcast -a com.android.systemui.doze.pulse com.android.systemui */
private static final String PULSE_ACTION = "com.android.systemui.doze.pulse";
@@ -81,7 +82,7 @@
mWakeLock = wakeLock;
mAllowPulseTriggers = allowPulseTriggers;
mDozeSensors = new DozeSensors(context, mSensorManager, dozeParameters, config,
- wakeLock, this::onSensor);
+ wakeLock, this::onSensor, this::onProximityFar);
mUiModeManager = mContext.getSystemService(UiModeManager.class);
}
@@ -113,6 +114,22 @@
}
}
+ private void onProximityFar(boolean far) {
+ final boolean near = !far;
+ DozeMachine.State state = mMachine.getState();
+ if (near && state == DozeMachine.State.DOZE_PULSING) {
+ if (DEBUG) Log.i(TAG, "Prox NEAR, ending pulse");
+ mMachine.requestState(DozeMachine.State.DOZE_PULSE_DONE);
+ }
+ if (far && state == DozeMachine.State.DOZE_AOD_PAUSED) {
+ if (DEBUG) Log.i(TAG, "Prox FAR, unpausing AOD");
+ mMachine.requestState(DozeMachine.State.DOZE_AOD);
+ } else if (near && state == DozeMachine.State.DOZE_AOD) {
+ if (DEBUG) Log.i(TAG, "Prox NEAR, pausing AOD");
+ mMachine.requestState(DozeMachine.State.DOZE_AOD_PAUSED);
+ }
+ }
+
private void onCarMode() {
mMachine.requestState(DozeMachine.State.FINISH);
}
@@ -131,15 +148,21 @@
break;
case DOZE:
case DOZE_AOD:
+ case DOZE_AOD_PAUSED:
+ mDozeSensors.setProxListening(newState != DozeMachine.State.DOZE);
mDozeSensors.setListening(true);
if (oldState != DozeMachine.State.INITIALIZED) {
mDozeSensors.reregisterAllSensors();
}
break;
+ case DOZE_PULSING:
+ mDozeSensors.setProxListening(true);
+ break;
case FINISH:
mBroadcastReceiver.unregister(mContext);
mDozeHost.removeCallback(mHostCallback);
mDozeSensors.setListening(false);
+ mDozeSensors.setProxListening(false);
break;
default:
}
@@ -156,6 +179,7 @@
private void requestPulse(final int reason, boolean performedProxCheck) {
Assert.isMainThread();
+ mDozeHost.extendPulse();
if (mPulsePending || !mAllowPulseTriggers || !canPulse()) {
return;
}
@@ -286,6 +310,8 @@
}
private class TriggerReceiver extends BroadcastReceiver {
+ private boolean mRegistered;
+
@Override
public void onReceive(Context context, Intent intent) {
if (PULSE_ACTION.equals(intent.getAction())) {
@@ -301,14 +327,22 @@
}
public void register(Context context) {
+ if (mRegistered) {
+ return;
+ }
IntentFilter filter = new IntentFilter(PULSE_ACTION);
filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
filter.addAction(Intent.ACTION_USER_SWITCHED);
context.registerReceiver(this, filter);
+ mRegistered = true;
}
public void unregister(Context context) {
+ if (!mRegistered) {
+ return;
+ }
context.unregisterReceiver(this);
+ mRegistered = false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index f577654..6098a20 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -75,11 +75,14 @@
scheduleTimeTick();
break;
case DOZE:
+ case DOZE_AOD_PAUSED:
unscheduleTimeTick();
break;
case DOZE_REQUEST_PULSE:
pulseWhileDozing(DozeLog.PULSE_REASON_NOTIFICATION /* TODO */);
break;
+ case DOZE_PULSE_DONE:
+ mHost.abortPulsing();
case INITIALIZED:
mHost.startDozing();
break;
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 9c4f16b..ac06703 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -195,6 +195,7 @@
updateFromIntent(getIntent());
setTitle(R.string.pip_menu_title);
+ setDisablePreviewScreenshots(true);
}
@Override
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 fb8574d..127296cd 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -37,10 +37,12 @@
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
+import android.view.Choreographer;
import android.view.animation.Interpolator;
import com.android.internal.os.BackgroundThread;
import com.android.internal.policy.PipSnapAlgorithm;
+import com.android.internal.view.SurfaceFlingerVsyncChoreographer;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.statusbar.FlingAnimationUtils;
@@ -72,6 +74,7 @@
private Context mContext;
private IActivityManager mActivityManager;
+ private SurfaceFlingerVsyncChoreographer mVsyncChoreographer;
private Handler mHandler;
private PipSnapAlgorithm mSnapAlgorithm;
@@ -96,6 +99,8 @@
mActivityManager = activityManager;
mSnapAlgorithm = snapAlgorithm;
mFlingAnimationUtils = flingAnimationUtils;
+ mVsyncChoreographer = new SurfaceFlingerVsyncChoreographer(mHandler, mContext.getDisplay(),
+ Choreographer.getInstance());
onConfigurationChanged();
}
@@ -394,7 +399,7 @@
*/
private void resizePipUnchecked(Rect toBounds) {
if (!toBounds.equals(mBounds)) {
- mHandler.post(() -> {
+ mVsyncChoreographer.scheduleAtSfVsync(() -> {
try {
mActivityManager.resizePinnedStack(toBounds, null /* tempPinnedTaskBounds */);
mBounds.set(toBounds);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index be16266..dd99749 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -23,6 +23,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewStub;
import android.widget.LinearLayout;
import com.android.systemui.Dependency;
@@ -36,6 +37,7 @@
import com.android.systemui.statusbar.policy.EncryptionHelper;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
/**
* Contains the collapsed status bar and handles hiding/showing based on disable flags
@@ -56,6 +58,13 @@
private DarkIconManager mDarkIconManager;
private SignalClusterView mSignalClusterView;
+ private SignalCallback mSignalCallback = new SignalCallback() {
+ @Override
+ public void setIsAirplaneMode(NetworkController.IconState icon) {
+ mStatusBarComponent.recomputeDisableFlags(true /* animate */);
+ }
+ };
+
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -84,6 +93,7 @@
Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mSignalClusterView);
// Default to showing until we know otherwise.
showSystemIconArea(false);
+ initEmergencyCryptkeeperText();
}
@Override
@@ -109,6 +119,9 @@
super.onDestroyView();
Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(mSignalClusterView);
Dependency.get(StatusBarIconController.class).removeIconGroup(mDarkIconManager);
+ if (mNetworkController.hasEmergencyCryptKeeperText()) {
+ mNetworkController.removeCallback(mSignalCallback);
+ }
}
public void initNotificationIconArea(NotificationIconAreaController
@@ -233,4 +246,17 @@
.start();
}
}
+
+ private void initEmergencyCryptkeeperText() {
+ View emergencyViewStub = mStatusBar.findViewById(R.id.emergency_cryptkeeper_text);
+ if (mNetworkController.hasEmergencyCryptKeeperText()) {
+ if (emergencyViewStub != null) {
+ ((ViewStub) emergencyViewStub).inflate();
+ }
+ mNetworkController.addCallback(mSignalCallback);
+ } else if (emergencyViewStub != null) {
+ ViewGroup parent = (ViewGroup) emergencyViewStub.getParent();
+ parent.removeView(emergencyViewStub);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index c3f8d97..40776ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -158,6 +158,10 @@
return sPickupSubtypePerformsProxMatcher.isIn(subType);
}
+ public int getPulseVisibleDurationExtended() {
+ return 2 * getPulseVisibleDuration();
+ }
+
/**
* Parses a spec of the form `1,2,3,!5,*`. The resulting object will match numbers that are
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index b78f748..c5f23c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -30,6 +30,7 @@
import com.android.systemui.Interpolators;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
+import com.android.systemui.doze.DozeTriggers;
/**
* Controller which handles all the doze animations of the scrims.
@@ -43,8 +44,6 @@
private final ScrimController mScrimController;
private final Context mContext;
- private final View mStackScroller;
- private final NotificationPanelView mNotificationPanelView;
private boolean mDozing;
private DozeHost.PulseCallback mPulseCallback;
@@ -53,24 +52,22 @@
private Animator mBehindAnimator;
private float mInFrontTarget;
private float mBehindTarget;
+ private boolean mDozingAborted;
- public DozeScrimController(ScrimController scrimController, Context context,
- View stackScroller, NotificationPanelView notificationPanelView) {
+ public DozeScrimController(ScrimController scrimController, Context context) {
mContext = context;
- mStackScroller = stackScroller;
mScrimController = scrimController;
mDozeParameters = new DozeParameters(context);
- mNotificationPanelView = notificationPanelView;
}
public void setDozing(boolean dozing, boolean animate) {
if (mDozing == dozing) return;
mDozing = dozing;
if (mDozing) {
+ mDozingAborted = false;
abortAnimations();
mScrimController.setDozeBehindAlpha(1f);
mScrimController.setDozeInFrontAlpha(mDozeParameters.getAlwaysOn() ? 0f : 1f);
- mNotificationPanelView.setDark(true);
} else {
cancelPulsing();
if (animate) {
@@ -85,8 +82,6 @@
mScrimController.setDozeBehindAlpha(0f);
mScrimController.setDozeInFrontAlpha(0f);
}
- // TODO: animate
- mNotificationPanelView.setDark(false);
}
}
@@ -116,10 +111,19 @@
cancelPulsing();
if (mDozing) {
mScrimController.setDozeBehindAlpha(1f);
- mScrimController.setDozeInFrontAlpha(1f);
+ mScrimController.setDozeInFrontAlpha(
+ mDozeParameters.getAlwaysOn() && !mDozingAborted ? 0f : 1f);
}
}
+ /**
+ * Aborts dozing immediately.
+ */
+ public void abortDoze() {
+ mDozingAborted = true;
+ abortPulsing();
+ }
+
public void onScreenTurnedOn() {
if (isPulsing()) {
final boolean pickupOrDoubleTap = mPulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP
@@ -139,12 +143,17 @@
return mDozing;
}
+ public void extendPulse() {
+ mHandler.removeCallbacks(mPulseOut);
+ }
+
private void cancelPulsing() {
if (DEBUG) Log.d(TAG, "Cancel pulsing");
if (mPulseCallback != null) {
mHandler.removeCallbacks(mPulseIn);
mHandler.removeCallbacks(mPulseOut);
+ mHandler.removeCallbacks(mPulseOutExtended);
pulseFinished();
}
}
@@ -271,12 +280,23 @@
if (DEBUG) Log.d(TAG, "Pulse in finished, mDozing=" + mDozing);
if (!mDozing) return;
mHandler.postDelayed(mPulseOut, mDozeParameters.getPulseVisibleDuration());
+ mHandler.postDelayed(mPulseOutExtended,
+ mDozeParameters.getPulseVisibleDurationExtended());
+ }
+ };
+
+ private final Runnable mPulseOutExtended = new Runnable() {
+ @Override
+ public void run() {
+ mHandler.removeCallbacks(mPulseOut);
+ mPulseOut.run();
}
};
private final Runnable mPulseOut = new Runnable() {
@Override
public void run() {
+ mHandler.removeCallbacks(mPulseOutExtended);
if (DEBUG) Log.d(TAG, "Pulse out, mDozing=" + mDozing);
if (!mDozing) return;
startScrimAnimation(true /* inFront */, mDozeParameters.getAlwaysOn() ? 0 : 1,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
index 2bb3cbc..9206914 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -221,7 +221,7 @@
case MODE_WAKE_AND_UNLOCK:
Trace.beginSection("MODE_WAKE_AND_UNLOCK");
mStatusBarWindowManager.setStatusBarFocusable(false);
- mDozeScrimController.abortPulsing();
+ mDozeScrimController.abortDoze();
mKeyguardViewMediator.onWakeAndUnlocking();
mScrimController.setWakeAndUnlocking();
if (mStatusBar.getNavigationBarView() != null) {
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 d3cb6a4a8..f0d38b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1114,14 +1114,11 @@
}
mHeadsUpManager.addListener(mScrimController);
mStackScroller.setScrimController(mScrimController);
- mDozeScrimController = new DozeScrimController(mScrimController, context, mStackScroller,
- mNotificationPanel);
+ mDozeScrimController = new DozeScrimController(mScrimController, context);
// Other icons
mVolumeComponent = getComponent(VolumeComponent.class);
- initEmergencyCryptkeeperText();
-
mKeyguardBottomArea.setStatusBar(this);
mKeyguardBottomArea.setUserSetupComplete(mUserSetup);
if (UserManager.get(mContext).isUserSwitcherEnabled()) {
@@ -1231,24 +1228,6 @@
});
}
- private void initEmergencyCryptkeeperText() {
- View emergencyViewStub = mStatusBarWindow.findViewById(R.id.emergency_cryptkeeper_text);
- if (mNetworkController.hasEmergencyCryptKeeperText()) {
- if (emergencyViewStub != null) {
- ((ViewStub) emergencyViewStub).inflate();
- }
- mNetworkController.addCallback(new NetworkController.SignalCallback() {
- @Override
- public void setIsAirplaneMode(NetworkController.IconState icon) {
- recomputeDisableFlags(true /* animate */);
- }
- });
- } else if (emergencyViewStub != null) {
- ViewGroup parent = (ViewGroup) emergencyViewStub.getParent();
- parent.removeView(emergencyViewStub);
- }
- }
-
/**
* Returns the {@link android.view.View.OnTouchListener} that will be invoked when the
* background window of the status bar is clicked.
@@ -4332,6 +4311,7 @@
mStackScroller.setDark(mDozing, animate, mWakeUpTouchLocation);
mScrimController.setDozing(mDozing);
mKeyguardIndicationController.setDozing(mDozing);
+ mNotificationPanel.setDark(mDozing);
// Immediately abort the dozing from the doze scrim controller in case of wake-and-unlock
// for pulsing so the Keyguard fade-out animation scrim can take over.
@@ -4958,6 +4938,7 @@
mDozing = mDozingRequested && mState == StatusBarState.KEYGUARD
|| mFingerprintUnlockController.getMode()
== FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
+ mStatusBarWindowManager.setDozing(mDozing);
updateDozingState();
Trace.endSection();
}
@@ -5065,6 +5046,16 @@
StatusBar.this.startPendingIntentDismissingKeyguard(intent);
}
+ @Override
+ public void abortPulsing() {
+ mDozeScrimController.abortPulsing();
+ }
+
+ @Override
+ public void extendPulse() {
+ mDozeScrimController.extendPulse();
+ }
+
}
// Begin Extra BaseStatusBar methods.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index deb0070..0326e40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -118,7 +118,7 @@
mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
}
- if (state.keyguardShowing && !state.backdropShowing) {
+ if (state.keyguardShowing && !state.backdropShowing && !state.dozing) {
mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
} else {
mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
@@ -357,6 +357,11 @@
apply(mCurrentState);
}
+ public void setDozing(boolean dozing) {
+ mCurrentState.dozing = dozing;
+ apply(mCurrentState);
+ }
+
public void setBarHeight(int barHeight) {
mBarHeight = barHeight;
apply(mCurrentState);
@@ -404,6 +409,7 @@
boolean remoteInputActive;
boolean forcePluginOpen;
+ boolean dozing;
private boolean isKeyguardShowingAndNotOccluded() {
return keyguardShowing && !keyguardOccluded;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 1848d4e..1a09d75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -255,6 +255,9 @@
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
mStackScrollLayout.closeControlsIfOutsideTouch(ev);
}
+ if (mService.isDozing()) {
+ mService.mDozeScrimController.extendPulse();
+ }
return super.dispatchTouchEvent(ev);
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 63bf373..57ef6d0 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -48,6 +48,7 @@
import android.provider.Settings;
import android.service.autofill.AutofillService;
import android.service.autofill.AutofillServiceInfo;
+import android.service.autofill.FillRequest;
import android.service.autofill.IAutoFillService;
import android.text.TextUtils;
import android.util.LocalLog;
@@ -169,7 +170,8 @@
structure.sanitizeForParceling(true);
// TODO(b/33197203): Need to pipe the bundle
- session.mRemoteFillService.onFillRequest(structure, null, session.mFlags);
+ FillRequest request = new FillRequest(structure, null, session.mFlags);
+ session.mRemoteFillService.onFillRequest(request);
}
};
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index dd520ac..3badcfc 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -20,12 +20,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.assist.AssistStructure;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
-import android.os.Bundle;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
import android.os.ICancellationSignal;
@@ -33,10 +31,12 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.service.autofill.AutofillService;
+import android.service.autofill.FillRequest;
import android.service.autofill.FillResponse;
import android.service.autofill.IAutoFillService;
import android.service.autofill.IFillCallback;
import android.service.autofill.ISaveCallback;
+import android.service.autofill.SaveRequest;
import android.text.format.DateUtils;
import android.util.Slog;
@@ -88,7 +88,7 @@
public interface FillServiceCallbacks {
void onFillRequestSuccess(@Nullable FillResponse response,
- @NonNull String servicePackageName);
+ @NonNull String servicePackageName, int requestId);
void onFillRequestFailure(@Nullable CharSequence message,
@NonNull String servicePackageName);
void onSaveRequestSuccess(@NonNull String servicePackageName);
@@ -134,17 +134,16 @@
mCallbacks.onServiceDied(this);
}
- public void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle extras,
- int flags) {
+ public void onFillRequest(@NonNull FillRequest request) {
cancelScheduledUnbind();
- final PendingFillRequest request = new PendingFillRequest(structure, extras, this, flags);
- mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, request).sendToTarget();
+ final PendingFillRequest pendingRequest = new PendingFillRequest(request, this);
+ mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, pendingRequest).sendToTarget();
}
- public void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle extras) {
+ public void onSaveRequest(@NonNull SaveRequest request) {
cancelScheduledUnbind();
- final PendingSaveRequest request = new PendingSaveRequest(structure, extras, this);
- mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, request).sendToTarget();
+ final PendingSaveRequest pendingRequest = new PendingSaveRequest(request, this);
+ mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, pendingRequest).sendToTarget();
}
// Note: we are dumping without a lock held so this is a bit racy but
@@ -253,10 +252,11 @@
}
private void dispatchOnFillRequestSuccess(PendingRequest pendingRequest,
- FillResponse response) {
+ FillResponse response, int requestId) {
mHandler.getHandler().post(() -> {
if (handleResponseCallbackCommon(pendingRequest)) {
- mCallbacks.onFillRequestSuccess(response, mComponentName.getPackageName());
+ mCallbacks.onFillRequestSuccess(response, mComponentName.getPackageName(),
+ requestId);
}
});
}
@@ -392,18 +392,13 @@
private static final class PendingFillRequest extends PendingRequest {
private final Object mLock = new Object();
private final WeakReference<RemoteFillService> mWeakService;
- private final AssistStructure mStructure;
- private final Bundle mExtras;
+ private final FillRequest mRequest;
private final IFillCallback mCallback;
private ICancellationSignal mCancellation;
private boolean mCancelled;
- private int mFlags;
- public PendingFillRequest(AssistStructure structure,
- Bundle extras, RemoteFillService service, int flags) {
- mStructure = structure;
- mExtras = extras;
- mFlags = flags;
+ public PendingFillRequest(FillRequest request, RemoteFillService service) {
+ mRequest = request;
mWeakService = new WeakReference<>(service);
mCallback = new IFillCallback.Stub() {
@Override
@@ -425,11 +420,11 @@
}
@Override
- public void onSuccess(FillResponse response) {
+ public void onSuccess(FillResponse response, int requestId) {
RemoteFillService remoteService = mWeakService.get();
if (remoteService != null) {
remoteService.dispatchOnFillRequestSuccess(
- PendingFillRequest.this, response);
+ PendingFillRequest.this, response, requestId);
}
}
@@ -449,8 +444,7 @@
RemoteFillService remoteService = mWeakService.get();
if (remoteService != null) {
try {
- remoteService.mAutoFillService.onFillRequest(mStructure,
- mExtras, mCallback, mFlags);
+ remoteService.mAutoFillService.onFillRequest(mRequest, mCallback);
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Error calling on fill request", e);
cancel();
@@ -481,14 +475,12 @@
private static final class PendingSaveRequest extends PendingRequest {
private final WeakReference<RemoteFillService> mWeakService;
- private final AssistStructure mStructure;
- private final Bundle mExtras;
+ private final SaveRequest mRequest;
private final ISaveCallback mCallback;
- public PendingSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle extras,
+ public PendingSaveRequest(@NonNull SaveRequest request,
@NonNull RemoteFillService service) {
- mStructure = structure;
- mExtras = extras;
+ mRequest = request;
mWeakService = new WeakReference<>(service);
mCallback = new ISaveCallback.Stub() {
@Override
@@ -516,7 +508,7 @@
final RemoteFillService service = mWeakService.get();
if (service != null) {
try {
- service.mAutoFillService.onSaveRequest(mStructure, mExtras, mCallback);
+ service.mAutoFillService.onSaveRequest(mRequest, mCallback);
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Error calling on save request", e);
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 1a31161..5feb81d 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -44,11 +44,15 @@
import android.os.RemoteException;
import android.service.autofill.AutofillService;
import android.service.autofill.Dataset;
+import android.service.autofill.FillContext;
+import android.service.autofill.FillRequest;
import android.service.autofill.FillResponse;
import android.service.autofill.SaveInfo;
+import android.service.autofill.SaveRequest;
import android.util.ArrayMap;
import android.util.DebugUtils;
import android.util.Slog;
+import android.util.SparseArray;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
@@ -125,7 +129,7 @@
RemoteFillService mRemoteFillService;
@GuardedBy("mLock")
- private ArrayList<FillResponse> mResponses;
+ private SparseArray<FillResponse> mResponses;
/**
* Response that requires a service authentitcation request.
@@ -156,7 +160,7 @@
* and used on subsequent {@code onFillRequest()} and {@code onSaveRequest()} calls.
*/
@GuardedBy("mLock")
- private Bundle mExtras;
+ private Bundle mClientState;
/**
* Flags used to start the session.
@@ -222,7 +226,7 @@
// FillServiceCallbacks
@Override
public void onFillRequestSuccess(@Nullable FillResponse response,
- @NonNull String servicePackageName) {
+ @NonNull String servicePackageName, int requestId) {
if (response == null) {
if ((mFlags & FLAG_MANUAL_REQUEST) != 0) {
getUiForShowing().showError(R.string.autofill_error_cannot_autofill);
@@ -243,7 +247,7 @@
// TODO(b/33197203 , b/35707731): make sure it's ignored if there is one already
mResponseWaitingAuth = response;
}
- processResponseLocked(response);
+ processResponseLocked(response, requestId);
}
final LogMaker log = (new LogMaker(MetricsEvent.AUTOFILL_REQUEST))
@@ -394,12 +398,18 @@
AutofillManager.EXTRA_AUTHENTICATION_RESULT);
if (result instanceof FillResponse) {
mMetricsLogger.action(MetricsEvent.AUTOFILL_AUTHENTICATED, mPackageName);
+ final int requestIndex = mResponses.indexOfValue(mResponseWaitingAuth);
mResponseWaitingAuth = null;
- processResponseLocked((FillResponse) result);
+ if (requestIndex >= 0) {
+ final int requestId = mResponses.keyAt(requestIndex);
+ processResponseLocked((FillResponse) result, requestId);
+ } else {
+ Slog.e(TAG, "Error cannot find id for auth response");
+ }
} else if (result instanceof Dataset) {
final Dataset dataset = (Dataset) result;
for (int i = 0; i < mResponses.size(); i++) {
- final FillResponse response = mResponses.get(i);
+ final FillResponse response = mResponses.valueAt(i);
final int index = response.getDatasets().indexOf(mDatasetWaitingAuth);
if (index >= 0) {
response.getDatasets().set(index, dataset);
@@ -440,12 +450,18 @@
return true;
}
- final FillResponse response = mResponses.get(mResponses.size() - 1);
+ final int lastResponseIdx = getLastResponseIndex();
+ if (lastResponseIdx < 0) {
+ Slog.d(TAG, "showSaveLocked(): mResponses=" + mResponses
+ + ", mViewStates=" + mViewStates);
+ return true;
+ }
+ final FillResponse response = mResponses.valueAt(lastResponseIdx);
final SaveInfo saveInfo = response.getSaveInfo();
if (DEBUG) {
- Slog.d(TAG,
- "showSaveLocked(): mResponses=" + mResponses + ", mViewStates=" + mViewStates);
+ Slog.d(TAG, "showSaveLocked(): mResponses=" + mResponses
+ + ", mViewStates=" + mViewStates);
}
/*
@@ -572,7 +588,15 @@
mStructure.dump();
}
- mRemoteFillService.onSaveRequest(mStructure, mExtras);
+ // TODO(b/33197203): Implement partitioning properly
+ final int lastResponseIdx = getLastResponseIndex();
+ final int requestId = mResponses.keyAt(lastResponseIdx);
+ final FillContext fillContext = new FillContext(requestId, mStructure);
+ final ArrayList fillContexts = new ArrayList(1);
+ fillContexts.add(fillContext);
+
+ final SaveRequest saveRequest = new SaveRequest(fillContexts, mClientState);
+ mRemoteFillService.onSaveRequest(saveRequest);
}
void updateLocked(AutofillId id, Rect virtualBounds, AutofillValue value, int flags) {
@@ -686,7 +710,9 @@
overlay.focused = id.equals(viewState.id);
node.setAutofillOverlay(overlay);
}
- mRemoteFillService.onFillRequest(mStructure, mExtras, 0);
+
+ FillRequest request = new FillRequest(mStructure, mClientState, 0);
+ mRemoteFillService.onFillRequest(request);
return newViewState;
}
@@ -723,17 +749,17 @@
}
}
- private void processResponseLocked(FillResponse response) {
+ private void processResponseLocked(FillResponse response, int requestId) {
if (DEBUG) {
Slog.d(TAG, "processResponseLocked(mCurrentViewId=" + mCurrentViewId + "):" + response);
}
if (mResponses == null) {
- mResponses = new ArrayList<>(4);
+ mResponses = new SparseArray<>(4);
}
- mResponses.add(response);
+ mResponses.put(requestId, response);
if (response != null) {
- mExtras = response.getExtras();
+ mClientState = response.getClientState();
}
setViewStatesLocked(response, ViewState.STATE_FILLABLE);
@@ -884,7 +910,8 @@
}
}
pw.print(prefix); pw.print("mHasCallback: "); pw.println(mHasCallback);
- pw.print(prefix); pw.print("mExtras: "); pw.println(Helper.bundleToString(mExtras));
+ pw.print(prefix); pw.print("mClientState: "); pw.println(
+ Helper.bundleToString(mClientState));
mRemoteFillService.dump(prefix, pw);
}
@@ -961,4 +988,20 @@
destroyLocked();
mService.removeSessionLocked(id);
}
+
+ private int getLastResponseIndex() {
+ // The response ids are monotonically increasing so
+ // we just find the largest id which is the last. We
+ // do not rely on the internal ordering in sparse
+ // array to avoid - wow this stopped working!?
+ int lastResponseIdx = -1;
+ int lastResponseId = -1;
+ final int responseCount = mResponses.size();
+ for (int i = 0; i < responseCount; i++) {
+ if (mResponses.keyAt(i) > lastResponseId) {
+ lastResponseIdx = i;
+ }
+ }
+ return lastResponseIdx;
+ }
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index 4449da9..ab6a3a7 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -161,7 +161,8 @@
log.setType(MetricsProto.MetricsEvent.TYPE_DETAIL);
hideFillUiUiThread();
if (mCallback != null) {
- mCallback.authenticate(response.getAuthentication(), response.getExtras());
+ mCallback.authenticate(response.getAuthentication(),
+ response.getClientState());
}
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 50c0a12..d5adf48 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -55,6 +55,7 @@
import android.net.Network;
import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
+import android.net.MatchAllNetworkSpecifier;
import android.net.NetworkConfig;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
@@ -89,7 +90,6 @@
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.SystemClock;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -203,6 +203,8 @@
// See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS
private final int mReleasePendingIntentDelayMs;
+ private MockableSystemProperties mSystemProperties;
+
private Tethering mTethering;
private final PermissionMonitor mPermissionMonitor;
@@ -675,6 +677,8 @@
IpConnectivityLog logger) {
if (DBG) log("ConnectivityService starting up");
+ mSystemProperties = getSystemProperties();
+
mMetricsLog = logger;
mDefaultRequest = createInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST);
NetworkRequestInfo defaultNRI = new NetworkRequestInfo(null, mDefaultRequest, new Binder());
@@ -692,7 +696,7 @@
mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);
- mLingerDelayMs = SystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
+ mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
mContext = checkNotNull(context, "missing Context");
mNetd = checkNotNull(netManager, "missing INetworkManagementService");
@@ -722,7 +726,7 @@
mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
// TODO: What is the "correct" way to do determine if this is a wifi only device?
- boolean wifiOnly = SystemProperties.getBoolean("ro.radio.noril", false);
+ boolean wifiOnly = mSystemProperties.getBoolean("ro.radio.noril", false);
log("wifiOnly=" + wifiOnly);
String[] naStrings = context.getResources().getStringArray(
com.android.internal.R.array.networkAttributes);
@@ -775,8 +779,8 @@
}
}
- mTestMode = SystemProperties.get("cm.test.mode").equals("true")
- && SystemProperties.get("ro.build.type").equals("eng");
+ mTestMode = mSystemProperties.get("cm.test.mode").equals("true")
+ && mSystemProperties.get("ro.build.type").equals("eng");
mTethering = new Tethering(mContext, mNetd, statsService, mPolicyManager,
IoThread.get().getLooper(), new MockableSystemProperties());
@@ -1732,8 +1736,8 @@
// Overridden for testing purposes to avoid writing to SystemProperties.
@VisibleForTesting
- protected int getDefaultTcpRwnd() {
- return SystemProperties.getInt(DEFAULT_TCP_RWND_KEY, 0);
+ protected MockableSystemProperties getSystemProperties() {
+ return new MockableSystemProperties();
}
private void updateTcpBufferSizes(NetworkAgentInfo nai) {
@@ -1771,10 +1775,11 @@
}
Integer rwndValue = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.TCP_DEFAULT_INIT_RWND, getDefaultTcpRwnd());
+ Settings.Global.TCP_DEFAULT_INIT_RWND,
+ mSystemProperties.getInt("net.tcp.default_init_rwnd", 0));
final String sysctlKey = "sys.sysctl.tcp_def_init_rwnd";
if (rwndValue != 0) {
- SystemProperties.set(sysctlKey, rwndValue.toString());
+ mSystemProperties.set(sysctlKey, rwndValue.toString());
}
}
@@ -1798,7 +1803,7 @@
@Override
public int getRestoreDefaultNetworkDelay(int networkType) {
- String restoreDefaultNetworkDelayStr = SystemProperties.get(
+ String restoreDefaultNetworkDelayStr = mSystemProperties.get(
NETWORK_RESTORE_DELAY_PROP_NAME);
if(restoreDefaultNetworkDelayStr != null &&
restoreDefaultNetworkDelayStr.length() != 0) {
@@ -2965,7 +2970,7 @@
@Override
public boolean isTetheringSupported() {
enforceTetherAccessPermission();
- int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
+ int defaultVal = (mSystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
boolean tetherEnabledInSettings = (Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.TETHER_SUPPORTED, defaultVal) != 0)
&& !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
@@ -4044,11 +4049,8 @@
throw new IllegalArgumentException("Bad timeout specified");
}
- if (NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER
- .equals(networkCapabilities.getNetworkSpecifier())) {
- throw new IllegalArgumentException("Invalid network specifier - must not be '"
- + NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER + "'");
- }
+ MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
+ networkCapabilities.getNetworkSpecifier());
NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
nextNetworkRequestId(), type);
@@ -4117,6 +4119,9 @@
enforceMeteredApnPolicy(networkCapabilities);
ensureRequestableCapabilities(networkCapabilities);
+ MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
+ networkCapabilities.getNetworkSpecifier());
+
NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
nextNetworkRequestId(), NetworkRequest.Type.REQUEST);
NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation);
@@ -4178,6 +4183,9 @@
nc.addCapability(NET_CAPABILITY_FOREGROUND);
}
+ MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
+ networkCapabilities.getNetworkSpecifier());
+
NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
NetworkRequest.Type.LISTEN);
NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder);
@@ -4195,6 +4203,9 @@
enforceAccessPermission();
}
+ MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
+ networkCapabilities.getNetworkSpecifier());
+
NetworkRequest networkRequest = new NetworkRequest(
new NetworkCapabilities(networkCapabilities), TYPE_NONE, nextNetworkRequestId(),
NetworkRequest.Type.LISTEN);
@@ -4466,17 +4477,24 @@
int last = 0;
for (InetAddress dns : dnses) {
++last;
- String key = "net.dns" + last;
- String value = dns.getHostAddress();
- SystemProperties.set(key, value);
+ setNetDnsProperty(last, dns.getHostAddress());
}
for (int i = last + 1; i <= mNumDnsEntries; ++i) {
- String key = "net.dns" + i;
- SystemProperties.set(key, "");
+ setNetDnsProperty(i, "");
}
mNumDnsEntries = last;
}
+ private void setNetDnsProperty(int which, String value) {
+ final String key = "net.dns" + which;
+ // Log and forget errors setting unsupported properties.
+ try {
+ mSystemProperties.set(key, value);
+ } catch (Exception e) {
+ Log.e(TAG, "Error setting unsupported net.dns property: ", e);
+ }
+ }
+
private String getNetworkPermission(NetworkCapabilities nc) {
// TODO: make these permission strings AIDL constants instead.
if (!nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2be5313..6b0a73b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -23885,6 +23885,15 @@
}
}
+ @Override
+ public long getActivityStartInitiatedTime(IBinder token) {
+ final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+ if (r != null) {
+ return r.mStartInitiatedTimeMs;
+ }
+ return 0;
+ }
+
void updateApplicationInfoLocked(@NonNull List<String> packagesToUpdate, int userId) {
final PackageManagerInternal packageManager = getPackageManagerInternalLocked();
final boolean updateFrameworkRes = packagesToUpdate.contains("android");
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 276b267..17c7dde 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -341,6 +341,12 @@
private final Rect mBounds = new Rect();
/**
+ * Denotes the timestamp at which this activity start was last initiated in the
+ * {@link SystemClock#uptimeMillis()} time base.
+ */
+ long mStartInitiatedTimeMs;
+
+ /**
* Temp configs used in {@link #ensureActivityConfigurationLocked(int, boolean)}
*/
private final Configuration mTmpConfig1 = new Configuration();
@@ -498,6 +504,8 @@
pw.print(" forceNewConfig="); pw.println(forceNewConfig);
pw.print(prefix); pw.print("mActivityType=");
pw.println(activityTypeToString(mActivityType));
+ pw.print(prefix); pw.print("mStartInitiatedTimeMs=");
+ TimeUtils.formatDuration(mStartInitiatedTimeMs, now, pw);
if (requestedVrComponent != null) {
pw.print(prefix);
pw.print("requestedVrComponent=");
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 56594d3..8f1c203 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -244,6 +244,7 @@
ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
TaskRecord inTask) {
+ final long activityStartTime = SystemClock.uptimeMillis();
int err = ActivityManager.START_SUCCESS;
ProcessRecord callerApp = null;
@@ -478,6 +479,7 @@
callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
mSupervisor, container, options, sourceRecord);
+ r.mStartInitiatedTimeMs = activityStartTime;
if (outActivity != null) {
outActivity[0] = r;
}
@@ -1029,6 +1031,7 @@
// so make sure the task now has the identity of the new intent.
top.getTask().setIntent(mStartActivity);
}
+ top.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs;
ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
mStartActivity.launchedFromPackage);
@@ -1052,6 +1055,7 @@
setTaskFromIntentActivity(reusedActivity);
if (!mAddingToTask && mReuseTask == null) {
+ reusedActivity.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs;
// We didn't do anything... but it was needed (a.k.a., client don't use that
// intent!) And for paranoia, make sure we have correctly resumed the top activity.
resumeTargetStackIfNeeded();
@@ -1084,6 +1088,7 @@
|| mLaunchSingleTop || mLaunchSingleTask);
if (dontStart) {
ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
+ top.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs;
// For paranoia, make sure we have correctly resumed the top activity.
topStack.mLastPausedActivity = null;
if (mDoResume) {
@@ -1664,6 +1669,7 @@
// desires.
if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
&& intentActivity.realActivity.equals(mStartActivity.realActivity)) {
+ intentActivity.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs;
ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
intentActivity.getTask());
if (intentActivity.frontOfTask) {
diff --git a/services/core/java/com/android/server/connectivity/MockableSystemProperties.java b/services/core/java/com/android/server/connectivity/MockableSystemProperties.java
index 4f68652..77b86d8 100644
--- a/services/core/java/com/android/server/connectivity/MockableSystemProperties.java
+++ b/services/core/java/com/android/server/connectivity/MockableSystemProperties.java
@@ -19,7 +19,20 @@
import android.os.SystemProperties;
public class MockableSystemProperties {
+
+ public String get(String key) {
+ return SystemProperties.get(key);
+ }
+
+ public int getInt(String key, int def) {
+ return SystemProperties.getInt(key, def);
+ }
+
public boolean getBoolean(String key, boolean def) {
return SystemProperties.getBoolean(key, def);
}
+
+ public void set(String key, String value) {
+ SystemProperties.set(key, value);
+ }
}
diff --git a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
index 552f0d1..fe49813 100644
--- a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
+++ b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
@@ -36,6 +36,7 @@
public abstract boolean handleFailedAttempt();
public abstract void resetFailedAttempts();
+ private boolean mAlreadyCancelled;
public AuthenticationClient(Context context, long halDeviceId, IBinder token,
IFingerprintServiceReceiver receiver, int targetUserId, int groupId, long opId,
@@ -129,6 +130,10 @@
@Override
public int stop(boolean initiatedByClient) {
+ if (mAlreadyCancelled) {
+ Slog.w(TAG, "stopAuthentication: already cancelled!");
+ return 0;
+ }
IBiometricsFingerprint daemon = getFingerprintDaemon();
if (daemon == null) {
Slog.w(TAG, "stopAuthentication: no fingerprint HAL!");
@@ -145,6 +150,7 @@
Slog.e(TAG, "stopAuthentication failed", e);
return ERROR_ESRCH;
}
+ mAlreadyCancelled = true;
return 0; // success
}
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index b0d8adc..2f82915 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -23,6 +23,7 @@
import android.os.UserHandle;
import android.util.IntArray;
import android.util.Log;
+import android.util.SparseArray;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -38,7 +39,7 @@
private static final String TAG = "MediaSessionStack";
/**
- * Listens the change in the media button session.
+ * Listen the change in the media button session.
*/
interface OnMediaButtonSessionChangedListener {
/**
@@ -85,7 +86,12 @@
private MediaSessionRecord mCachedDefault;
private MediaSessionRecord mCachedVolumeDefault;
- private ArrayList<MediaSessionRecord> mCachedActiveList;
+
+ /**
+ * Cache the result of the {@link #getActiveSessions} per user.
+ */
+ private final SparseArray<ArrayList<MediaSessionRecord>> mCachedActiveLists =
+ new SparseArray<>();
MediaSessionStack(AudioPlaybackMonitor monitor, OnMediaButtonSessionChangedListener listener) {
mAudioPlaybackMonitor = monitor;
@@ -99,7 +105,7 @@
*/
public void addSession(MediaSessionRecord record) {
mSessions.add(record);
- clearCache();
+ clearCache(record.getUserId());
// Update the media button session.
// The added session could be the session from the package with the audio playback.
@@ -119,7 +125,7 @@
// in the media button session app.
onMediaSessionChangeInMediaButtonSessionApp();
}
- clearCache();
+ clearCache(record.getUserId());
}
/**
@@ -140,7 +146,7 @@
if (shouldUpdatePriority(oldState, newState)) {
mSessions.remove(record);
mSessions.add(0, record);
- clearCache();
+ clearCache(record.getUserId());
} else if (!MediaSession.isActiveState(newState)) {
// Just clear the volume cache when a state goes inactive
mCachedVolumeDefault = null;
@@ -163,7 +169,7 @@
public void onSessionStateChange(MediaSessionRecord record) {
// For now just clear the cache. Eventually we'll selectively clear
// depending on what changed.
- clearCache();
+ clearCache(record.getUserId());
}
/**
@@ -245,14 +251,17 @@
* Get the current priority sorted list of active sessions. The most
* important session is at index 0 and the least important at size - 1.
*
- * @param userId The user to check.
+ * @param userId The user to check. It can be {@link UserHandle#USER_ALL} to get all sessions
+ * for all users in this {@link MediaSessionStack}.
* @return All the active sessions in priority order.
*/
public ArrayList<MediaSessionRecord> getActiveSessions(int userId) {
- if (mCachedActiveList == null) {
- mCachedActiveList = getPriorityList(true, userId);
+ ArrayList<MediaSessionRecord> cachedActiveList = mCachedActiveLists.get(userId);
+ if (cachedActiveList == null) {
+ cachedActiveList = getPriorityList(true, userId);
+ mCachedActiveLists.put(userId, cachedActiveList);
}
- return mCachedActiveList;
+ return cachedActiveList;
}
/**
@@ -382,9 +391,12 @@
return false;
}
- private void clearCache() {
+ private void clearCache(int userId) {
mCachedDefault = null;
mCachedVolumeDefault = null;
- mCachedActiveList = null;
+ mCachedActiveLists.remove(userId);
+ // mCachedActiveLists may also include the list of sessions for UserHandle.USER_ALL,
+ // so they also need to be cleared.
+ mCachedActiveLists.remove(UserHandle.USER_ALL);
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index b7d3173..b48fd5c 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -172,7 +172,7 @@
final boolean useDefaultSound = (n.defaults & Notification.DEFAULT_SOUND) != 0;
if (useDefaultSound) {
sound = Settings.System.DEFAULT_NOTIFICATION_URI;
- } else if (n.sound != null) {
+ } else {
sound = n.sound;
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 650d2f6..9040fcf 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -23636,4 +23636,10 @@
public ComponentName getInstantAppResolverSettingsComponent() {
return mInstantAppResolverSettingsComponent;
}
+
+ @Override
+ public ComponentName getInstantAppInstallerComponent() {
+ return mInstantAppInstallerActivity == null
+ ? null : mInstantAppInstallerActivity.getComponentName();
+ }
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 058fdae..1823610 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -125,6 +125,7 @@
import android.view.SurfaceControl;
import android.view.WindowManagerPolicy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ToBooleanFunction;
import com.android.internal.view.IInputMethodClient;
@@ -1396,6 +1397,22 @@
return null;
}
+ @VisibleForTesting
+ int getStackCount() {
+ return mTaskStackContainers.size();
+ }
+
+ @VisibleForTesting
+ int getStaskPosById(int stackId) {
+ for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+ final TaskStack stack = mTaskStackContainers.get(i);
+ if (stack.mStackId == stackId) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
@Override
void onConfigurationChanged(Configuration newParentConfig) {
super.onConfigurationChanged(newParentConfig);
@@ -3274,8 +3291,9 @@
: requestedPosition >= topChildPosition;
int targetPosition = requestedPosition;
- if (toTop && isStackVisible(PINNED_STACK_ID) && stack.mStackId != PINNED_STACK_ID) {
- // The pinned stack is always the top most stack (always-on-top) when it is visible.
+ if (toTop && stack.mStackId != PINNED_STACK_ID
+ && getStackById(PINNED_STACK_ID) != null) {
+ // The pinned stack is always the top most stack (always-on-top) when it is present.
TaskStack topStack = mChildren.get(topChildPosition);
if (topStack.mStackId != PINNED_STACK_ID) {
throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
diff --git a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
index 6b3271f..122a954 100644
--- a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
+++ b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
@@ -20,10 +20,12 @@
import static com.android.internal.util.CollectionUtils.size;
import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.internal.util.Preconditions.checkState;
import android.Manifest;
import android.annotation.CheckResult;
import android.annotation.Nullable;
+import android.app.PendingIntent;
import android.companion.AssociationRequest;
import android.companion.CompanionDeviceManager;
import android.companion.ICompanionDeviceDiscoveryService;
@@ -47,13 +49,18 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.provider.Settings;
+import android.provider.SettingsStringUtil.ComponentNameSet;
+import android.text.BidiFormatter;
import android.util.AtomicFile;
import android.util.ExceptionUtils;
+import android.util.Log;
import android.util.Slog;
import android.util.Xml;
import com.android.internal.app.IAppOpsService;
import com.android.internal.content.PackageMonitor;
+import com.android.internal.notification.NotificationAccessConfirmationActivityContract;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
import com.android.server.FgThread;
@@ -80,6 +87,7 @@
//TODO schedule stopScan on activity destroy(except if configuration change)
//TODO on associate called again after configuration change -> replace old callback with new
//TODO avoid leaking calling activity in IFindDeviceCallback (see PrintManager#print for example)
+//TODO check user-feature present in manifest on API calls
/** @hide */
public class CompanionDeviceManagerService extends SystemService implements Binder.DeathRecipient {
@@ -217,6 +225,7 @@
a -> a.deviceAddress);
}
+ //TODO also revoke notification access
@Override
public void disassociate(String deviceMacAddress, String callingPackage)
throws RemoteException {
@@ -237,11 +246,49 @@
checkArgument(getCallingUserId() == userId,
"Must be called by either same user or system");
-
mAppOpsManager.checkPackage(Binder.getCallingUid(), pkg);
}
+
+ @Override
+ public PendingIntent requestNotificationAccess(ComponentName component)
+ throws RemoteException {
+ String callingPackage = component.getPackageName();
+ checkCanCallNotificationApi(callingPackage);
+ int userId = getCallingUserId();
+ String packageTitle = BidiFormatter.getInstance().unicodeWrap(
+ getPackageInfo(callingPackage, userId)
+ .applicationInfo
+ .loadSafeLabel(getContext().getPackageManager())
+ .toString());
+ long identity = Binder.clearCallingIdentity();
+ try {
+ return PendingIntent.getActivity(getContext(),
+ 0 /* request code */,
+ NotificationAccessConfirmationActivityContract.launcherIntent(
+ userId, component, packageTitle),
+ PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT
+ | PendingIntent.FLAG_CANCEL_CURRENT);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public boolean hasNotificationAccess(ComponentName component) throws RemoteException {
+ checkCanCallNotificationApi(component.getPackageName());
+ String setting = Settings.Secure.getString(getContext().getContentResolver(),
+ Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
+ return new ComponentNameSet(setting).contains(component);
+ }
+
+ private void checkCanCallNotificationApi(String callingPackage) throws RemoteException {
+ checkCallerIsSystemOr(callingPackage);
+ checkState(!ArrayUtils.isEmpty(readAllAssociations(getCallingUserId(), callingPackage)),
+ "App must have an association before calling this API");
+ }
}
+
private int getCallingUserId() {
return UserHandle.getUserId(Binder.getCallingUid());
}
@@ -291,6 +338,17 @@
return new ICompanionDeviceDiscoveryServiceCallback.Stub() {
@Override
+ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+ throws RemoteException {
+ try {
+ return super.onTransact(code, data, reply, flags);
+ } catch (Throwable e) {
+ Slog.e(LOG_TAG, "Error during IPC", e);
+ throw ExceptionUtils.propagate(e, RemoteException.class);
+ }
+ }
+
+ @Override
public void onDeviceSelected(String packageName, int userId, String deviceAddress) {
updateSpecialAccessPermissionForAssociatedPackage(packageName, userId);
recordAssociation(packageName, deviceAddress);
@@ -301,7 +359,6 @@
public void onDeviceSelectionCancel() {
cleanup();
}
-
};
}
@@ -351,8 +408,13 @@
}
private void recordAssociation(String priviledgedPackage, String deviceAddress) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "recordAssociation(priviledgedPackage = " + priviledgedPackage
+ + ", deviceAddress = " + deviceAddress + ")");
+ }
+ int userId = getCallingUserId();
updateAssociations(associations -> CollectionUtils.add(associations,
- new Association(getCallingUserId(), deviceAddress, priviledgedPackage)));
+ new Association(userId, deviceAddress, priviledgedPackage)));
}
private void updateAssociations(Function<List<Association>, List<Association>> update) {
@@ -364,7 +426,7 @@
final AtomicFile file = getStorageFileForUser(userId);
synchronized (file) {
List<Association> associations = readAllAssociations(userId);
- final ArrayList<Association> old = new ArrayList<>(associations);
+ final List<Association> old = CollectionUtils.copyOf(associations);
associations = update.apply(associations);
if (size(old) == size(associations)) return;
@@ -394,15 +456,6 @@
});
}
-
-
- //TODO Show dialog before recording notification access
-// final SettingStringHelper setting =
-// new SettingStringHelper(
-// getContext().getContentResolver(),
-// Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
-// getUserId());
-// setting.write(ColonDelimitedSet.OfStrings.add(setting.read(), priviledgedPackage));
}
private AtomicFile getStorageFileForUser(int uid) {
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
index 946044d..b2e6ef9 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
@@ -124,6 +124,9 @@
builder.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
}
+ } else {
+ channel.setSound(null, null);
+ builder.setSound(null, null);
}
if (buzzy) {
if (defaultVibration) {
@@ -206,6 +209,18 @@
}
@Test
+ public void testSound_noSound_preUpgrade() throws Exception {
+ // pre upgrade, default sound.
+ StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
+ false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+ false /* lights */, false /*defaultLights */);
+
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ assertEquals(null, record.getSound());
+ assertEquals(Notification.AUDIO_ATTRIBUTES_DEFAULT, record.getAudioAttributes());
+ }
+
+ @Test
public void testSound_default_upgradeUsesChannel() throws Exception {
channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
// post upgrade, default sound.
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index 0270bb9..837ce56 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
@@ -289,6 +290,24 @@
verifySizes(sDisplayContent, smallerWidth, smallerHeight, smallerDensity);
}
+ /**
+ * This test enforces that the pinned stack is always kept as the top stack.
+ */
+ @Test
+ public void testPinnedStackLocation() {
+ createStackControllerOnStackOnDisplay(PINNED_STACK_ID, sDisplayContent);
+ final int initialStackCount = sDisplayContent.getStackCount();
+ // Ensure that the pinned stack was placed at the end
+ assertEquals(initialStackCount - 1, sDisplayContent.getStaskPosById(PINNED_STACK_ID));
+ // By default, this should try to create a new stack on top
+ createTaskStackOnDisplay(sDisplayContent);
+ final int afterStackCount = sDisplayContent.getStackCount();
+ // Make sure the stack count has increased
+ assertEquals(initialStackCount + 1, afterStackCount);
+ // Ensure that the pinned stack is still on top
+ assertEquals(afterStackCount - 1, sDisplayContent.getStaskPosById(PINNED_STACK_ID));
+ }
+
private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
int expectedBaseHeight, int expectedBaseDensity) {
assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 960a2d9..20392e7 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -1126,4 +1126,12 @@
public ComponentName getInstantAppResolverSettingsComponent() {
throw new UnsupportedOperationException();
}
+
+ /**
+ * @hide
+ */
+ @Override
+ public ComponentName getInstantAppInstallerComponent() {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index c562cb9..6140a896 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -23,7 +23,12 @@
import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.NetworkCapabilities.*;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -33,6 +38,7 @@
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.ConnectivityManager.PacketKeepalive;
@@ -42,6 +48,7 @@
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
+import android.net.MatchAllNetworkSpecifier;
import android.net.Network;
import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
@@ -51,7 +58,9 @@
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkMisc;
import android.net.NetworkRequest;
+import android.net.NetworkSpecifier;
import android.net.RouteInfo;
+import android.net.StringNetworkSpecifier;
import android.net.metrics.IpConnectivityLog;
import android.net.util.MultinetworkPolicyTracker;
import android.os.ConditionVariable;
@@ -64,24 +73,32 @@
import android.os.MessageQueue;
import android.os.Messenger;
import android.os.MessageQueue.IdleHandler;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.Process;
import android.os.SystemClock;
import android.provider.Settings;
import android.test.AndroidTestCase;
import android.test.mock.MockContentResolver;
import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
import android.util.Log;
import android.util.LogPrinter;
import com.android.internal.util.WakeupMessage;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.server.connectivity.MockableSystemProperties;
import com.android.server.connectivity.NetworkAgentInfo;
import com.android.server.connectivity.NetworkMonitor;
import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
import com.android.server.net.NetworkPinner;
import com.android.server.net.NetworkPolicyManagerInternal;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
@@ -134,8 +151,19 @@
private class MockContext extends BroadcastInterceptingContext {
private final MockContentResolver mContentResolver;
+ @Spy private Resources mResources;
+
MockContext(Context base) {
super(base);
+
+ mResources = spy(base.getResources());
+ when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
+ thenReturn(new String[] {
+ "wifi,1,1,1,-1,true",
+ "mobile,0,0,0,-1,true",
+ "mobile_mms,2,0,2,60000,true",
+ });
+
mContentResolver = new MockContentResolver();
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
}
@@ -151,6 +179,11 @@
public ContentResolver getContentResolver() {
return mContentResolver;
}
+
+ @Override
+ public Resources getResources() {
+ return mResources;
+ }
}
/**
@@ -319,6 +352,11 @@
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
}
+ public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
+ mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
+ mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
+ }
+
public void connectWithoutInternet() {
mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
mNetworkAgent.sendNetworkInfo(mNetworkInfo);
@@ -621,6 +659,7 @@
private class WrappedConnectivityService extends ConnectivityService {
public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
+ private MockableSystemProperties mSystemProperties;
public WrappedConnectivityService(Context context, INetworkManagementService netManager,
INetworkStatsService statsService, INetworkPolicyManager policyManager,
@@ -630,9 +669,13 @@
}
@Override
- protected int getDefaultTcpRwnd() {
- // Prevent wrapped ConnectivityService from trying to write to SystemProperties.
- return 0;
+ protected MockableSystemProperties getSystemProperties() {
+ // Minimal approach to overriding system properties: let most calls fall through to real
+ // device values, and only override ones values that are important to this test.
+ mSystemProperties = spy(new MockableSystemProperties());
+ when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
+ when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
+ return mSystemProperties;
}
@Override
@@ -805,6 +848,14 @@
return cv;
}
+ public void testNetworkTypes() {
+ // Ensure that our mocks for the networkAttributes config variable work as expected. If they
+ // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
+ // will fail. Failing here is much easier to debug.
+ assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
+ assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
+ }
+
@SmallTest
public void testLingering() throws Exception {
verifyNoNetwork();
@@ -1819,34 +1870,130 @@
captivePortalCallback.assertNoCallback();
}
- @SmallTest
- public void testInvalidNetworkSpecifier() {
- boolean execptionCalled = true;
+ private NetworkRequest.Builder newWifiRequestBuilder() {
+ return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
+ }
- try {
- NetworkRequest.Builder builder = new NetworkRequest.Builder();
- builder.setNetworkSpecifier(MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
- execptionCalled = false;
- } catch (IllegalArgumentException e) {
- // do nothing - should get here
+ @SmallTest
+ public void testNetworkSpecifier() {
+ NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
+ NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
+ NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
+ NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
+ (NetworkSpecifier) null).build();
+ NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier("foo").build();
+ NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
+ new StringNetworkSpecifier("bar")).build();
+
+ TestNetworkCallback cEmpty1 = new TestNetworkCallback();
+ TestNetworkCallback cEmpty2 = new TestNetworkCallback();
+ TestNetworkCallback cEmpty3 = new TestNetworkCallback();
+ TestNetworkCallback cEmpty4 = new TestNetworkCallback();
+ TestNetworkCallback cFoo = new TestNetworkCallback();
+ TestNetworkCallback cBar = new TestNetworkCallback();
+ TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
+ cEmpty1, cEmpty2, cEmpty3 };
+
+ mCm.registerNetworkCallback(rEmpty1, cEmpty1);
+ mCm.registerNetworkCallback(rEmpty2, cEmpty2);
+ mCm.registerNetworkCallback(rEmpty3, cEmpty3);
+ mCm.registerNetworkCallback(rEmpty4, cEmpty4);
+ mCm.registerNetworkCallback(rFoo, cFoo);
+ mCm.registerNetworkCallback(rBar, cBar);
+
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(false);
+ cEmpty1.expectAvailableCallbacks(mWiFiNetworkAgent);
+ cEmpty2.expectAvailableCallbacks(mWiFiNetworkAgent);
+ cEmpty3.expectAvailableCallbacks(mWiFiNetworkAgent);
+ cEmpty4.expectAvailableCallbacks(mWiFiNetworkAgent);
+ assertNoCallbacks(cFoo, cBar);
+
+ mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("foo"));
+ cFoo.expectAvailableCallbacks(mWiFiNetworkAgent);
+ for (TestNetworkCallback c: emptyCallbacks) {
+ c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
+ }
+ cFoo.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
+ cFoo.assertNoCallback();
+
+ mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("bar"));
+ cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ cBar.expectAvailableCallbacks(mWiFiNetworkAgent);
+ for (TestNetworkCallback c: emptyCallbacks) {
+ c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
+ }
+ cBar.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
+ cBar.assertNoCallback();
+
+ mWiFiNetworkAgent.setNetworkSpecifier(null);
+ cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ for (TestNetworkCallback c: emptyCallbacks) {
+ c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
}
- assertTrue("NetworkRequest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
- execptionCalled);
+ assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cFoo, cBar);
+ }
+
+ @SmallTest
+ public void testInvalidNetworkSpecifier() {
+ try {
+ NetworkRequest.Builder builder = new NetworkRequest.Builder();
+ builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
+ fail("NetworkRequest builder with MatchAllNetworkSpecifier");
+ } catch (IllegalArgumentException expected) {
+ // expected
+ }
try {
NetworkCapabilities networkCapabilities = new NetworkCapabilities();
networkCapabilities.addTransportType(TRANSPORT_WIFI)
- .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
+ .setNetworkSpecifier(new MatchAllNetworkSpecifier());
mService.requestNetwork(networkCapabilities, null, 0, null,
ConnectivityManager.TYPE_WIFI);
- execptionCalled = false;
- } catch (IllegalArgumentException e) {
- // do nothing - should get here
+ fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier");
+ } catch (IllegalArgumentException expected) {
+ // expected
}
- assertTrue("ConnectivityService requestNetwork with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
- execptionCalled);
+ class NonParcelableSpecifier extends NetworkSpecifier {
+ public boolean satisfiedBy(NetworkSpecifier other) { return false; }
+ };
+ class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
+ @Override public int describeContents() { return 0; }
+ @Override public void writeToParcel(Parcel p, int flags) {}
+ }
+ NetworkRequest.Builder builder;
+
+ builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
+ try {
+ builder.setNetworkSpecifier(new NonParcelableSpecifier());
+ Parcel parcelW = Parcel.obtain();
+ builder.build().writeToParcel(parcelW, 0);
+ fail("Parceling a non-parcelable specifier did not throw an exception");
+ } catch (Exception e) {
+ // expected
+ }
+
+ builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
+ builder.setNetworkSpecifier(new ParcelableSpecifier());
+ NetworkRequest nr = builder.build();
+ assertNotNull(nr);
+
+ try {
+ Parcel parcelW = Parcel.obtain();
+ nr.writeToParcel(parcelW, 0);
+ byte[] bytes = parcelW.marshall();
+ parcelW.recycle();
+
+ Parcel parcelR = Parcel.obtain();
+ parcelR.unmarshall(bytes, 0, bytes.length);
+ parcelR.setDataPosition(0);
+ NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
+ fail("Unparceling a non-framework NetworkSpecifier did not throw an exception");
+ } catch (Exception e) {
+ // expected
+ }
}
@SmallTest
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index 5a239e1..ad26bc8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -923,4 +923,9 @@
public ComponentName getInstantAppResolverSettingsComponent() {
return null;
}
+
+ @Override
+ public ComponentName getInstantAppInstallerComponent() {
+ return null;
+ }
}