Merge "Change system alert window setting proto comments"
diff --git a/api/current.txt b/api/current.txt
index 477e346..2644372 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1790,6 +1790,7 @@
field public static final int accessibilityActionSetProgress = 16908349; // 0x102003d
field public static final int accessibilityActionShowOnScreen = 16908342; // 0x1020036
field public static final int addToDictionary = 16908330; // 0x102002a
+ field public static final int autofill = 16908355; // 0x1020043
field public static final int background = 16908288; // 0x1020000
field public static final int button1 = 16908313; // 0x1020019
field public static final int button2 = 16908314; // 0x102001a
@@ -5493,7 +5494,6 @@
public final class NotificationChannel implements android.os.Parcelable {
ctor public NotificationChannel(java.lang.String, java.lang.CharSequence, int);
- ctor public NotificationChannel(java.lang.String, int, int);
ctor protected NotificationChannel(android.os.Parcel);
method public boolean canBypassDnd();
method public boolean canShowBadge();
@@ -5507,7 +5507,6 @@
method public int getLightColor();
method public int getLockscreenVisibility();
method public java.lang.CharSequence getName();
- method public int getNameResId();
method public android.net.Uri getSound();
method public long[] getVibrationPattern();
method public void setBypassDnd(boolean);
@@ -5515,6 +5514,7 @@
method public void setImportance(int);
method public void setLightColor(int);
method public void setLockscreenVisibility(int);
+ method public void setName(java.lang.CharSequence);
method public void setShowBadge(boolean);
method public void setSound(android.net.Uri, android.media.AudioAttributes);
method public void setVibrationPattern(long[]);
@@ -5527,14 +5527,12 @@
public final class NotificationChannelGroup implements android.os.Parcelable {
ctor public NotificationChannelGroup(java.lang.String, java.lang.CharSequence);
- ctor public NotificationChannelGroup(java.lang.String, int);
ctor protected NotificationChannelGroup(android.os.Parcel);
method public android.app.NotificationChannelGroup clone();
method public int describeContents();
method public java.util.List<android.app.NotificationChannel> getChannels();
method public java.lang.String getId();
method public java.lang.CharSequence getName();
- method public int getNameResId();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.NotificationChannelGroup> CREATOR;
}
@@ -21827,7 +21825,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.os.Bundle getMetrics();
+ method public android.media.MediaMetricsSet getMetrics();
method public final java.lang.String getName();
method public java.nio.ByteBuffer getOutputBuffer(int);
method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
@@ -22379,7 +22377,7 @@
method public boolean advance();
method public long getCachedDuration();
method public android.media.DrmInitData getDrmInitData();
- method public android.os.Bundle getMetrics();
+ method public android.media.MediaMetricsSet getMetrics();
method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
method public int getSampleFlags();
@@ -22634,6 +22632,69 @@
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;
@@ -22674,7 +22735,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.os.Bundle getMetrics();
+ method public android.media.MediaMetricsSet getMetrics();
method public android.media.PlaybackParams getPlaybackParams();
method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
method public android.media.SyncParams getSyncParams();
@@ -22842,7 +22903,7 @@
ctor public MediaRecorder();
method public static final int getAudioSourceMax();
method public int getMaxAmplitude() throws java.lang.IllegalStateException;
- method public android.os.Bundle getMetrics();
+ method public android.media.MediaMetricsSet 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;
@@ -36743,7 +36804,7 @@
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, android.os.CancellationSignal, android.service.autofill.FillCallback);
+ method public 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);
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";
@@ -45424,7 +45485,7 @@
method public void setActivated(boolean);
method public void setAlpha(float);
method public void setAnimation(android.view.animation.Animation);
- method public void setAutofillHint(java.lang.String[]);
+ method public void setAutofillHint(java.lang.String...);
method public void setAutofillMode(int);
method public void setBackground(android.graphics.drawable.Drawable);
method public void setBackgroundColor(int);
@@ -47507,6 +47568,7 @@
public final class AutofillManager {
method public void cancel();
method public void commit();
+ method public boolean isEnabled();
method public void notifyValueChanged(android.view.View);
method public void notifyViewEntered(android.view.View);
method public void notifyViewExited(android.view.View);
@@ -47514,9 +47576,12 @@
method public void notifyVirtualViewEntered(android.view.View, int, android.graphics.Rect);
method public void notifyVirtualViewExited(android.view.View, int);
method public void registerCallback(android.view.autofill.AutofillManager.AutofillCallback);
+ method public void requestAutofill(android.view.View);
+ method public void requestAutofill(android.view.View, int, android.graphics.Rect);
method public void unregisterCallback(android.view.autofill.AutofillManager.AutofillCallback);
field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
+ field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
}
public static abstract class AutofillManager.AutofillCallback {
diff --git a/api/system-current.txt b/api/system-current.txt
index 04dc632..eb5ebd7 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1907,6 +1907,7 @@
field public static final int accessibilityActionSetProgress = 16908349; // 0x102003d
field public static final int accessibilityActionShowOnScreen = 16908342; // 0x1020036
field public static final int addToDictionary = 16908330; // 0x102002a
+ field public static final int autofill = 16908355; // 0x1020043
field public static final int background = 16908288; // 0x1020000
field public static final int button1 = 16908313; // 0x1020019
field public static final int button2 = 16908314; // 0x102001a
@@ -5680,7 +5681,6 @@
public final class NotificationChannel implements android.os.Parcelable {
ctor public NotificationChannel(java.lang.String, java.lang.CharSequence, int);
- ctor public NotificationChannel(java.lang.String, int, int);
ctor protected NotificationChannel(android.os.Parcel);
method public boolean canBypassDnd();
method public boolean canShowBadge();
@@ -5694,19 +5694,17 @@
method public int getLightColor();
method public int getLockscreenVisibility();
method public java.lang.CharSequence getName();
- method public int getNameResId();
method public android.net.Uri getSound();
method public int getUserLockedFields();
method public long[] getVibrationPattern();
method public boolean isDeleted();
- method public void lockFields(int);
method public void populateFromXml(org.xmlpull.v1.XmlPullParser);
method public void setBypassDnd(boolean);
- method public void setDeleted(boolean);
method public void setGroup(java.lang.String);
method public void setImportance(int);
method public void setLightColor(int);
method public void setLockscreenVisibility(int);
+ method public void setName(java.lang.CharSequence);
method public void setShowBadge(boolean);
method public void setSound(android.net.Uri, android.media.AudioAttributes);
method public void setVibrationPattern(long[]);
@@ -5731,18 +5729,14 @@
public final class NotificationChannelGroup implements android.os.Parcelable {
ctor public NotificationChannelGroup(java.lang.String, java.lang.CharSequence);
- ctor public NotificationChannelGroup(java.lang.String, int);
ctor protected NotificationChannelGroup(android.os.Parcel);
- method public void addChannel(android.app.NotificationChannel);
method public android.app.NotificationChannelGroup clone();
method public int describeContents();
method public java.util.List<android.app.NotificationChannel> getChannels();
method public java.lang.String getId();
method public java.lang.CharSequence getName();
- method public int getNameResId();
method public org.json.JSONObject toJson() throws org.json.JSONException;
method public void writeToParcel(android.os.Parcel, int);
- method public void writeXml(org.xmlpull.v1.XmlSerializer) throws java.io.IOException;
field public static final android.os.Parcelable.Creator<android.app.NotificationChannelGroup> CREATOR;
}
@@ -23623,7 +23617,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.os.Bundle getMetrics();
+ method public android.media.MediaMetricsSet getMetrics();
method public final java.lang.String getName();
method public java.nio.ByteBuffer getOutputBuffer(int);
method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
@@ -24175,7 +24169,7 @@
method public boolean advance();
method public long getCachedDuration();
method public android.media.DrmInitData getDrmInitData();
- method public android.os.Bundle getMetrics();
+ method public android.media.MediaMetricsSet getMetrics();
method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
method public int getSampleFlags();
@@ -24430,6 +24424,69 @@
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;
@@ -24470,7 +24527,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.os.Bundle getMetrics();
+ method public android.media.MediaMetricsSet getMetrics();
method public android.media.PlaybackParams getPlaybackParams();
method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
method public android.media.SyncParams getSyncParams();
@@ -24638,7 +24695,7 @@
ctor public MediaRecorder();
method public static final int getAudioSourceMax();
method public int getMaxAmplitude() throws java.lang.IllegalStateException;
- method public android.os.Bundle getMetrics();
+ method public android.media.MediaMetricsSet 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;
@@ -39781,7 +39838,7 @@
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, android.os.CancellationSignal, android.service.autofill.FillCallback);
+ method public 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);
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";
@@ -48891,7 +48948,7 @@
method public void setActivated(boolean);
method public void setAlpha(float);
method public void setAnimation(android.view.animation.Animation);
- method public void setAutofillHint(java.lang.String[]);
+ method public void setAutofillHint(java.lang.String...);
method public void setAutofillMode(int);
method public void setBackground(android.graphics.drawable.Drawable);
method public void setBackgroundColor(int);
@@ -50977,6 +51034,7 @@
public final class AutofillManager {
method public void cancel();
method public void commit();
+ method public boolean isEnabled();
method public void notifyValueChanged(android.view.View);
method public void notifyViewEntered(android.view.View);
method public void notifyViewExited(android.view.View);
@@ -50984,9 +51042,12 @@
method public void notifyVirtualViewEntered(android.view.View, int, android.graphics.Rect);
method public void notifyVirtualViewExited(android.view.View, int);
method public void registerCallback(android.view.autofill.AutofillManager.AutofillCallback);
+ method public void requestAutofill(android.view.View);
+ method public void requestAutofill(android.view.View, int, android.graphics.Rect);
method public void unregisterCallback(android.view.autofill.AutofillManager.AutofillCallback);
field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
+ field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
}
public static abstract class AutofillManager.AutofillCallback {
diff --git a/api/test-current.txt b/api/test-current.txt
index 6962c45..3b02916 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1790,6 +1790,7 @@
field public static final int accessibilityActionSetProgress = 16908349; // 0x102003d
field public static final int accessibilityActionShowOnScreen = 16908342; // 0x1020036
field public static final int addToDictionary = 16908330; // 0x102002a
+ field public static final int autofill = 16908355; // 0x1020043
field public static final int background = 16908288; // 0x1020000
field public static final int button1 = 16908313; // 0x1020019
field public static final int button2 = 16908314; // 0x102001a
@@ -5503,7 +5504,6 @@
public final class NotificationChannel implements android.os.Parcelable {
ctor public NotificationChannel(java.lang.String, java.lang.CharSequence, int);
- ctor public NotificationChannel(java.lang.String, int, int);
ctor protected NotificationChannel(android.os.Parcel);
method public boolean canBypassDnd();
method public boolean canShowBadge();
@@ -5517,7 +5517,6 @@
method public int getLightColor();
method public int getLockscreenVisibility();
method public java.lang.CharSequence getName();
- method public int getNameResId();
method public android.net.Uri getSound();
method public long[] getVibrationPattern();
method public void setBypassDnd(boolean);
@@ -5525,6 +5524,7 @@
method public void setImportance(int);
method public void setLightColor(int);
method public void setLockscreenVisibility(int);
+ method public void setName(java.lang.CharSequence);
method public void setShowBadge(boolean);
method public void setSound(android.net.Uri, android.media.AudioAttributes);
method public void setVibrationPattern(long[]);
@@ -5537,14 +5537,12 @@
public final class NotificationChannelGroup implements android.os.Parcelable {
ctor public NotificationChannelGroup(java.lang.String, java.lang.CharSequence);
- ctor public NotificationChannelGroup(java.lang.String, int);
ctor protected NotificationChannelGroup(android.os.Parcel);
method public android.app.NotificationChannelGroup clone();
method public int describeContents();
method public java.util.List<android.app.NotificationChannel> getChannels();
method public java.lang.String getId();
method public java.lang.CharSequence getName();
- method public int getNameResId();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.NotificationChannelGroup> CREATOR;
}
@@ -21928,7 +21926,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.os.Bundle getMetrics();
+ method public android.media.MediaMetricsSet getMetrics();
method public final java.lang.String getName();
method public java.nio.ByteBuffer getOutputBuffer(int);
method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
@@ -22480,7 +22478,7 @@
method public boolean advance();
method public long getCachedDuration();
method public android.media.DrmInitData getDrmInitData();
- method public android.os.Bundle getMetrics();
+ method public android.media.MediaMetricsSet getMetrics();
method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
method public int getSampleFlags();
@@ -22735,6 +22733,69 @@
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;
@@ -22775,7 +22836,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.os.Bundle getMetrics();
+ method public android.media.MediaMetricsSet getMetrics();
method public android.media.PlaybackParams getPlaybackParams();
method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
method public android.media.SyncParams getSyncParams();
@@ -22943,7 +23004,7 @@
ctor public MediaRecorder();
method public static final int getAudioSourceMax();
method public int getMaxAmplitude() throws java.lang.IllegalStateException;
- method public android.os.Bundle getMetrics();
+ method public android.media.MediaMetricsSet 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;
@@ -36887,7 +36948,7 @@
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, android.os.CancellationSignal, android.service.autofill.FillCallback);
+ method public 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);
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";
@@ -45787,7 +45848,7 @@
method public void setActivated(boolean);
method public void setAlpha(float);
method public void setAnimation(android.view.animation.Animation);
- method public void setAutofillHint(java.lang.String[]);
+ method public void setAutofillHint(java.lang.String...);
method public void setAutofillMode(int);
method public void setBackground(android.graphics.drawable.Drawable);
method public void setBackgroundColor(int);
@@ -47876,6 +47937,7 @@
public final class AutofillManager {
method public void cancel();
method public void commit();
+ method public boolean isEnabled();
method public void notifyValueChanged(android.view.View);
method public void notifyViewEntered(android.view.View);
method public void notifyViewExited(android.view.View);
@@ -47883,9 +47945,12 @@
method public void notifyVirtualViewEntered(android.view.View, int, android.graphics.Rect);
method public void notifyVirtualViewExited(android.view.View, int);
method public void registerCallback(android.view.autofill.AutofillManager.AutofillCallback);
+ method public void requestAutofill(android.view.View);
+ method public void requestAutofill(android.view.View, int, android.graphics.Rect);
method public void unregisterCallback(android.view.autofill.AutofillManager.AutofillCallback);
field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
+ field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
}
public static abstract class AutofillManager.AutofillCallback {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 44cc5b4..5cdfb8e 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -50,6 +50,7 @@
import android.database.sqlite.SQLiteDebug.DbStats;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Typeface;
import android.hardware.display.DisplayManagerGlobal;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
@@ -5665,6 +5666,7 @@
}
// Preload fonts resources
+ Typeface.setApplicationContext(appContext);
try {
final ApplicationInfo info =
getPackageManager().getApplicationInfo(
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 5ab767b..896f56c 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -66,6 +66,7 @@
ParceledListSlice getNotificationChannels(String pkg);
ParceledListSlice getNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted);
int getNumNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted);
+ int getDeletedChannelCount(String pkg, int uid);
// TODO: Remove this when callers have been migrated to the equivalent
// INotificationListener method.
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 16c85f5..29c4520 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -24,6 +24,7 @@
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.SystemApi;
+import android.content.Intent;
import android.media.AudioAttributes;
import android.net.Uri;
import android.os.Parcel;
@@ -47,7 +48,6 @@
private static final String TAG_CHANNEL = "channel";
private static final String ATT_NAME = "name";
- private static final String ATT_NAME_RES_ID = "name_res_id";
private static final String ATT_ID = "id";
private static final String ATT_DELETED = "deleted";
private static final String ATT_PRIORITY = "priority";
@@ -141,7 +141,6 @@
private final String mId;
private CharSequence mName;
- private int mNameResId = 0;
private int mImportance = DEFAULT_IMPORTANCE;
private boolean mBypassDnd;
private int mLockscreenVisibility = DEFAULT_VISIBILITY;
@@ -162,7 +161,9 @@
* @param id The id of the channel. Must be unique per package.
* @param name The user visible name of the channel. Unchangeable once created; use this
* constructor if the channel represents a user-defined category that does not
- * need to be translated.
+ * need to be translated. You can rename this channel when the system
+ * locale changes by listening for the {@link Intent#ACTION_LOCALE_CHANGED}
+ * broadcast.
* @param importance The importance of the channel. This controls how interruptive notifications
* posted to this channel are. See e.g.
* {@link NotificationManager#IMPORTANCE_DEFAULT}.
@@ -173,21 +174,6 @@
this.mImportance = importance;
}
- /**
- * Creates a notification channel.
- *
- * @param id The id of the channel. Must be unique per package.
- * @param nameResId The resource id of the string containing the channel name.
- * @param importance The importance of the channel. This controls how interruptive notifications
- * posted to this channel are. See e.g.
- * {@link NotificationManager#IMPORTANCE_DEFAULT}.
- */
- public NotificationChannel(String id, @StringRes int nameResId, int importance) {
- this.mId = id;
- this.mNameResId = nameResId;
- this.mImportance = importance;
- }
-
protected NotificationChannel(Parcel in) {
if (in.readByte() != 0) {
mId = in.readString();
@@ -195,7 +181,6 @@
mId = null;
}
mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
- mNameResId = in.readInt();
mImportance = in.readInt();
mBypassDnd = in.readByte() != 0;
mLockscreenVisibility = in.readInt();
@@ -228,7 +213,6 @@
dest.writeByte((byte) 0);
}
TextUtils.writeToParcel(mName, dest, flags);
- dest.writeInt(mNameResId);
dest.writeInt(mImportance);
dest.writeByte(mBypassDnd ? (byte) 1 : (byte) 0);
dest.writeInt(mLockscreenVisibility);
@@ -262,7 +246,6 @@
/**
* @hide
*/
- @SystemApi
public void lockFields(int field) {
mUserLockedFields |= field;
}
@@ -270,16 +253,15 @@
/**
* @hide
*/
- @SystemApi
public void setDeleted(boolean deleted) {
mDeleted = deleted;
}
/**
- * @hide
+ * Sets the name of this channel.
*/
- public void setNameResId(@StringRes int nameResId) {
- this.mNameResId = nameResId;
+ public void setName(CharSequence name) {
+ mName = name;
}
// Modifiable by a notification ranker.
@@ -417,13 +399,6 @@
}
/**
- * Returns the resource id of the user visible name of this channel.
- */
- public int getNameResId() {
- return mNameResId;
- }
-
- /**
* Returns the user specified importance {e.g. @link NotificationManager#IMPORTANCE_LOW} for
* notifications posted to this channel.
*/
@@ -556,7 +531,6 @@
if (getName() != null) {
out.attribute(null, ATT_NAME, getName().toString());
}
- out.attribute(null, ATT_NAME_RES_ID, Integer.toString(getNameResId()));
if (getImportance() != DEFAULT_IMPORTANCE) {
out.attribute(
null, ATT_IMPORTANCE, Integer.toString(getImportance()));
@@ -614,7 +588,6 @@
JSONObject record = new JSONObject();
record.put(ATT_ID, getId());
record.put(ATT_NAME, getName());
- record.put(ATT_NAME_RES_ID, getNameResId());
if (getImportance() != DEFAULT_IMPORTANCE) {
record.put(ATT_IMPORTANCE,
NotificationListenerService.Ranking.importanceToString(getImportance()));
@@ -732,7 +705,6 @@
NotificationChannel that = (NotificationChannel) o;
- if (getNameResId() != that.getNameResId()) return false;
if (getImportance() != that.getImportance()) return false;
if (mBypassDnd != that.mBypassDnd) return false;
if (getLockscreenVisibility() != that.getLockscreenVisibility()) return false;
@@ -762,7 +734,6 @@
public int hashCode() {
int result = getId() != null ? getId().hashCode() : 0;
result = 31 * result + (getName() != null ? getName().hashCode() : 0);
- result = 31 * result + getNameResId();
result = 31 * result + getImportance();
result = 31 * result + (mBypassDnd ? 1 : 0);
result = 31 * result + getLockscreenVisibility();
@@ -784,7 +755,6 @@
return "NotificationChannel{" +
"mId='" + mId + '\'' +
", mName=" + mName +
- ", mNameResId=" + mNameResId +
", mImportance=" + mImportance +
", mBypassDnd=" + mBypassDnd +
", mLockscreenVisibility=" + mLockscreenVisibility +
diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java
index 288d39a..2b0cd04 100644
--- a/core/java/android/app/NotificationChannelGroup.java
+++ b/core/java/android/app/NotificationChannelGroup.java
@@ -17,6 +17,7 @@
import android.annotation.StringRes;
import android.annotation.SystemApi;
+import android.content.Intent;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -41,38 +42,25 @@
private static final String TAG_GROUP = "channelGroup";
private static final String ATT_NAME = "name";
- private static final String ATT_NAME_RES_ID = "name_res_id";
private static final String ATT_ID = "id";
private final String mId;
private CharSequence mName;
- private int mNameResId = 0;
private List<NotificationChannel> mChannels = new ArrayList<>();
/**
- * Creates a notification channel.
+ * Creates a notification channel group.
*
* @param id The id of the group. Must be unique per package.
- * @param name The user visible name of the group. Unchangeable once created; use this
- * constructor if the group represents something user-defined that does not
- * need to be translated.
+ * @param name The user visible name of the group. You can rename this group when the system
+ * locale changes by listening for the {@link Intent#ACTION_LOCALE_CHANGED}
+ * broadcast.
*/
public NotificationChannelGroup(String id, CharSequence name) {
this.mId = id;
this.mName = name;
}
- /**
- * Creates a notification channel.
- *
- * @param id The id of the group. Must be unique per package.
- * @param nameResId String resource id of the user visible name of the group.
- */
- public NotificationChannelGroup(String id, @StringRes int nameResId) {
- this.mId = id;
- this.mNameResId = nameResId;
- }
-
protected NotificationChannelGroup(Parcel in) {
if (in.readByte() != 0) {
mId = in.readString();
@@ -80,7 +68,6 @@
mId = null;
}
mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
- mNameResId = in.readInt();
in.readParcelableList(mChannels, NotificationChannel.class.getClassLoader());
}
@@ -93,7 +80,6 @@
dest.writeByte((byte) 0);
}
TextUtils.writeToParcel(mName, dest, flags);
- dest.writeInt(mNameResId);
dest.writeParcelableList(mChannels, flags);
}
@@ -111,19 +97,11 @@
return mName;
}
- /**
- * Returns the resource id of the user visible name of this group.
- */
- public @StringRes int getNameResId() {
- return mNameResId;
- }
-
/*
* Returns the list of channels that belong to this group
*
* @hide
*/
- @SystemApi
public List<NotificationChannel> getChannels() {
return mChannels;
}
@@ -131,7 +109,6 @@
/**
* @hide
*/
- @SystemApi
public void addChannel(NotificationChannel channel) {
mChannels.add(channel);
}
@@ -139,7 +116,6 @@
/**
* @hide
*/
- @SystemApi
public void writeXml(XmlSerializer out) throws IOException {
out.startTag(null, TAG_GROUP);
@@ -147,9 +123,6 @@
if (getName() != null) {
out.attribute(null, ATT_NAME, getName().toString());
}
- if (getNameResId() != 0) {
- out.attribute(null, ATT_NAME_RES_ID, Integer.toString(getNameResId()));
- }
out.endTag(null, TAG_GROUP);
}
@@ -162,7 +135,6 @@
JSONObject record = new JSONObject();
record.put(ATT_ID, getId());
record.put(ATT_NAME, getName());
- record.put(ATT_NAME_RES_ID, getNameResId());
return record;
}
@@ -191,31 +163,22 @@
NotificationChannelGroup that = (NotificationChannelGroup) o;
- if (getNameResId() != that.getNameResId()) return false;
if (getId() != null ? !getId().equals(that.getId()) : that.getId() != null) return false;
if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) {
return false;
}
- return getChannels() != null ? getChannels().equals(that.getChannels())
- : that.getChannels() == null;
-
+ return true;
}
@Override
public NotificationChannelGroup clone() {
- if (getName() != null) {
- return new NotificationChannelGroup(getId(), getName());
- } else {
- return new NotificationChannelGroup(getId(), getNameResId());
- }
+ return new NotificationChannelGroup(getId(), getName());
}
@Override
public int hashCode() {
int result = getId() != null ? getId().hashCode() : 0;
result = 31 * result + (getName() != null ? getName().hashCode() : 0);
- result = 31 * result + getNameResId();
- result = 31 * result + (getChannels() != null ? getChannels().hashCode() : 0);
return result;
}
@@ -224,7 +187,6 @@
return "NotificationChannelGroup{" +
"mId='" + mId + '\'' +
", mName=" + mName +
- ", mNameResId=" + mNameResId +
", mChannels=" + mChannels +
'}';
}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 2296838..2a78b6b 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -385,7 +385,7 @@
/**
* Creates a group container for {@link NotificationChannel} objects.
*
- * This is a no-op for groups that already exist.
+ * This can be used to rename an existing group.
* <p>
* Group information is only used for presentation, not for behavior. Groups are optional
* for channels, and you can have a mix of channels that belong to groups and channels
@@ -421,21 +421,22 @@
/**
* Creates a notification channel that notifications can be posted to.
*
- * This is a no-op for channels that already exist.
+ * This can also be used to restore a deleted channel and to rename an existing channel. All
+ * other fields are ignored for channels that already exist.
*
* @param channel the channel to create. Note that the created channel may differ from this
* value. If the provided channel is malformed, a RemoteException will be
- * thrown. If the channel already exists, it will not be modified.
+ * thrown.
*/
public void createNotificationChannel(@NonNull NotificationChannel channel) {
createNotificationChannels(Arrays.asList(channel));
}
/**
- * Creates multiple notification channels that different notifications can be posted to.
+ * Creates multiple notification channels that different notifications can be posted to. See
+ * {@link #createNotificationChannel(NotificationChannel)}.
*
- * @param channels the list of channels to attempt to create. If any of these channels already
- * exist, they will not be modified.
+ * @param channels the list of channels to attempt to create.
*/
public void createNotificationChannels(@NonNull List<NotificationChannel> channels) {
INotificationManager service = getService();
diff --git a/core/java/android/net/ConnectivityMetricsEvent.java b/core/java/android/net/ConnectivityMetricsEvent.java
index 6fdc739..4faff62 100644
--- a/core/java/android/net/ConnectivityMetricsEvent.java
+++ b/core/java/android/net/ConnectivityMetricsEvent.java
@@ -19,39 +19,40 @@
import android.os.Parcel;
import android.os.Parcelable;
-/** {@hide} */
+/**
+ * Represents a core networking event defined in package android.net.metrics.
+ * Logged by IpConnectivityLog and managed by ConnectivityMetrics service.
+ * {@hide}
+ * */
public final class ConnectivityMetricsEvent implements Parcelable {
- /** The time when this event was collected, as returned by System.currentTimeMillis(). */
- final public long timestamp;
-
- /** The subsystem that generated the event. One of the COMPONENT_TAG_xxx constants. */
- final public int componentTag;
-
- /** The subsystem-specific event ID. */
- final public int eventTag;
-
+ /** Time when this event was collected, as returned by System.currentTimeMillis(). */
+ public long timestamp;
+ /** Transports of the network associated with the event, as defined in NetworkCapabilities. */
+ public long transports;
+ /** Network id of the network associated with the event, or 0 if unspecified. */
+ public int netId;
+ /** Name of the network interface associated with the event, or null if unspecified. */
+ public String ifname;
/** Opaque event-specific data. */
- final public Parcelable data;
+ public Parcelable data;
- public ConnectivityMetricsEvent(long timestamp, int componentTag,
- int eventTag, Parcelable data) {
- this.timestamp = timestamp;
- this.componentTag = componentTag;
- this.eventTag = eventTag;
- this.data = data;
+ public ConnectivityMetricsEvent() {
+ }
+
+ private ConnectivityMetricsEvent(Parcel in) {
+ timestamp = in.readLong();
+ transports = in.readLong();
+ netId = in.readInt();
+ ifname = in.readString();
+ data = in.readParcelable(null);
}
/** Implement the Parcelable interface */
public static final Parcelable.Creator<ConnectivityMetricsEvent> CREATOR
= new Parcelable.Creator<ConnectivityMetricsEvent> (){
public ConnectivityMetricsEvent createFromParcel(Parcel source) {
- final long timestamp = source.readLong();
- final int componentTag = source.readInt();
- final int eventTag = source.readInt();
- final Parcelable data = source.readParcelable(null);
- return new ConnectivityMetricsEvent(timestamp, componentTag,
- eventTag, data);
+ return new ConnectivityMetricsEvent(source);
}
public ConnectivityMetricsEvent[] newArray(int size) {
@@ -59,7 +60,6 @@
}
};
- /** Implement the Parcelable interface */
@Override
public int describeContents() {
return 0;
@@ -68,13 +68,15 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(timestamp);
- dest.writeInt(componentTag);
- dest.writeInt(eventTag);
+ dest.writeLong(transports);
+ dest.writeInt(netId);
+ dest.writeString(ifname);
dest.writeParcelable(data, 0);
}
+ @Override
public String toString() {
- return String.format("ConnectivityMetricsEvent(%tT.%tL, %d, %d): %s",
- timestamp, timestamp, componentTag, eventTag, data);
+ // TODO: add transports, netId, ifname
+ return String.format("ConnectivityMetricsEvent(%tT.%tL): %s", timestamp, timestamp, data);
}
}
diff --git a/core/java/android/net/metrics/IpConnectivityLog.java b/core/java/android/net/metrics/IpConnectivityLog.java
index 173e5fd..79094c0 100644
--- a/core/java/android/net/metrics/IpConnectivityLog.java
+++ b/core/java/android/net/metrics/IpConnectivityLog.java
@@ -60,21 +60,23 @@
}
/**
- * Log an IpConnectivity event.
- * @param timestamp is the epoch timestamp of the event in ms.
- * @param data is a Parcelable instance representing the event.
+ * Log a ConnectivityMetricsEvent.
+ * @param ev the event to log. If the event timestamp is 0,
+ * the timestamp is set to the current time in milliseconds.
* @return true if the event was successfully logged.
*/
- public boolean log(long timestamp, Parcelable data) {
+ public boolean log(ConnectivityMetricsEvent ev) {
if (!checkLoggerService()) {
if (DBG) {
Log.d(TAG, SERVICE_NAME + " service was not ready");
}
return false;
}
-
+ if (ev.timestamp == 0) {
+ ev.timestamp = System.currentTimeMillis();
+ }
try {
- int left = mService.logEvent(new ConnectivityMetricsEvent(timestamp, 0, 0, data));
+ int left = mService.logEvent(ev);
return left >= 0;
} catch (RemoteException e) {
Log.e(TAG, "Error logging event", e);
@@ -82,7 +84,31 @@
}
}
- public void log(Parcelable event) {
- log(System.currentTimeMillis(), event);
+ /**
+ * Log an IpConnectivity event.
+ * @param timestamp is the epoch timestamp of the event in ms.
+ * If the timestamp is 0, the timestamp is set to the current time in milliseconds.
+ * @param data is a Parcelable instance representing the event.
+ * @return true if the event was successfully logged.
+ */
+ public boolean log(long timestamp, Parcelable data) {
+ ConnectivityMetricsEvent ev = makeEv(data);
+ ev.timestamp = timestamp;
+ return log(ev);
+ }
+
+ /**
+ * Log an IpConnectivity event.
+ * @param data is a Parcelable instance representing the event.
+ * @return true if the event was successfully logged.
+ */
+ public boolean log(Parcelable data) {
+ return log(makeEv(data));
+ }
+
+ private static ConnectivityMetricsEvent makeEv(Parcelable data) {
+ ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
+ ev.data = data;
+ return ev;
}
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index dc170ed..29884b1 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2042,8 +2042,8 @@
public static final String[] HISTORY_EVENT_NAMES = new String[] {
"null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn",
- "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active", "tmpwhitelist",
- "screenwake", "wakeupap", "longwake", "est_capacity"
+ "active", "pkginst", "pkgunin", "alarm", "stats", "pkginactive", "pkgactive",
+ "tmpwhitelist", "screenwake", "wakeupap", "longwake", "est_capacity"
};
public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index b525193..8632194 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -35,6 +35,12 @@
private static final String TAG = "SystemProperties";
private static final boolean TRACK_KEY_ACCESS = false;
+ /**
+ * Android O removed the property name length limit, but com.amazon.kindle 7.8.1.5
+ * uses reflection to read this whenever text is selected (http://b/36095274).
+ */
+ public static final int PROP_NAME_MAX = Integer.MAX_VALUE;
+
public static final int PROP_VALUE_MAX = 91;
private static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>();
diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java
index 9f5d9d4..84443e9 100644
--- a/core/java/android/provider/FontsContract.java
+++ b/core/java/android/provider/FontsContract.java
@@ -138,12 +138,8 @@
private HandlerThread mThread;
/** @hide */
- public FontsContract() {
- // TODO: investigate if the system context is the best option here. ApplicationContext or
- // the one passed by developer?
- // TODO: Looks like ActivityThread.currentActivityThread() can return null. Check when it
- // returns null and check if we need to handle null case.
- mContext = ActivityThread.currentActivityThread().getSystemContext();
+ public FontsContract(Context context) {
+ mContext = context.getApplicationContext();
mPackageManager = mContext.getPackageManager();
}
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 29e2073..709e5f9 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -30,6 +30,7 @@
import android.os.ICancellationSignal;
import android.os.Looper;
import android.util.Log;
+import android.view.autofill.AutofillManager;
import com.android.internal.os.SomeArgs;
@@ -90,6 +91,8 @@
private static final int MSG_ON_FILL_REQUEST = 3;
private static final int MSG_ON_SAVE_REQUEST = 4;
+ private static final int UNUSED_ARG = -1;
+
private final IAutoFillService mInterface = new IAutoFillService.Stub() {
@Override
public void onInit(IAutoFillServiceConnection connection) {
@@ -102,14 +105,14 @@
@Override
public void onFillRequest(AssistStructure structure, Bundle extras,
- IFillCallback callback) {
+ IFillCallback callback, int flags) {
ICancellationSignal transport = CancellationSignal.createTransport();
try {
callback.onCancellable(transport);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
- mHandlerCaller.obtainMessageOOOO(MSG_ON_FILL_REQUEST, structure,
+ mHandlerCaller.obtainMessageIIOOOO(MSG_ON_FILL_REQUEST, flags, UNUSED_ARG, structure,
CancellationSignal.fromTransport(transport), extras, callback)
.sendToTarget();
}
@@ -135,8 +138,9 @@
final Bundle extras = (Bundle) args.arg3;
final IFillCallback callback = (IFillCallback) args.arg4;
final FillCallback fillCallback = new FillCallback(callback);
+ final int flags = msg.arg1;
args.recycle();
- onFillRequest(structure, extras, cancellation, fillCallback);
+ onFillRequest(structure, extras, flags, cancellation, fillCallback);
break;
} case MSG_ON_SAVE_REQUEST: {
final SomeArgs args = (SomeArgs) msg.obj;
@@ -188,7 +192,6 @@
* <p>You should generally do initialization here rather than in {@link #onCreate}.
*/
public void onConnected() {
- //TODO(b/33197203): is not called anymore, fix it!
}
/**
@@ -206,11 +209,25 @@
* as well as when filling different sections of the UI as the system will try to
* aggressively unbind from the service to conserve resources. See {@link
* FillResponse} Javadoc for examples of multiple-sections requests.
+ * @param flags either {@code 0} or {@link AutofillManager#FLAG_MANUAL_REQUEST}.
* @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 AssistStructure structure, @Nullable Bundle data, int flags,
+ @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback) {
+ //TODO(b/33197203): make non-abstract once older method is removed
+ onFillRequest(structure, data, cancellationSignal, callback);
+ }
+
+ /**
+ * @hide
+ * @deprecated - use {@link #onFillRequest(AssistStructure, Bundle, int,
+ * CancellationSignal, FillCallback)} instead
+ */
+ //TODO(b/33197203): remove once clients are not using anymore
+ @Deprecated
public abstract void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
@NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback);
@@ -238,7 +255,6 @@
* <p> At this point this service may no longer be an active {@link AutofillService}.
*/
public void onDisconnected() {
- //TODO(b/33197203): is not called anymore, fix it!
}
/**
diff --git a/core/java/android/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java
index 00b206c..e8ad14f 100644
--- a/core/java/android/service/autofill/FillCallback.java
+++ b/core/java/android/service/autofill/FillCallback.java
@@ -37,7 +37,7 @@
/**
* Notifies the Android System that an
* {@link AutofillService#onFillRequest(android.app.assist.AssistStructure, Bundle,
- * android.os.CancellationSignal, FillCallback)} was successfully fulfilled by the service.
+ * int, android.os.CancellationSignal, FillCallback)} was successfully fulfilled by the service.
*
* @param response autofill information for that activity, or {@code null} when the activity
* cannot be autofilled (for example, if it only contains read-only fields). See
@@ -56,7 +56,7 @@
/**
* Notifies the Android System that an
* {@link AutofillService#onFillRequest(android.app.assist.AssistStructure,
- * Bundle, android.os.CancellationSignal, FillCallback)}
+ * Bundle, int, android.os.CancellationSignal, FillCallback)}
* could not be fulfilled by the service.
*
* @param message error message to be displayed to the user.
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index b808de7..c43019d 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -31,7 +31,7 @@
/**
* Response for a {@link
* AutofillService#onFillRequest(android.app.assist.AssistStructure,
- * Bundle, android.os.CancellationSignal, FillCallback)}.
+ * Bundle, int, android.os.CancellationSignal, FillCallback)}.
*
* <p>The response typically contains one or more {@link Dataset}s, each representing a set of
* fields that can be autofilled together, and the Android system displays a dataset picker UI
@@ -269,8 +269,8 @@
* Sets a {@link Bundle} 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, android.os.CancellationSignal,
- * FillCallback)} and {@link AutofillService#onSaveRequest(
+ * android.app.assist.AssistStructure, Bundle, int,
+ * android.os.CancellationSignal, FillCallback)} and {@link AutofillService#onSaveRequest(
* android.app.assist.AssistStructure, Bundle, SaveCallback)}.
*
* @param extras The response extras.
diff --git a/core/java/android/service/autofill/IAutoFillService.aidl b/core/java/android/service/autofill/IAutoFillService.aidl
index 80685d8..9f296c6 100644
--- a/core/java/android/service/autofill/IAutoFillService.aidl
+++ b/core/java/android/service/autofill/IAutoFillService.aidl
@@ -31,7 +31,7 @@
oneway interface IAutoFillService {
void onInit(in IAutoFillServiceConnection connection);
void onFillRequest(in AssistStructure structure, in Bundle extras,
- in IFillCallback callback);
+ in IFillCallback callback, int flags);
void onSaveRequest(in AssistStructure structure, in Bundle extras,
in ISaveCallback callback);
}
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 6d368b5..6663f03 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -119,7 +119,6 @@
*/
public static final int SAVE_DATA_TYPE_PASSWORD = 1;
-
/**
* Type used on when the {@link FillResponse} represents a physical address (such as street,
* city, state, etc).
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 1facc10..7e6af11 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -98,31 +98,6 @@
out Rect outOutsets, out Rect outBackdropFrame, out Configuration outConfig,
out Surface outSurface);
- /**
- * Position a window relative to it's parent (attached) window without triggering
- * a full relayout. This action may be deferred until a given frame number
- * for the parent window appears. This allows for synchronizing movement of a child
- * to repainting the contents of the parent.
- *
- * "width" and "height" correspond to the width and height members of
- * WindowManager.LayoutParams in the {@link #relayout relayout()} case.
- * This may differ from the surface buffer size in the
- * case of {@link LayoutParams#FLAG_SCALED} and {@link #relayout relayout()}
- * must be used with requestedWidth/height if this must be changed.
- *
- * @param window The window being modified. Must be attached to a parent window
- * or this call will fail.
- * @param left The new left position
- * @param top The new top position
- * @param right The new right position
- * @param bottom The new bottom position
- * @param deferTransactionUntilFrame Frame number from our parent (attached) to
- * defer this action until.
- * @param outFrame Rect in which is placed the new position/size on screen.
- */
- void repositionChild(IWindow childWindow, int left, int top, int right, int bottom,
- long deferTransactionUntilFrame, out Rect outFrame);
-
/*
* Notify the window manager that an application is relaunching and
* windows should be prepared for replacement.
@@ -134,12 +109,6 @@
void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly);
/**
- * If a call to relayout() asked to have the surface destroy deferred,
- * it must call this once it is okay to destroy that surface.
- */
- void performDeferredDestroy(IWindow window);
-
- /**
* Called by a client to report that it ran out of graphics memory.
*/
boolean outOfMemory(IWindow window);
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index a71b899..38c7738 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -350,7 +350,7 @@
* Sets whether the data on this node is sensitive; if it is, then its content (text, autofill
* value, etc..) is striped before calls to {@link
* android.service.autofill.AutofillService#onFillRequest(android.app.assist.AssistStructure,
- * Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback)}.
+ * Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback)}.
*
* <p>By default, all nodes are assumed to be sensitive, and only nodes that does not have PII
* (Personally Identifiable Information - sensitive data such as email addresses, credit card
@@ -360,8 +360,8 @@
* <p>Notice that the content of even sensitive nodes are sent to the service (through the
* {@link
* android.service.autofill.AutofillService#onSaveRequest(android.app.assist.AssistStructure,
- * Bundle, android.service.autofill.SaveCallback)} call) when the user consented to save the
- * data, so it is important to set the content of sensitive nodes as well, but mark them as
+ * Bundle, android.service.autofill.SaveCallback)} call) when the user consented to save
+ * thedata, so it is important to set the content of sensitive nodes as well, but mark them as
* sensitive.
*
* <p>Should only be set when the node is used for autofill purposes - it will be ignored
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index c4f90dc..f036b9c 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -71,10 +71,17 @@
public static final String EXTRA_AUTHENTICATION_RESULT =
"android.view.autofill.extra.AUTHENTICATION_RESULT";
- /** @hide */ public static final int FLAG_START_SESSION = 0x1;
- /** @hide */ public static final int FLAG_VIEW_ENTERED = 0x2;
- /** @hide */ public static final int FLAG_VIEW_EXITED = 0x4;
- /** @hide */ public static final int FLAG_VALUE_CHANGED = 0x8;
+ // Public flags start from the lowest bit
+ /**
+ * Indicates autofill was explicitly requested by the user.
+ */
+ public static final int FLAG_MANUAL_REQUEST = 0x1;
+
+ // Private flags start from the highest bit
+ /** @hide */ public static final int FLAG_START_SESSION = 0x80000000;
+ /** @hide */ public static final int FLAG_VIEW_ENTERED = 0x40000000;
+ /** @hide */ public static final int FLAG_VIEW_EXITED = 0x20000000;
+ /** @hide */ public static final int FLAG_VALUE_CHANGED = 0x10000000;
private final Rect mTempRect = new Rect();
@@ -121,6 +128,66 @@
}
/**
+ * Checkes whether autofill is enabled for the current user.
+ *
+ * <p>Typically used to determine whether the option to explicitly request autofill should
+ * be offered - see {@link #requestAutofill(View)}.
+ *
+ * @return whether autofill is enabled for the current user.
+ */
+ public boolean isEnabled() {
+ ensureServiceClientAddedIfNeeded();
+ return mEnabled;
+ }
+
+ /**
+ * Explicitly requests a new autofill context.
+ *
+ * <p>Normally, the autofill context is automatically started when autofillable views are
+ * focused, but this method should be used in the cases where it must be explicitly requested,
+ * like a view that provides a contextual menu allowing users to autofill the activity.
+ *
+ * @param view view requesting the new autofill context.
+ */
+ public void requestAutofill(@NonNull View view) {
+ ensureServiceClientAddedIfNeeded();
+
+ if (!mEnabled) {
+ return;
+ }
+
+ final Rect bounds = mTempRect;
+ view.getBoundsOnScreen(bounds);
+ final AutofillId id = getAutofillId(view);
+ final AutofillValue value = view.getAutofillValue();
+
+ startSession(id, view.getWindowToken(), bounds, value, FLAG_MANUAL_REQUEST);
+ }
+
+ /**
+ * Explicitly requests a new autofill context for virtual views.
+ *
+ * <p>Normally, the autofill context is automatically started when autofillable views are
+ * focused, but this method should be used in the cases where it must be explicitly requested,
+ * like a virtual view that provides a contextual menu allowing users to autofill the activity.
+ *
+ * @param view the {@link View} whose descendant is the virtual view.
+ * @param childId id identifying the virtual child inside the view.
+ * @param bounds child boundaries, relative to the top window.
+ */
+ public void requestAutofill(@NonNull View view, int childId, @NonNull Rect bounds) {
+ ensureServiceClientAddedIfNeeded();
+
+ if (!mEnabled) {
+ return;
+ }
+
+ final AutofillId id = getAutofillId(view, childId);
+ startSession(id, view.getWindowToken(), bounds, null, FLAG_MANUAL_REQUEST);
+ }
+
+
+ /**
* Called when a {@link View} that supports autofill is entered.
*
* @param view {@link View} that was entered.
@@ -139,7 +206,7 @@
if (!mHasSession) {
// Starts new session.
- startSession(id, view.getWindowToken(), bounds, value);
+ startSession(id, view.getWindowToken(), bounds, value, 0);
} else {
// Update focus on existing session.
updateSession(id, bounds, value, FLAG_VIEW_ENTERED);
@@ -181,7 +248,7 @@
if (!mHasSession) {
// Starts new session.
- startSession(id, view.getWindowToken(), bounds, null);
+ startSession(id, view.getWindowToken(), bounds, null, 0);
} else {
// Update focus on existing session.
updateSession(id, bounds, null, FLAG_VIEW_ENTERED);
@@ -224,16 +291,16 @@
/**
* Called to indicate the value of an autofillable virtual {@link View} changed.
*
- * @param parent parent view whose value changed.
+ * @param view the {@link View} whose descendant is the virtual view.
* @param childId id identifying the virtual child inside the parent view.
* @param value new value of the child.
*/
- public void notifyVirtualValueChanged(View parent, int childId, AutofillValue value) {
+ public void notifyVirtualValueChanged(View view, int childId, AutofillValue value) {
if (!mEnabled || !mHasSession) {
return;
}
- final AutofillId id = getAutofillId(parent, childId);
+ final AutofillId id = getAutofillId(view, childId);
updateSession(id, null, value, FLAG_VALUE_CHANGED);
}
@@ -305,15 +372,16 @@
}
private void startSession(AutofillId id, IBinder windowToken, Rect bounds,
- AutofillValue value) {
+ AutofillValue value, int flags) {
if (DEBUG) {
- Log.d(TAG, "startSession(): id=" + id + ", bounds=" + bounds + ", value=" + value);
+ Log.d(TAG, "startSession(): id=" + id + ", bounds=" + bounds + ", value=" + value
+ + ", flags=" + flags);
}
try {
mService.startSession(mContext.getActivityToken(), windowToken,
mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
- mCallback != null);
+ mCallback != null, flags);
final AutofillClient client = getClient();
if (client != null) {
client.resetableStateAvailable();
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index 86a4965..85b05e5 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -32,7 +32,7 @@
boolean addClient(in IAutoFillManagerClient client, int userId);
oneway void startSession(in IBinder activityToken, IBinder windowToken, in IBinder appCallback,
in AutofillId autoFillId, in Rect bounds, in AutofillValue value, int userId,
- boolean hasCallback);
+ boolean hasCallback, int flags);
oneway void updateSession(in IBinder activityToken, in AutofillId id, in Rect bounds,
in AutofillValue value, int flags, int userId);
oneway void finishSession(in IBinder activityToken, int userId);
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index ade03e1..faa2310 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -157,6 +157,7 @@
private static final int MENU_ITEM_ORDER_SELECT_ALL = 9;
private static final int MENU_ITEM_ORDER_REPLACE = 10;
private static final int MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START = 11;
+ private static final int MENU_ITEM_ORDER_AUTOFILL = 12;
// Each Editor manages its own undo stack.
private final UndoManager mUndoManager = new UndoManager();
@@ -2644,6 +2645,10 @@
.setAlphabeticShortcut('a')
.setEnabled(mTextView.canSelectAllText())
.setOnMenuItemClickListener(mOnContextMenuItemClickListener);
+ menu.add(Menu.NONE, TextView.ID_AUTOFILL, MENU_ITEM_ORDER_AUTOFILL,
+ com.android.internal.R.string.autofill)
+ .setEnabled(mTextView.canRequestAutofill())
+ .setOnMenuItemClickListener(mOnContextMenuItemClickListener);
mPreserveSelection = true;
}
@@ -3828,6 +3833,12 @@
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
+ if (mTextView.canRequestAutofill()) {
+ menu.add(Menu.NONE, TextView.ID_AUTOFILL, MENU_ITEM_ORDER_AUTOFILL,
+ com.android.internal.R.string.autofill)
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ }
+
updateSelectAllItem(menu);
updateReplaceItem(menu);
}
diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java
index a6a9db4..59881b5 100644
--- a/core/java/android/widget/TextClock.java
+++ b/core/java/android/widget/TextClock.java
@@ -132,7 +132,7 @@
private CharSequence mDescFormat;
- private boolean mRegistered;
+ private boolean mAttached;
private Calendar mTime;
private String mTimeZone;
@@ -252,7 +252,7 @@
}
createTime(mTimeZone);
- // Wait until registering for events to handle the ticker
+ // Wait until onAttachedToWindow() to handle the ticker
chooseFormat(false);
}
@@ -503,9 +503,12 @@
boolean hadSeconds = mHasSeconds;
mHasSeconds = DateFormat.hasSeconds(mFormat);
- if (handleTicker && mRegistered && hadSeconds != mHasSeconds) {
- if (hadSeconds) getHandler().removeCallbacks(mTicker);
- else mTicker.run();
+ if (handleTicker && mAttached && hadSeconds != mHasSeconds) {
+ if (hadSeconds) {
+ getHandler().removeCallbacks(mTicker);
+ } else if (getVisibility() == VISIBLE) {
+ mTicker.run();
+ }
}
}
@@ -517,27 +520,50 @@
}
@Override
- public void onVisibilityAggregated(boolean isVisible) {
- if (!mRegistered && isVisible) {
- mRegistered = true;
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ if (!mAttached) {
+ mAttached = true;
registerReceiver();
registerObserver();
createTime(mTimeZone);
- if (mHasSeconds) {
- mTicker.run();
- } else {
- onTimeChanged();
+ if (getVisibility() == VISIBLE) {
+ if (mHasSeconds) {
+ mTicker.run();
+ } else {
+ onTimeChanged();
+ }
}
- } else if (mRegistered && !isVisible) {
+ }
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+
+ if (mAttached) {
unregisterReceiver();
unregisterObserver();
getHandler().removeCallbacks(mTicker);
- mRegistered = false;
+ mAttached = false;
+ }
+ }
+
+ @Override
+ public void onVisibilityAggregated(boolean isVisible) {
+ if (mAttached) {
+ if (isVisible && mHasSeconds) {
+ mTicker.run();
+ } else {
+ getHandler().removeCallbacks(mTicker);
+ }
+ onTimeChanged();
}
}
@@ -560,7 +586,7 @@
}
private void registerObserver() {
- if (mRegistered) {
+ if (mAttached) {
if (mFormatChangeObserver == null) {
mFormatChangeObserver = new FormatChangeObserver(getHandler());
}
@@ -587,9 +613,11 @@
}
private void onTimeChanged() {
- mTime.setTimeInMillis(System.currentTimeMillis());
- setText(DateFormat.format(mFormat, mTime));
- setContentDescription(DateFormat.format(mDescFormat, mTime));
+ if (getVisibility() == VISIBLE) {
+ mTime.setTimeInMillis(System.currentTimeMillis());
+ setText(DateFormat.format(mFormat, mTime));
+ setContentDescription(DateFormat.format(mDescFormat, mTime));
+ }
}
/** @hide */
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index d04f70f..c5c317d 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -10012,6 +10012,21 @@
// TODO(b/33197203): add unit/CTS tests for autofill methods
+ boolean canRequestAutofill() {
+ final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
+ if (afm != null) {
+ return afm.isEnabled();
+ }
+ return false;
+ }
+
+ private void requestAutofill() {
+ final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
+ if (afm != null) {
+ afm.requestAutofill(this);
+ }
+ }
+
@Override
public void autofill(AutofillValue value) {
if (value.isText()) {
@@ -10481,6 +10496,7 @@
static final int ID_PASTE_AS_PLAIN_TEXT = android.R.id.pasteAsPlainText;
static final int ID_REPLACE = android.R.id.replaceText;
static final int ID_ASSIST = android.R.id.textAssist;
+ static final int ID_AUTOFILL = android.R.id.autofill;
/**
* Called when a context menu option for the text view is selected. Currently
@@ -10545,6 +10561,11 @@
case ID_SHARE:
shareSelectedText();
return true;
+
+ case ID_AUTOFILL:
+ requestAutofill();
+ stopTextActionMode();
+ return true;
}
return false;
}
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index ec3aac2..c840f26 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -48,12 +48,12 @@
List<NotificationChannel> channelsList = new ArrayList<NotificationChannel>();
channelsList.add(new NotificationChannel(
VIRTUAL_KEYBOARD,
- R.string.notification_channel_virtual_keyboard,
+ context.getString(R.string.notification_channel_virtual_keyboard),
NotificationManager.IMPORTANCE_LOW));
final NotificationChannel physicalKeyboardChannel = new NotificationChannel(
PHYSICAL_KEYBOARD,
- R.string.notification_channel_physical_keyboard,
+ context.getString(R.string.notification_channel_physical_keyboard),
NotificationManager.IMPORTANCE_DEFAULT);
physicalKeyboardChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
Notification.AUDIO_ATTRIBUTES_DEFAULT);
@@ -61,32 +61,32 @@
channelsList.add(new NotificationChannel(
SECURITY,
- R.string.notification_channel_security,
+ context.getString(R.string.notification_channel_security),
NotificationManager.IMPORTANCE_LOW));
channelsList.add(new NotificationChannel(
CAR_MODE,
- R.string.notification_channel_car_mode,
+ context.getString(R.string.notification_channel_car_mode),
NotificationManager.IMPORTANCE_LOW));
channelsList.add(new NotificationChannel(
DEVELOPER,
- R.string.notification_channel_developer,
+ context.getString(R.string.notification_channel_developer),
NotificationManager.IMPORTANCE_LOW));
channelsList.add(new NotificationChannel(
UPDATES,
- R.string.notification_channel_updates,
+ context.getString(R.string.notification_channel_updates),
NotificationManager.IMPORTANCE_LOW));
channelsList.add(new NotificationChannel(
NETWORK_STATUS,
- R.string.notification_channel_network_status,
+ context.getString(R.string.notification_channel_network_status),
NotificationManager.IMPORTANCE_LOW));
final NotificationChannel networkAlertsChannel = new NotificationChannel(
NETWORK_ALERTS,
- R.string.notification_channel_network_alerts,
+ context.getString(R.string.notification_channel_network_alerts),
NotificationManager.IMPORTANCE_HIGH);
networkAlertsChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
Notification.AUDIO_ATTRIBUTES_DEFAULT);
@@ -94,17 +94,17 @@
channelsList.add(new NotificationChannel(
VPN,
- R.string.notification_channel_vpn,
+ context.getString(R.string.notification_channel_vpn),
NotificationManager.IMPORTANCE_LOW));
channelsList.add(new NotificationChannel(
DEVICE_ADMIN,
- R.string.notification_channel_device_admin,
+ context.getString(R.string.notification_channel_device_admin),
NotificationManager.IMPORTANCE_LOW));
final NotificationChannel alertsChannel = new NotificationChannel(
ALERTS,
- R.string.notification_channel_alerts,
+ context.getString(R.string.notification_channel_alerts),
NotificationManager.IMPORTANCE_DEFAULT);
alertsChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
Notification.AUDIO_ATTRIBUTES_DEFAULT);
@@ -112,12 +112,12 @@
channelsList.add(new NotificationChannel(
RETAIL_MODE,
- R.string.notification_channel_retail_mode,
+ context.getString(R.string.notification_channel_retail_mode),
NotificationManager.IMPORTANCE_LOW));
channelsList.add(new NotificationChannel(
USB,
- R.string.notification_channel_usb,
+ context.getString(R.string.notification_channel_usb),
NotificationManager.IMPORTANCE_MIN));
nm.createNotificationChannels(channelsList);
@@ -128,7 +128,7 @@
final NotificationManager nm = context.getSystemService(NotificationManager.class);
nm.createNotificationChannelsForPackage(pkg, Arrays.asList(new NotificationChannel(
ACCOUNT,
- R.string.notification_channel_account,
+ context.getString(R.string.notification_channel_account),
NotificationManager.IMPORTANCE_LOW)));
}
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index f8a071d..cd3624d 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -138,4 +138,8 @@
<!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_MOVE_WINDOW}. -->
<item type="id" name="accessibilityActionMoveWindow" />
+
+ <!-- Action used to manually trigger an autofill request -->
+ <item type="id" name="autofill" />
+
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 59432cd..2897c62 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2815,6 +2815,7 @@
<public-group type="id" first-id="0x01020041">
<public name="textAssist" />
<public name="accessibilityActionMoveWindow" />
+ <public name="autofill" />
</public-group>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d1d406d..1ed069b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2640,6 +2640,9 @@
<!-- Item on EditText context menu. This action is used to redo a text edit operation. -->
<string name="redo">Redo</string>
+ <!-- Item on EditText context menu. This action is used to request autofill. -->
+ <string name="autofill">Autofill</string>
+
<!-- Text selection contextual mode title, displayed in the CAB. [CHAR LIMIT=20] -->
<string name="textSelectionCABTitle">Text selection</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 26d71c3..07cecbc 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2841,11 +2841,13 @@
<java-symbol type="dimen" name="autofill_fill_min_margin" />
<java-symbol type="layout" name="autofill_save"/>
<java-symbol type="layout" name="autofill_dataset_picker"/>
+ <java-symbol type="id" name="autofill" />
<java-symbol type="id" name="autofill_save_title" />
<java-symbol type="id" name="autofill_save_subtitle" />
<java-symbol type="id" name="autofill_save_no" />
<java-symbol type="id" name="autofill_save_yes" />
<java-symbol type="id" name="autofill_save_close" />
+ <java-symbol type="string" name="autofill" />
<java-symbol type="string" name="autofill_save_title" />
<java-symbol type="string" name="autofill_save_title_with_type" />
<java-symbol type="string" name="autofill_save_yes" />
diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java
index 704f0ce..5973d3e 100644
--- a/drm/java/android/drm/DrmManagerClient.java
+++ b/drm/java/android/drm/DrmManagerClient.java
@@ -275,6 +275,10 @@
* the {@link DrmManagerClient} object is no longer needed in your
* application. After this method is called, {@link DrmManagerClient} is no
* longer usable since it has lost all of its required resource.
+ *
+ * This method was added in API 24. In API versions 16 through 23, release()
+ * should be called instead. There is no need to do anything for API
+ * versions prior to 16.
*/
@Override
public void close() {
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 95577ca..3416401 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -24,6 +24,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.fonts.FontRequest;
import android.graphics.fonts.FontResult;
@@ -88,7 +89,7 @@
@GuardedBy("sLock")
private static FontsContract sFontsContract;
@GuardedBy("sLock")
- private static Handler mHandler;
+ private static Handler sHandler;
/**
* Cache for Typeface objects dynamically loaded from assets. Currently max size is 16.
@@ -226,6 +227,20 @@
}
/**
+ * Set the application context so we can generate font requests from the provider. This should
+ * be called from ActivityThread when the application binds, as we preload fonts.
+ * @hide
+ */
+ public static void setApplicationContext(Context context) {
+ synchronized (sLock) {
+ if (sFontsContract == null) {
+ sFontsContract = new FontsContract(context);
+ sHandler = new Handler();
+ }
+ }
+ }
+
+ /**
* Create a typeface object given a font request. The font will be asynchronously fetched,
* therefore the result is delivered to the given callback. See {@link FontRequest}.
* Only one of the methods in callback will be invoked, depending on whether the request
@@ -241,18 +256,17 @@
Typeface cachedTypeface = findFromCache(
request.getProviderAuthority(), request.getQuery());
if (cachedTypeface != null) {
- mHandler.post(() -> callback.onTypefaceRetrieved(cachedTypeface));
+ sHandler.post(() -> callback.onTypefaceRetrieved(cachedTypeface));
return;
}
synchronized (sLock) {
if (sFontsContract == null) {
- sFontsContract = new FontsContract();
- mHandler = new Handler();
+ throw new RuntimeException("Context not initialized, can't query provider");
}
final ResultReceiver receiver = new ResultReceiver(null) {
@Override
public void onReceiveResult(int resultCode, Bundle resultData) {
- mHandler.post(() -> receiveResult(request, callback, resultCode, resultData));
+ sHandler.post(() -> receiveResult(request, callback, resultCode, resultData));
}
};
sFontsContract.getFont(request, receiver);
diff --git a/libs/common_time/Android.mk b/libs/common_time/Android.mk
index 1fec504..636f057 100644
--- a/libs/common_time/Android.mk
+++ b/libs/common_time/Android.mk
@@ -15,7 +15,8 @@
clock_recovery.cpp \
common_clock.cpp \
main.cpp \
- utils.cpp
+ utils.cpp \
+ LinearTransform.cpp
# Uncomment to enable vesbose logging and debug service.
#TIME_SERVICE_DEBUG=true
diff --git a/libs/common_time/LinearTransform.cpp b/libs/common_time/LinearTransform.cpp
new file mode 100644
index 0000000..6730855
--- /dev/null
+++ b/libs/common_time/LinearTransform.cpp
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#define __STDC_LIMIT_MACROS
+
+#include "LinearTransform.h"
+#include <assert.h>
+
+
+// disable sanitize as these functions may intentionally overflow (see comments below).
+// the ifdef can be removed when host builds use clang.
+#if defined(__clang__)
+#define ATTRIBUTE_NO_SANITIZE_INTEGER __attribute__((no_sanitize("integer")))
+#else
+#define ATTRIBUTE_NO_SANITIZE_INTEGER
+#endif
+
+namespace android {
+
+// sanitize failure with T = int32_t and x = 0x80000000
+template<class T>
+ATTRIBUTE_NO_SANITIZE_INTEGER
+static inline T ABS(T x) { return (x < 0) ? -x : x; }
+
+// Static math methods involving linear transformations
+// remote sanitize failure on overflow case.
+ATTRIBUTE_NO_SANITIZE_INTEGER
+static bool scale_u64_to_u64(
+ uint64_t val,
+ uint32_t N,
+ uint32_t D,
+ uint64_t* res,
+ bool round_up_not_down) {
+ uint64_t tmp1, tmp2;
+ uint32_t r;
+
+ assert(res);
+ assert(D);
+
+ // Let U32(X) denote a uint32_t containing the upper 32 bits of a 64 bit
+ // integer X.
+ // Let L32(X) denote a uint32_t containing the lower 32 bits of a 64 bit
+ // integer X.
+ // Let X[A, B] with A <= B denote bits A through B of the integer X.
+ // Let (A | B) denote the concatination of two 32 bit ints, A and B.
+ // IOW X = (A | B) => U32(X) == A && L32(X) == B
+ //
+ // compute M = val * N (a 96 bit int)
+ // ---------------------------------
+ // tmp2 = U32(val) * N (a 64 bit int)
+ // tmp1 = L32(val) * N (a 64 bit int)
+ // which means
+ // M = val * N = (tmp2 << 32) + tmp1
+ tmp2 = (val >> 32) * N;
+ tmp1 = (val & UINT32_MAX) * N;
+
+ // compute M[32, 95]
+ // tmp2 = tmp2 + U32(tmp1)
+ // = (U32(val) * N) + U32(L32(val) * N)
+ // = M[32, 95]
+ tmp2 += tmp1 >> 32;
+
+ // if M[64, 95] >= D, then M/D has bits > 63 set and we have
+ // an overflow.
+ if ((tmp2 >> 32) >= D) {
+ *res = UINT64_MAX;
+ return false;
+ }
+
+ // Divide. Going in we know
+ // tmp2 = M[32, 95]
+ // U32(tmp2) < D
+ r = tmp2 % D;
+ tmp2 /= D;
+
+ // At this point
+ // tmp1 = L32(val) * N
+ // tmp2 = M[32, 95] / D
+ // = (M / D)[32, 95]
+ // r = M[32, 95] % D
+ // U32(tmp2) = 0
+ //
+ // compute tmp1 = (r | M[0, 31])
+ tmp1 = (tmp1 & UINT32_MAX) | ((uint64_t)r << 32);
+
+ // Divide again. Keep the remainder around in order to round properly.
+ r = tmp1 % D;
+ tmp1 /= D;
+
+ // At this point
+ // tmp2 = (M / D)[32, 95]
+ // tmp1 = (M / D)[ 0, 31]
+ // r = M % D
+ // U32(tmp1) = 0
+ // U32(tmp2) = 0
+
+ // Pack the result and deal with the round-up case (As well as the
+ // remote possiblility over overflow in such a case).
+ *res = (tmp2 << 32) | tmp1;
+ if (r && round_up_not_down) {
+ ++(*res);
+ if (!(*res)) {
+ *res = UINT64_MAX;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// at least one known sanitize failure (see comment below)
+ATTRIBUTE_NO_SANITIZE_INTEGER
+static bool linear_transform_s64_to_s64(
+ int64_t val,
+ int64_t basis1,
+ int32_t N,
+ uint32_t D,
+ bool invert_frac,
+ int64_t basis2,
+ int64_t* out) {
+ uint64_t scaled, res;
+ uint64_t abs_val;
+ bool is_neg;
+
+ if (!out)
+ return false;
+
+ // Compute abs(val - basis_64). Keep track of whether or not this delta
+ // will be negative after the scale opertaion.
+ if (val < basis1) {
+ is_neg = true;
+ abs_val = basis1 - val;
+ } else {
+ is_neg = false;
+ abs_val = val - basis1;
+ }
+
+ if (N < 0)
+ is_neg = !is_neg;
+
+ if (!scale_u64_to_u64(abs_val,
+ invert_frac ? D : ABS(N),
+ invert_frac ? ABS(N) : D,
+ &scaled,
+ is_neg))
+ return false; // overflow/undeflow
+
+ // if scaled is >= 0x8000<etc>, then we are going to overflow or
+ // underflow unless ABS(basis2) is large enough to pull us back into the
+ // non-overflow/underflow region.
+ if (scaled & INT64_MIN) {
+ if (is_neg && (basis2 < 0))
+ return false; // certain underflow
+
+ if (!is_neg && (basis2 >= 0))
+ return false; // certain overflow
+
+ if (ABS(basis2) <= static_cast<int64_t>(scaled & INT64_MAX))
+ return false; // not enough
+
+ // Looks like we are OK
+ *out = (is_neg ? (-scaled) : scaled) + basis2;
+ } else {
+ // Scaled fits within signed bounds, so we just need to check for
+ // over/underflow for two signed integers. Basically, if both scaled
+ // and basis2 have the same sign bit, and the result has a different
+ // sign bit, then we have under/overflow. An easy way to compute this
+ // is
+ // (scaled_signbit XNOR basis_signbit) &&
+ // (scaled_signbit XOR res_signbit)
+ // ==
+ // (scaled_signbit XOR basis_signbit XOR 1) &&
+ // (scaled_signbit XOR res_signbit)
+
+ if (is_neg)
+ scaled = -scaled; // known sanitize failure
+ res = scaled + basis2;
+
+ if ((scaled ^ basis2 ^ INT64_MIN) & (scaled ^ res) & INT64_MIN)
+ return false;
+
+ *out = res;
+ }
+
+ return true;
+}
+
+bool LinearTransform::doForwardTransform(int64_t a_in, int64_t* b_out) const {
+ if (0 == a_to_b_denom)
+ return false;
+
+ return linear_transform_s64_to_s64(a_in,
+ a_zero,
+ a_to_b_numer,
+ a_to_b_denom,
+ false,
+ b_zero,
+ b_out);
+}
+
+bool LinearTransform::doReverseTransform(int64_t b_in, int64_t* a_out) const {
+ if (0 == a_to_b_numer)
+ return false;
+
+ return linear_transform_s64_to_s64(b_in,
+ b_zero,
+ a_to_b_numer,
+ a_to_b_denom,
+ true,
+ a_zero,
+ a_out);
+}
+
+template <class T> void LinearTransform::reduce(T* N, T* D) {
+ T a, b;
+ if (!N || !D || !(*D)) {
+ assert(false);
+ return;
+ }
+
+ a = *N;
+ b = *D;
+
+ if (a == 0) {
+ *D = 1;
+ return;
+ }
+
+ // This implements Euclid's method to find GCD.
+ if (a < b) {
+ T tmp = a;
+ a = b;
+ b = tmp;
+ }
+
+ while (1) {
+ // a is now the greater of the two.
+ const T remainder = a % b;
+ if (remainder == 0) {
+ *N /= b;
+ *D /= b;
+ return;
+ }
+ // by swapping remainder and b, we are guaranteeing that a is
+ // still the greater of the two upon entrance to the loop.
+ a = b;
+ b = remainder;
+ }
+};
+
+template void LinearTransform::reduce<uint64_t>(uint64_t* N, uint64_t* D);
+template void LinearTransform::reduce<uint32_t>(uint32_t* N, uint32_t* D);
+
+// sanitize failure if *N = 0x80000000
+ATTRIBUTE_NO_SANITIZE_INTEGER
+void LinearTransform::reduce(int32_t* N, uint32_t* D) {
+ if (N && D && *D) {
+ if (*N < 0) {
+ *N = -(*N);
+ reduce(reinterpret_cast<uint32_t*>(N), D);
+ *N = -(*N);
+ } else {
+ reduce(reinterpret_cast<uint32_t*>(N), D);
+ }
+ }
+}
+
+} // namespace android
diff --git a/libs/common_time/LinearTransform.h b/libs/common_time/LinearTransform.h
new file mode 100644
index 0000000..bf6ab8e
--- /dev/null
+++ b/libs/common_time/LinearTransform.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef _LINEAR_TRANSFORM_H
+#define _LINEAR_TRANSFORM_H
+
+#include <stdint.h>
+
+namespace android {
+
+// LinearTransform defines a structure which hold the definition of a
+// transformation from single dimensional coordinate system A into coordinate
+// system B (and back again). Values in A and in B are 64 bit, the linear
+// scale factor is expressed as a rational number using two 32 bit values.
+//
+// Specifically, let
+// f(a) = b
+// F(b) = f^-1(b) = a
+// then
+//
+// f(a) = (((a - a_zero) * a_to_b_numer) / a_to_b_denom) + b_zero;
+//
+// and
+//
+// F(b) = (((b - b_zero) * a_to_b_denom) / a_to_b_numer) + a_zero;
+//
+struct LinearTransform {
+ int64_t a_zero;
+ int64_t b_zero;
+ int32_t a_to_b_numer;
+ uint32_t a_to_b_denom;
+
+ // Transform from A->B
+ // Returns true on success, or false in the case of a singularity or an
+ // overflow.
+ bool doForwardTransform(int64_t a_in, int64_t* b_out) const;
+
+ // Transform from B->A
+ // Returns true on success, or false in the case of a singularity or an
+ // overflow.
+ bool doReverseTransform(int64_t b_in, int64_t* a_out) const;
+
+ // Helpers which will reduce the fraction N/D using Euclid's method.
+ template <class T> static void reduce(T* N, T* D);
+ static void reduce(int32_t* N, uint32_t* D);
+};
+
+
+}
+
+#endif // _LINEAR_TRANSFORM_H
diff --git a/libs/common_time/clock_recovery.h b/libs/common_time/clock_recovery.h
index 278a75e..8066a39 100644
--- a/libs/common_time/clock_recovery.h
+++ b/libs/common_time/clock_recovery.h
@@ -19,9 +19,10 @@
#include <stdint.h>
#include <common_time/ICommonClock.h>
-#include <utils/LinearTransform.h>
#include <utils/threads.h>
+#include "LinearTransform.h"
+
#ifdef TIME_SERVICE_DEBUG
#include "diag_thread.h"
#endif
diff --git a/libs/common_time/common_clock.cpp b/libs/common_time/common_clock.cpp
index ee326e1..aed52f1 100644
--- a/libs/common_time/common_clock.cpp
+++ b/libs/common_time/common_clock.cpp
@@ -23,7 +23,6 @@
#include <stdint.h>
#include <utils/Errors.h>
-#include <utils/LinearTransform.h>
#include "common_clock.h"
diff --git a/libs/common_time/common_clock.h b/libs/common_time/common_clock.h
index b786fdc..5e4e5f5 100644
--- a/libs/common_time/common_clock.h
+++ b/libs/common_time/common_clock.h
@@ -20,9 +20,10 @@
#include <stdint.h>
#include <utils/Errors.h>
-#include <utils/LinearTransform.h>
#include <utils/threads.h>
+#include "LinearTransform.h"
+
namespace android {
class CommonClock {
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index d264127..13a22b4 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -23,6 +23,7 @@
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;
@@ -3186,59 +3187,22 @@
public native final String getName();
/**
- * Returns Analytics/Metrics data about the current content being
+ * Return Metrics data about the current codec instance.
*
- * @return a Bundle containing the set of attributes and values available
- * for the media being handled by this instance of MediaCodec
+ * @return a MediaMetricsSet 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}.
*
- * <table style="width: 0%">
- * <thead>
- * <tr>
- * <th>Key</th>
- * <th>Type</th>
- * <th>Description</th>
- * </tr>
- * </thead>
- * <tbody>
- * <tr>
- * <td>{@code "codec"}</td>
- * <td>String</td>
- * <td>Identifies the particular codec in use</td>
- * </tr><tr>
- * <td>{@code "mime"}</td>
- * <td>String</td>
- * <td>Mime type of the media being encoded/decoded</td>
- * </tr><tr>
- * <td>{@code "mode"}</td>
- * <td>String</td>
- * <td>"Audio" or "Video"</td>
- * </tr><tr>
- * <td>{@code "secure"}</td>
- * <td>Integer</td>
- * <td>Indicates whether the code is operating on secure content and
- * may also use capabilities in android.media.MediaCrypto</td>
- * </tr><tr>
- * <td>{@code "height"}</td>
- * <td>Integer</td>
- * <td>Height (pixels); valid only when mode=video</td>
- * </tr><tr>
- * <td>{@code "width"}</td>
- * <td>Integer</td>
- * <td>Width (pixels); valid only when mode=video</td>
- * </tr><tr>
- * <td>{@code "rotation"}</td>
- * <td>Integer</td>
- * <td>rotation (degrees) to orient the video onto the target surface;
- * valid only when mode=video. Note there may be additional
- * rotations applied when the surface is mapped to the screen.</td>
- * </tr>
- * </tbody>
- * </table>
- *
- * Additional fields specific to individual codecs will also appear in
+ * Additional vendor-specific fields may also be present in
* the return value.
*/
- public native Bundle getMetrics();
+ public MediaMetricsSet getMetrics() {
+ Bundle bundle = native_getMetrics();
+ MediaMetricsSet mSet = new MediaMetricsSet(bundle);
+ return mSet;
+ }
+
+ private native Bundle native_getMetrics();
/**
* Change a video encoder's target bitrate on the fly. The value is an
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index b9e409d..2ed6668 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -25,6 +25,7 @@
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;
@@ -651,41 +652,24 @@
public native boolean hasCacheReachedEndOfStream();
/**
- * Returns Analytics/Metrics data about the current media container.
+ * Return Metrics data about the current media container.
*
- * @return the set of keys and values available for the media being
- * handled by this instance of MediaExtractor
+ * @return a MediaMetricsSet 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}.
*
- * <table style="width: 0%">
- * <thead>
- * <tr>
- * <th>Key</th>
- * <th>Type</th>
- * <th>Description</th>
- * </tr>
- * </thead>
- * <tbody>
- * <tr>
- * <td>{@code "fmt"}</td>
- * <td>String</td>
- * <td>The container format (which determines the handler)</td>
- * </tr><tr>
- * <td>{@code "mime"}</td>
- * <td>String</td>
- * <td>Mime type of the container.</td>
- * </tr><tr>
- * <td>{@code "ntrk"}</td>
- * <td>Integer</td>
- * <td>Number of tracks in the container</td>
- * </tr>
- * </tbody>
- * </table>
- *
- * Additional fields specific to individual codecs will also appear in
+ * Additional vendor-specific fields may also be present in
* the return value.
*/
- public native Bundle getMetrics();
+ public MediaMetricsSet getMetrics() {
+ Bundle bundle = native_getMetrics();
+ MediaMetricsSet mSet = new MediaMetricsSet(bundle);
+ return mSet;
+ }
+
+ private native Bundle native_getMetrics();
private static native final void native_init();
private native final void native_setup();
diff --git a/media/java/android/media/MediaMetricsSet.java b/media/java/android/media/MediaMetricsSet.java
new file mode 100644
index 0000000..5ecbee2
--- /dev/null
+++ b/media/java/android/media/MediaMetricsSet.java
@@ -0,0 +1,491 @@
+/*
+ * 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 b85c911..1ee05b8 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -49,6 +49,7 @@
import android.media.BufferingParams;
import android.media.MediaDrm;
import android.media.MediaFormat;
+import android.media.MediaMetricsSet;
import android.media.MediaTimeProvider;
import android.media.PlaybackParams;
import android.media.SubtitleController;
@@ -1494,70 +1495,22 @@
public native int getVideoHeight();
/**
- * Returns Analytics/Metrics data about the current video in this player.
+ * Return Metrics data about the current player.
*
- * @return the a map of attributes and values available for this video
- * player or null if no metrics are available.
+ * @return a MediaMetricsSet 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}.
*
- * <table style="width: 0%">
- * <thead>
- * <tr>
- * <th>Key</th>
- * <th>Type</th>
- * <th>Description</th>
- * </tr>
- * </thead>
- * <tbody>
- * <tr>
- * <td>{@code "video/codec"}</td>
- * <td>String</td>
- * <td>Identifies the video codec in use</td>
- * </tr><tr>
- * <td>{@code "video/mime"}</td>
- * <td>String</td>
- * <td>Mime type of the video being encoded/decoded</td>
- * </tr><tr>
- * <td>{@code "audio/codec"}</td>
- * <td>String</td>
- * <td>Identifies the audio codec in use</td>
- * </tr><tr>
- * <td>{@code "audio/mime"}</td>
- * <td>String</td>
- * <td>Mime type of the audio being encoded/decoded</td>
- * </tr><tr>
- * <td>{@code "ht"}</td>
- * <td>Integer</td>
- * <td>Height (pixels); valid only when mode=video</td>
- * </tr><tr>
- * <td>{@code "wid"}</td>
- * <td>Integer</td>
- * <td>Width (pixels); valid only when mode=video</td>
- * </tr><tr>
- * <td>{@code "frame"}</td>
- * <td>Integer</td>
- * <td>Number of decoded video frames sent to the display</td>
- * </tr><tr>
- * <td>{@code "dropped"}</td>
- * <td>Integer</td>
- * <td>Number of decoded video frames that were not sent to display.
- * These frames were dropped by the player.</td>
- * </tr><tr>
- * <td>{@code "durationMs"}</td>
- * <td>Integer</td>
- * <td>The length of the media being played (in ms), e.g. "This video lasts for 30000 milliseconds". </td>
- * </tr><tr>
- * <td>{@code "playingMs"}</td>
- * <td>Integer</td>
- * <td>The time the media has been played (in ms). If you watch a
- * 30 second twice through, this will report 60000 ms.</td>
- * </tr>
- * </tbody>
- * </table>
- *
- * Additional fields specific to individual codecs will also appear in
+ * Additional vendor-specific fields may also be present in
* the return value.
*/
- public native Bundle getMetrics();
+ public MediaMetricsSet getMetrics() {
+ Bundle bundle = native_getMetrics();
+ MediaMetricsSet mSet = new MediaMetricsSet(bundle);
+ return mSet;
+ }
+
+ private native Bundle native_getMetrics();
/**
* Checks whether the MediaPlayer is playing.
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 075a84f..cdc1d60 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -20,6 +20,7 @@
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;
@@ -1259,91 +1260,23 @@
private native void setParameter(String nameValuePair);
/**
- * Returns Metrics data about the current media container.
+ * Return Metrics data about the current Mediarecorder instance.
*
- * @return the set of keys and values available for the media being
- * handled by this instance of MediaExtractor. The keys, data types,
- * and meaning are described in the following table.
+ * @return a MediaMetricsSet 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}.
*
- * <table style="width: 0%">
- * <thead>
- * <tr>
- * <th>Key</th>
- * <th>Type</th>
- * <th>Description</th>
- * </tr>
- * </thead>
- * <tbody>
- * <tr>
- * <td>{@code "ht"}</td>
- * <td>Integer</td>
- * <td>Height of the recorded video (pixels)</td>
- * </tr><tr>
- * <td>{@code "wid"}</td>
- * <td>Integer</td>
- * <td>Width of the recorded video (pixels)</td>
- * </tr><tr>
- * <td>{@code "frame-rate"}</td>
- * <td>Integer</td>
- * <td>Framerate of captured Video (frames per second)</td>
- * </tr><tr>
- * <td>{@code "video-bitrate"}</td>
- * <td>Integer</td>
- * <td>Bit rate of encoded video (bits per second)</td>
- * </tr><tr>
- * <td>{@code "video-iframe-interval"}</td>
- * <td>Integer</td>
- * <td>Interval between encoded IFrames (seconds)</td>
- * </tr><tr>
- * <td>{@code "video-timescale"}</td>
- * <td>Integer</td>
- * <td></td>
- * </tr><tr>
- * <td>{@code "video-encoder-profile"}</td>
- * <td>Integer</td>
- * <td>Video Encoder Profile, as defined in OpenMAX IL</td>
- * </tr><tr>
- * <td>{@code "video-encoder-level"}</td>
- * <td>Integer</td>
- * <td>Video Encoder Level, as defined in OpenMAX IL</td>
- * </tr><tr>
- * <td>{@code "audio-bitrate"}</td>
- * <td>Integer</td>
- * <td>Bitrate of encoded audio (bits per second)</td>
- * </tr><tr>
- * <td>{@code "audio-samplerate"}</td>
- * <td>Integer</td>
- * <td></td>
- * </tr><tr>
- * <td>{@code "audio-channels"}</td>
- * <td>Integer</td>
- * <td>Number of Audio Channels Captured</td>
- * </tr><tr>
- * <td>{@code "audio-timescale"}</td>
- * <td>Integer</td>
- * <td></td>
- * </tr><tr>
- * <td>{@code "movie-timescale"}</td>
- * <td>Integer</td>
- * <td></td>
- * </tr><tr>
- * <td>{@code "movie-timescale"}</td>
- * <td>Integer</td>
- * <td></td>
- * </tr><tr>
- * <td>{@code "capture-fps"}</td>
- * <td>Integer</td>
- * <td></td>
- * </tr><tr>
- * <td>{@code "rotation"}</td>
- * <td>Integer</td>
- * <td>Orientation of the Video (degrees)</td>
- * </tr>
- * </tbody>
- * </table>
+ * 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 native Bundle getMetrics();
+ private native Bundle native_getMetrics();
@Override
protected void finalize() { native_finalize(); }
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 293e5dd..a8dd313 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -624,7 +624,7 @@
return OK;
}
-status_t JMediaCodec::getMetrics(JNIEnv *, Parcel *reply) const {
+status_t JMediaCodec::getMetrics(JNIEnv *, MediaAnalyticsItem * &reply) const {
status_t status = mCodec->getMetrics(reply);
return status;
@@ -1666,9 +1666,9 @@
}
static jobject
-android_media_MediaCodec_getMetrics(JNIEnv *env, jobject thiz)
+android_media_MediaCodec_native_getMetrics(JNIEnv *env, jobject thiz)
{
- ALOGV("android_media_MediaCodec_getMetrics");
+ ALOGV("android_media_MediaCodec_native_getMetrics");
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL ) {
@@ -1677,16 +1677,14 @@
}
// get what we have for the metrics from the codec
- Parcel reply;
- status_t err = codec->getMetrics(env, &reply);
+ MediaAnalyticsItem *item = NULL;
+
+ status_t err = codec->getMetrics(env, item);
if (err != OK) {
ALOGE("getMetrics failed");
return (jobject) NULL;
}
- // build and return the Bundle
- MediaAnalyticsItem *item = new MediaAnalyticsItem;
- item->readFromParcel(reply);
jobject mybundle = MediaMetricsJNI::writeMetricsToBundle(env, item, NULL);
// housekeeping
@@ -2004,8 +2002,8 @@
{ "getName", "()Ljava/lang/String;",
(void *)android_media_MediaCodec_getName },
- { "getMetrics", "()Landroid/os/Bundle;",
- (void *)android_media_MediaCodec_getMetrics},
+ { "native_getMetrics", "()Landroid/os/Bundle;",
+ (void *)android_media_MediaCodec_native_getMetrics},
{ "setParameters", "([Ljava/lang/String;[Ljava/lang/Object;)V",
(void *)android_media_MediaCodec_setParameters },
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index a8c76c5..c9a1700 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -19,6 +19,7 @@
#include "jni.h"
+#include <media/MediaAnalyticsItem.h>
#include <media/hardware/CryptoAPI.h>
#include <media/stagefright/foundation/ABase.h>
#include <media/stagefright/foundation/AHandler.h>
@@ -116,7 +117,7 @@
status_t getName(JNIEnv *env, jstring *name) const;
- status_t getMetrics(JNIEnv *env, Parcel *reply) const;
+ status_t getMetrics(JNIEnv *env, MediaAnalyticsItem * &reply) const;
status_t setParameters(const sp<AMessage> ¶ms);
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 3c33493..c2cfed9 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -811,9 +811,9 @@
}
static jobject
-android_media_MediaExtractor_getMetrics(JNIEnv * env, jobject thiz)
+android_media_MediaExtractor_native_getMetrics(JNIEnv * env, jobject thiz)
{
- ALOGV("android_media_MediaExtractor_getMetrics");
+ ALOGV("android_media_MediaExtractor_native_getMetrics");
sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
if (extractor == NULL ) {
@@ -905,8 +905,8 @@
{ "hasCacheReachedEndOfStream", "()Z",
(void *)android_media_MediaExtractor_hasCacheReachedEOS },
- {"getMetrics", "()Landroid/os/Bundle;",
- (void *)android_media_MediaExtractor_getMetrics},
+ {"native_getMetrics", "()Landroid/os/Bundle;",
+ (void *)android_media_MediaExtractor_native_getMetrics},
};
int register_android_media_MediaExtractor(JNIEnv *env) {
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 27724a1..1b52cf5 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -708,7 +708,7 @@
}
static jobject
-android_media_MediaPlayer_getMetrics(JNIEnv *env, jobject thiz)
+android_media_MediaPlayer_native_getMetrics(JNIEnv *env, jobject thiz)
{
sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
if (mp == NULL ) {
@@ -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},
- {"getMetrics", "()Landroid/os/Bundle;", (void *)android_media_MediaPlayer_getMetrics},
+ {"native_getMetrics", "()Landroid/os/Bundle;", (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 77544eb..7a63e00 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -628,9 +628,9 @@
}
static jobject
-android_media_MediaRecorder_getMetrics(JNIEnv *env, jobject thiz)
+android_media_MediaRecorder_native_getMetrics(JNIEnv *env, jobject thiz)
{
- ALOGV("android_media_MediaRecorder_getMetrics");
+ ALOGV("android_media_MediaRecorder_native_getMetrics");
sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
if (mr == NULL) {
@@ -688,7 +688,7 @@
{"native_finalize", "()V", (void *)android_media_MediaRecorder_native_finalize},
{"native_setInputSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaRecorder_setInputSurface },
- {"getMetrics", "()Landroid/os/Bundle;", (void *)android_media_MediaRecorder_getMetrics},
+ {"native_getMetrics", "()Landroid/os/Bundle;", (void *)android_media_MediaRecorder_native_getMetrics},
};
// This function only registers the native methods, and is called from
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index f77d466..c64574f 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -422,11 +422,11 @@
<!-- Setting Checkbox title whether to enable WiFi Verbose Logging. [CHAR LIMIT=40] -->
<string name="wifi_verbose_logging">Enable Wi\u2011Fi Verbose Logging</string>
<!-- Setting Checkbox title whether to enable WiFi Aggressive Handover. [CHAR LIMIT=40] -->
- <string name="wifi_aggressive_handover">Aggressive Wi\u2011Fi to Cellular handover</string>
+ <string name="wifi_aggressive_handover">Aggressive Wi\u2011Fi to mobile handover</string>
<!-- Setting Checkbox title whether to enable WiFi Scanning in the presence of traffic. [CHAR LIMIT=80] -->
<string name="wifi_allow_scan_with_traffic">Always allow Wi\u2011Fi Roam Scans</string>
- <!-- Setting Checkbox title whether to always keep cellular data active. [CHAR LIMIT=80] -->
- <string name="mobile_data_always_on">Cellular data always active</string>
+ <!-- Setting Checkbox title whether to always keep mobile data active. [CHAR LIMIT=80] -->
+ <string name="mobile_data_always_on">Mobile data always active</string>
<!-- Setting Checkbox title for disabling Bluetooth absolute volume -->
<string name="bluetooth_disable_absolute_volume">Disable absolute volume</string>
@@ -463,7 +463,7 @@
<!-- Setting Checkbox summary whether to enable Wifi verbose Logging [CHAR LIMIT=80] -->
<string name="wifi_verbose_logging_summary">Increase Wi\u2011Fi logging level, show per SSID RSSI in Wi\u2011Fi Picker</string>
<!-- Setting Checkbox summary whether to enable Wifi aggressive handover [CHAR LIMIT=130] -->
- <string name="wifi_aggressive_handover_summary">When enabled, Wi\u2011Fi will be more aggressive in handing over the data connection to Cellular, when Wi\u2011Fi signal is low</string>
+ <string name="wifi_aggressive_handover_summary">When enabled, Wi\u2011Fi will be more aggressive in handing over the data connection to mobile, when Wi\u2011Fi signal is low</string>
<!-- Setting Checkbox summary whether to always allow WiFi Roam Scans [CHAR LIMIT=130] -->
<string name="wifi_allow_scan_with_traffic_summary">Allow/Disallow Wi\u2011Fi Roam Scans based on the amount of data traffic present at the interface</string>
<!-- UI debug setting: limit size of Android logger buffers -->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index af464c6..5db5498 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -136,12 +136,7 @@
if (channel.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
channelNameText = mContext.getString(R.string.notification_header_default_channel);
} else {
- if (info != null && channel.getNameResId() != 0) {
- channelNameText = pm.getText(pkg, channel.getNameResId(), info);
- }
- if (channel.getName() != null) {
- channelNameText = channel.getName();
- }
+ channelNameText = channel.getName();
}
((TextView) findViewById(R.id.pkgname)).setText(appName);
((TextView) findViewById(R.id.channel_name)).setText(channelNameText);
@@ -154,12 +149,7 @@
iNotificationManager.getNotificationChannelGroupForPackage(
channel.getGroup(), pkg, appUid);
if (notificationChannelGroup != null) {
- if (info != null && notificationChannelGroup.getNameResId() != 0) {
- groupName = pm.getText(pkg, notificationChannelGroup.getNameResId(), info);
- }
- if (notificationChannelGroup.getName() != null) {
- groupName = notificationChannelGroup.getName();
- }
+ groupName = notificationChannelGroup.getName();
}
} catch (RemoteException e) {
Log.e(TAG, e.toString());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
index a87b50a..d6c080a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
@@ -129,6 +129,7 @@
public void notifyKeyguardDoneFading() {
mKeyguardFadingAway = false;
+ mKeyguardGoingAway = false;
notifyKeyguardChanged();
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
index 5df3beb..cd85a76 100644
--- a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
+++ b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
@@ -38,19 +38,19 @@
nm.createNotificationChannels(Arrays.asList(
new NotificationChannel(
ALERTS,
- R.string.notification_channel_alerts,
+ context.getString(R.string.notification_channel_alerts),
NotificationManager.IMPORTANCE_HIGH),
new NotificationChannel(
SCREENSHOTS,
- R.string.notification_channel_screenshot,
+ context.getString(R.string.notification_channel_screenshot),
NotificationManager.IMPORTANCE_LOW),
new NotificationChannel(
GENERAL,
- R.string.notification_channel_general,
+ context.getString(R.string.notification_channel_general),
NotificationManager.IMPORTANCE_MIN),
new NotificationChannel(
STORAGE,
- R.string.notification_channel_storage,
+ context.getString(R.string.notification_channel_storage),
isTv(context)
? NotificationManager.IMPORTANCE_DEFAULT
: NotificationManager.IMPORTANCE_LOW)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index 5b9270d..726300f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -161,27 +161,6 @@
}
@Test
- public void testBindNotification_SetsGroupName_resId() throws Exception {
- when(mMockPackageManager.getText(eq(TEST_PACKAGE_NAME),
- eq(R.string.legacy_vpn_name), anyObject())).thenReturn(
- getContext().getString(R.string.legacy_vpn_name));
- mNotificationChannel.setGroup("test_group_id");
- final NotificationChannelGroup notificationChannelGroup =
- new NotificationChannelGroup("test_group_id", R.string.legacy_vpn_name);
- when(mMockINotificationManager.getNotificationChannelGroupForPackage(
- eq("test_group_id"), eq(TEST_PACKAGE_NAME), anyInt()))
- .thenReturn(notificationChannelGroup);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null, null);
- final TextView groupNameView = (TextView) mNotificationInfo.findViewById(R.id.group_name);
- assertEquals(View.VISIBLE, groupNameView.getVisibility());
- assertEquals(mContext.getString(R.string.legacy_vpn_name), groupNameView.getText());
- final TextView groupDividerView =
- (TextView) mNotificationInfo.findViewById(R.id.pkg_group_divider);
- assertEquals(View.VISIBLE, groupDividerView.getVisibility());
- }
-
- @Test
public void testBindNotification_SetsTextChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
mMockStatusBarNotification, mNotificationChannel, null, null, null);
@@ -190,21 +169,6 @@
}
@Test
- public void testBindNotification_SetsTextChannelName_resId() throws Exception {
- when(mMockPackageManager.getText(eq(TEST_PACKAGE_NAME),
- eq(R.string.notification_menu_accessibility), anyObject())).thenReturn(
- getContext().getString(R.string.notification_menu_accessibility));
- NotificationChannel notificationChannelResId = new NotificationChannel(
- TEST_CHANNEL, R.string.notification_menu_accessibility,
- NotificationManager.IMPORTANCE_LOW);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, notificationChannelResId, null, null, null);
- final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
- assertEquals(getContext().getString(R.string.notification_menu_accessibility),
- textView.getText());
- }
-
- @Test
public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index a372f95..af1193d 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -316,13 +316,13 @@
@Override
public void startSession(IBinder activityToken, IBinder windowToken, IBinder appCallback,
AutofillId autofillId, Rect bounds, AutofillValue value, int userId,
- boolean hasCallback) {
+ boolean hasCallback, int flags) {
// TODO(b/33197203): make sure it's called by resumed / focused activity
synchronized (mLock) {
final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
service.startSessionLocked(activityToken, windowToken, appCallback,
- autofillId, bounds, value, hasCallback);
+ autofillId, bounds, value, hasCallback, flags);
}
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 4786cbe..3e5ad82 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -74,7 +74,6 @@
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;
@@ -171,7 +170,7 @@
structure.sanitizeForParceling(true);
// TODO(b/33197203): Need to pipe the bundle
- session.mRemoteFillService.onFillRequest(structure, null);
+ session.mRemoteFillService.onFillRequest(structure, null, session.mFlags);
}
};
@@ -286,7 +285,8 @@
}
void startSessionLocked(IBinder activityToken, IBinder windowToken, IBinder appCallbackToken,
- AutofillId autofillId, Rect bounds, AutofillValue value, boolean hasCallback) {
+ AutofillId autofillId, Rect bounds, AutofillValue value, boolean hasCallback,
+ int flags) {
if (!hasService()) {
return;
}
@@ -294,7 +294,7 @@
final String historyItem = "s=" + mInfo.getServiceInfo().packageName
+ " u=" + mUserId + " a=" + activityToken
- + " i=" + autofillId + " b=" + bounds + " hc=" + hasCallback;
+ + " i=" + autofillId + " b=" + bounds + " hc=" + hasCallback + " f=" + flags;
mRequestsHistory.log(historyItem);
// TODO(b/33197203): Handle partitioning
@@ -305,7 +305,7 @@
}
final Session newSession = createSessionByTokenLocked(activityToken,
- windowToken, appCallbackToken, hasCallback);
+ windowToken, appCallbackToken, hasCallback, flags);
newSession.updateLocked(autofillId, bounds, value, FLAG_START_SESSION);
}
@@ -338,9 +338,9 @@
}
private Session createSessionByTokenLocked(IBinder activityToken, IBinder windowToken,
- IBinder appCallbackToken, boolean hasCallback) {
+ IBinder appCallbackToken, boolean hasCallback, int flags) {
final Session newSession = new Session(mContext, activityToken,
- windowToken, appCallbackToken, hasCallback);
+ windowToken, appCallbackToken, hasCallback, flags);
mSessions.put(activityToken, newSession);
/*
@@ -630,13 +630,19 @@
*/
private boolean mHasCallback;
+ /**
+ * Flags used to start the session.
+ */
+ private int mFlags;
+
private Session(Context context, IBinder activityToken, IBinder windowToken,
- IBinder client, boolean hasCallback) {
+ IBinder client, boolean hasCallback, int flags) {
mRemoteFillService = new RemoteFillService(context,
mInfo.getServiceInfo().getComponentName(), mUserId, this);
mActivityToken = activityToken;
mWindowToken = windowToken;
mHasCallback = hasCallback;
+ mFlags = flags;
mClient = IAutoFillManagerClient.Stub.asInterface(client);
try {
@@ -856,7 +862,8 @@
} else {
if (state.mAutofillValue == null || state.mAutofillValue.isEmpty()) {
if (DEBUG) {
- Slog.d(TAG, "finishSessionLocked(): empty value for " + id );
+ Slog.d(TAG, "finishSessionLocked(): empty value for " + id + ": "
+ + state.mAutofillValue);
}
allRequiredAreNotEmpty = false;
break;
@@ -1101,6 +1108,7 @@
void dumpLocked(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken);
+ pw.print(prefix); pw.print("mFlags: "); pw.println(mFlags);
pw.print(prefix); pw.print("mCurrentResponse: "); pw.println(mCurrentResponse);
pw.print(prefix); pw.print("mAutoFilledDataset: "); pw.println(mAutoFilledDataset);
pw.print(prefix); pw.print("mCurrentViewStates: "); pw.println(mCurrentViewState);
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index 47251db..b1cc89b 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -132,9 +132,10 @@
mCallbacks.onServiceDied(this);
}
- public void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle extras) {
+ public void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle extras,
+ int flags) {
cancelScheduledUnbind();
- final PendingFillRequest request = new PendingFillRequest(structure, extras, this);
+ final PendingFillRequest request = new PendingFillRequest(structure, extras, this, flags);
mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, request).sendToTarget();
}
@@ -418,11 +419,13 @@
private final IFillCallback mCallback;
private ICancellationSignal mCancellation;
private boolean mCancelled;
+ private int mFlags;
public PendingFillRequest(AssistStructure structure,
- Bundle extras, RemoteFillService service) {
+ Bundle extras, RemoteFillService service, int flags) {
mStructure = structure;
mExtras = extras;
+ mFlags = flags;
mWeakService = new WeakReference<>(service);
mCallback = new IFillCallback.Stub() {
@Override
@@ -469,7 +472,7 @@
if (remoteService != null) {
try {
remoteService.mAutoFillService.onFillRequest(mStructure,
- mExtras, mCallback);
+ mExtras, mCallback, mFlags);
synchronized (mLock) {
mStructure = null;
mExtras = null;
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index bcee2c1b..34c73d2 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -146,6 +146,7 @@
private final LockPatternUtils mLockPatternUtils;
private final NotificationManager mNotificationManager;
private final UserManager mUserManager;
+ private final DevicePolicyManager mDevicePolicyManager;
private final IActivityManager mActivityManager;
private final KeyStore mKeyStore;
@@ -333,6 +334,10 @@
return (UserManager) mContext.getSystemService(Context.USER_SERVICE);
}
+ public DevicePolicyManager getDevicePolicyManager() {
+ return (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ }
+
public KeyStore getKeyStore() {
return KeyStore.getInstance();
}
@@ -380,6 +385,7 @@
mStorage = injector.getStorage();
mNotificationManager = injector.getNotificationManager();
mUserManager = injector.getUserManager();
+ mDevicePolicyManager = injector.getDevicePolicyManager();
mStrongAuthTracker = injector.getStrongAuthTracker();
mStrongAuthTracker.register(mStrongAuth);
@@ -2015,14 +2021,17 @@
}
}
long handle = getSyntheticPasswordHandleLocked(userId);
- AuthenticationToken auth = mSpManager.unwrapPasswordBasedSyntheticPassword(
- getGateKeeperService(), handle, savedCredential, userId).authToken;
+ AuthenticationResult authResult = mSpManager.unwrapPasswordBasedSyntheticPassword(
+ getGateKeeperService(), handle, savedCredential, userId);
+ VerifyCredentialResponse response = authResult.gkResponse;
+ AuthenticationToken auth = authResult.authToken;
if (auth != null) {
// We are performing a trusted credential change i.e. a correct existing credential
// is provided
setLockCredentialWithAuthTokenLocked(credential, credentialType, auth, userId);
mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);
- } else {
+ } else if (response != null
+ && response.getResponseCode() == VerifyCredentialResponse.RESPONSE_ERROR){
// We are performing an untrusted credential change i.e. by DevicePolicyManager.
// So provision a new SP and SID. This would invalidate existing escrow tokens.
// Still support this for now but this flow will be removed in the next release.
@@ -2031,6 +2040,10 @@
initializeSyntheticPasswordLocked(null, credential, credentialType, userId);
synchronizeUnifiedWorkChallengeForProfiles(userId, null);
mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);
+ } else /* response == null || responseCode == VerifyCredentialResponse.RESPONSE_RETRY */ {
+ Slog.w(TAG, "spBasedSetLockCredentialInternalLocked: " +
+ (response != null ? "rate limit exceeded" : "failed"));
+ return;
}
notifyActivePasswordMetricsAvailable(credential, userId);
@@ -2042,7 +2055,7 @@
if (DEBUG) Slog.d(TAG, "addEscrowToken: user=" + userId);
synchronized (mSpManager) {
enableSyntheticPasswordLocked();
- // Migrate to synthetic password based credentials if ther user has no password,
+ // Migrate to synthetic password based credentials if the user has no password,
// the token can then be activated immediately.
AuthenticationToken auth = null;
if (!isUserSecure(userId)) {
@@ -2201,22 +2214,20 @@
Slog.i(TAG, "Managed profile can have escrow token");
return;
}
- DevicePolicyManager dpm = (DevicePolicyManager)
- mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
// Devices with Device Owner should have escrow enabled on all users.
- if (dpm.getDeviceOwnerComponentOnAnyUser() != null) {
+ if (mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser() != null) {
Slog.i(TAG, "Corp-owned device can have escrow token");
return;
}
// We could also have a profile owner on the given (non-managed) user for unicorn cases
- if (dpm.getProfileOwnerAsUser(userId) != null) {
+ if (mDevicePolicyManager.getProfileOwnerAsUser(userId) != null) {
Slog.i(TAG, "User with profile owner can have escrow token");
return;
}
// If the device is yet to be provisioned (still in SUW), there is still
// a chance that Device Owner will be set on the device later, so postpone
// disabling escrow token for now.
- if (!dpm.isDeviceProvisioned()) {
+ if (!mDevicePolicyManager.isDeviceProvisioned()) {
Slog.i(TAG, "Postpone disabling escrow tokens until device is provisioned");
return;
}
diff --git a/services/core/java/com/android/server/SyntheticPasswordManager.java b/services/core/java/com/android/server/SyntheticPasswordManager.java
index 6267880..2517613 100644
--- a/services/core/java/com/android/server/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/SyntheticPasswordManager.java
@@ -526,7 +526,7 @@
* RESPONSE_OK, since user authentication failures are detected earlier when trying to
* decrypt SP.
*/
- public VerifyCredentialResponse verifyChallenge(IGateKeeperService gatekeeper,
+ public @Nullable VerifyCredentialResponse verifyChallenge(IGateKeeperService gatekeeper,
@NonNull AuthenticationToken auth, long challenge, int userId) throws RemoteException {
byte[] spHandle = loadSyntheticPasswordHandle(userId);
if (spHandle == null) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index be8aaf0..7285a4c 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1698,6 +1698,12 @@
}
@Override
+ public int getDeletedChannelCount(String pkg, int uid) {
+ enforceSystemOrSystemUI("getDeletedChannelCount");
+ return mRankingHelper.getDeletedChannelCount(pkg, uid);
+ }
+
+ @Override
public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroupsForPackage(
String pkg, int uid, boolean includeDeleted) {
checkCallerIsSystem();
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 4b1804c..e239164 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -69,7 +69,6 @@
private static final String ATT_VERSION = "version";
private static final String ATT_NAME = "name";
- private static final String ATT_NAME_RES_ID = "name_res_id";
private static final String ATT_UID = "uid";
private static final String ATT_ID = "id";
private static final String ATT_PRIORITY = "priority";
@@ -195,14 +194,9 @@
if (TAG_GROUP.equals(tagName)) {
String id = parser.getAttributeValue(null, ATT_ID);
CharSequence groupName = parser.getAttributeValue(null, ATT_NAME);
- int groupNameRes = safeInt(parser, ATT_NAME_RES_ID, 0);
if (!TextUtils.isEmpty(id)) {
- NotificationChannelGroup group = null;
- if (groupName != null) {
- group = new NotificationChannelGroup(id, groupName);
- } else {
- group = new NotificationChannelGroup(id, groupNameRes);
- }
+ NotificationChannelGroup group
+ = new NotificationChannelGroup(id, groupName);
r.groups.put(id, group);
}
}
@@ -210,19 +204,12 @@
if (TAG_CHANNEL.equals(tagName)) {
String id = parser.getAttributeValue(null, ATT_ID);
CharSequence channelName = parser.getAttributeValue(null, ATT_NAME);
- int channelNameRes = safeInt(parser, ATT_NAME_RES_ID, 0);
int channelImportance =
safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
- if (!TextUtils.isEmpty(id)) {
- NotificationChannel channel;
- if (channelName != null) {
- channel = new NotificationChannel(id, channelName,
- channelImportance);
- } else {
- channel = new NotificationChannel(id, channelNameRes,
- channelImportance);
- }
+ if (!TextUtils.isEmpty(id) && !TextUtils.isEmpty(channelName)) {
+ NotificationChannel channel = new NotificationChannel(id,
+ channelName, channelImportance);
channel.populateFromXml(parser);
r.channels.put(id, channel);
}
@@ -302,7 +289,7 @@
NotificationChannel channel;
channel = new NotificationChannel(
NotificationChannel.DEFAULT_CHANNEL_ID,
- R.string.default_notification_channel_label,
+ mContext.getString(R.string.default_notification_channel_label),
r.importance);
channel.setBypassDnd(r.priority == Notification.PRIORITY_MAX);
channel.setLockscreenVisibility(r.visibility);
@@ -482,8 +469,7 @@
Preconditions.checkNotNull(pkg);
Preconditions.checkNotNull(group);
Preconditions.checkNotNull(group.getId());
- Preconditions.checkNotNull(!TextUtils.isEmpty(group.getName())
- || group.getNameResId() != 0);
+ Preconditions.checkNotNull(!TextUtils.isEmpty(group.getName()));
Record r = getOrCreateRecord(pkg, uid);
if (r == null) {
throw new IllegalArgumentException("Invalid package");
@@ -504,8 +490,7 @@
Preconditions.checkNotNull(pkg);
Preconditions.checkNotNull(channel);
Preconditions.checkNotNull(channel.getId());
- Preconditions.checkArgument(!TextUtils.isEmpty(channel.getName())
- || channel.getNameResId() != 0);
+ Preconditions.checkArgument(!TextUtils.isEmpty(channel.getName()));
Record r = getOrCreateRecord(pkg, uid);
if (r == null) {
throw new IllegalArgumentException("Invalid package");
@@ -524,7 +509,7 @@
existing.setDeleted(false);
}
- existing.setNameResId(channel.getNameResId());
+ existing.setName(channel.getName());
MetricsLogger.action(getChannelLog(channel, pkg));
updateConfig();
@@ -781,6 +766,23 @@
return new ParceledListSlice<>(channels);
}
+ public int getDeletedChannelCount(String pkg, int uid) {
+ Preconditions.checkNotNull(pkg);
+ int deletedCount = 0;
+ Record r = getRecord(pkg, uid);
+ if (r == null) {
+ return deletedCount;
+ }
+ int N = r.channels.size();
+ for (int i = 0; i < N; i++) {
+ final NotificationChannel nc = r.channels.valueAt(i);
+ if (nc.isDeleted()) {
+ deletedCount++;
+ }
+ }
+ return deletedCount;
+ }
+
/**
* Sets importance.
*/
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 2f221df..c20ee97 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -163,9 +163,6 @@
private boolean mLastContainsShowWhenLockedWindow;
private boolean mLastContainsDismissKeyguardWindow;
- private ArrayList<WindowSurfaceController.SurfaceControlWithBackground> mSurfaceViewBackgrounds =
- new ArrayList<>();
-
ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
@@ -970,36 +967,6 @@
mService.mWindowPlacerLocked.performSurfacePlacement();
}
- void addSurfaceViewBackground(WindowSurfaceController.SurfaceControlWithBackground background) {
- mSurfaceViewBackgrounds.add(background);
- }
-
- void removeSurfaceViewBackground(WindowSurfaceController.SurfaceControlWithBackground background) {
- mSurfaceViewBackgrounds.remove(background);
- updateSurfaceViewBackgroundVisibilities();
- }
-
- // We use DimLayers behind SurfaceViews to prevent holes while resizing and creating.
- // However, we need to ensure one SurfaceView doesn't cover another when they are both placed
- // below the main app window (as traditionally a SurfaceView which is never drawn
- // to is totally translucent). So we look at all our SurfaceView backgrounds and only enable
- // the background for the SurfaceView with lowest Z order
- void updateSurfaceViewBackgroundVisibilities() {
- WindowSurfaceController.SurfaceControlWithBackground bottom = null;
- int bottomLayer = Integer.MAX_VALUE;
- for (int i = 0; i < mSurfaceViewBackgrounds.size(); i++) {
- WindowSurfaceController.SurfaceControlWithBackground sc = mSurfaceViewBackgrounds.get(i);
- if (sc.mVisible && sc.mLayer < bottomLayer) {
- bottomLayer = sc.mLayer;
- bottom = sc;
- }
- }
- for (int i = 0; i < mSurfaceViewBackgrounds.size(); i++) {
- WindowSurfaceController.SurfaceControlWithBackground sc = mSurfaceViewBackgrounds.get(i);
- sc.updateBackgroundVisibility(sc != bottom);
- }
- }
-
void resetJustMovedInStack() {
for (int i = mChildren.size() - 1; i >= 0; i--) {
(mChildren.get(i)).resetJustMovedInStack();
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index b7a9e66..4df513e 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -208,13 +208,6 @@
}
@Override
- public void repositionChild(IWindow window, int left, int top, int right, int bottom,
- long deferTransactionUntilFrame, Rect outFrame) {
- mService.repositionChild(this, window, left, top, right, bottom,
- deferTransactionUntilFrame, outFrame);
- }
-
- @Override
public void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly) {
mService.setWillReplaceWindows(appToken, childrenOnly);
}
@@ -235,10 +228,6 @@
return res;
}
- public void performDeferredDestroy(IWindow window) {
- mService.performDeferredDestroyWindow(this, window);
- }
-
public boolean outOfMemory(IWindow window) {
return mService.outOfMemoryWindow(this, window);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 014a89d..5551afe 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1808,64 +1808,6 @@
}
}
- void repositionChild(Session session, IWindow client,
- int left, int top, int right, int bottom,
- long frameNumber, Rect outFrame) {
- Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "repositionChild");
- long origId = Binder.clearCallingIdentity();
-
- try {
- synchronized(mWindowMap) {
- WindowState win = windowForClientLocked(session, client, false);
- if (win == null) {
- return;
- }
- if (!win.isChildWindow()) {
- throw new IllegalArgumentException(
- "repositionChild called but window is not"
- + "attached to a parent win=" + win);
- }
-
- win.mAttrs.x = left;
- win.mAttrs.y = top;
- win.mAttrs.width = right - left;
- win.mAttrs.height = bottom - top;
- win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);
-
- if (win.mHasSurface) {
- if (SHOW_TRANSACTIONS) {
- Slog.i(TAG_WM, ">>> OPEN TRANSACTION repositionChild");
- }
-
- openSurfaceTransaction();
-
- try {
-
- win.applyGravityAndUpdateFrame(win.mContainingFrame, win.mDisplayFrame);
- win.mWinAnimator.computeShownFrameLocked();
-
- win.mWinAnimator.setSurfaceBoundariesLocked(false);
-
- if (frameNumber > 0) {
- win.mWinAnimator.deferTransactionUntilParentFrame(frameNumber);
- }
-
- } finally {
- closeSurfaceTransaction();
- if (SHOW_TRANSACTIONS) {
- Slog.i(TAG_WM, "<<< CLOSE TRANSACTION repositionChild");
- }
- }
- }
-
- outFrame = win.mCompatFrame;
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
- }
- }
-
public int relayoutWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int requestedWidth,
int requestedHeight, int viewVisibility, int flags,
@@ -2210,23 +2152,6 @@
return result;
}
- public void performDeferredDestroyWindow(Session session, IWindow client) {
- long origId = Binder.clearCallingIdentity();
-
- try {
- synchronized (mWindowMap) {
- WindowState win = windowForClientLocked(session, client, false);
- if (win == null || win.mWillReplaceWindow) {
- return;
- }
-
- win.mWinAnimator.destroyDeferredSurfaceLocked();
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
-
public boolean outOfMemoryWindow(Session session, IWindow client) {
final long origId = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index c9863c5..b08bb70 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -97,13 +97,7 @@
mWindowType = windowType;
mWindowSession = win.mSession;
- // For opaque child windows placed under parent windows, we use a special SurfaceControl
- // which mirrors commands to a black-out layer placed one Z-layer below the surface.
- // This prevents holes to whatever app/wallpaper is underneath.
- if (win.isChildWindow() && win.mSubLayer < 0 && win.mAppToken != null) {
- mSurfaceControl = new SurfaceControlWithBackground(
- s, name, w, h, format, flags, win.mAppToken, windowType, ownerUid);
- } else if (DEBUG_SURFACE_TRACE) {
+ if (DEBUG_SURFACE_TRACE) {
mSurfaceControl = new SurfaceTrace(
s, name, w, h, format, flags, windowType, ownerUid);
} else {
@@ -834,141 +828,4 @@
+ " (" + mDsdx + "," + mDtdx + "," + mDsdy + "," + mDtdy + ")";
}
}
-
- class SurfaceControlWithBackground extends SurfaceControl {
- private SurfaceControl mBackgroundControl;
- private boolean mOpaque = true;
- private boolean mAppForcedInvisible = false;
- private AppWindowToken mAppToken;
- public boolean mVisible = false;
- public int mLayer = -1;
-
- public SurfaceControlWithBackground(SurfaceSession s, String name, int w, int h, int format,
- int flags, AppWindowToken token, int windowType, int ownerUid)
- throws OutOfResourcesException {
- super(s, name, w, h, format, flags, windowType, ownerUid);
- mBackgroundControl = new SurfaceControl(s, name, w, h,
- PixelFormat.OPAQUE, flags | SurfaceControl.FX_SURFACE_DIM);
- mOpaque = (flags & SurfaceControl.OPAQUE) != 0;
- mAppToken = token;
-
- mAppToken.addSurfaceViewBackground(this);
- }
-
- @Override
- public void setAlpha(float alpha) {
- super.setAlpha(alpha);
- mBackgroundControl.setAlpha(alpha);
- }
-
- @Override
- public void setLayer(int zorder) {
- super.setLayer(zorder);
- mBackgroundControl.setLayer(zorder - 1);
- if (mLayer != zorder) {
- mLayer = zorder;
- mAppToken.updateSurfaceViewBackgroundVisibilities();
- }
- }
-
- @Override
- public void setPosition(float x, float y) {
- super.setPosition(x, y);
- mBackgroundControl.setPosition(x, y);
- }
-
- @Override
- public void setSize(int w, int h) {
- super.setSize(w, h);
- mBackgroundControl.setSize(w, h);
- }
-
- @Override
- public void setWindowCrop(Rect crop) {
- super.setWindowCrop(crop);
- mBackgroundControl.setWindowCrop(crop);
- }
-
- @Override
- public void setFinalCrop(Rect crop) {
- super.setFinalCrop(crop);
- mBackgroundControl.setFinalCrop(crop);
- }
-
- @Override
- public void setLayerStack(int layerStack) {
- super.setLayerStack(layerStack);
- mBackgroundControl.setLayerStack(layerStack);
- }
-
- @Override
- public void setOpaque(boolean isOpaque) {
- super.setOpaque(isOpaque);
- mOpaque = isOpaque;
- updateBackgroundVisibility(mAppForcedInvisible);
- }
-
- @Override
- public void setSecure(boolean isSecure) {
- super.setSecure(isSecure);
- }
-
- @Override
- public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
- super.setMatrix(dsdx, dtdx, dsdy, dtdy);
- mBackgroundControl.setMatrix(dsdx, dtdx, dsdy, dtdy);
- }
-
- @Override
- public void hide() {
- super.hide();
- if (mVisible) {
- mVisible = false;
- mAppToken.updateSurfaceViewBackgroundVisibilities();
- }
- }
-
- @Override
- public void show() {
- super.show();
- if (!mVisible) {
- mVisible = true;
- mAppToken.updateSurfaceViewBackgroundVisibilities();
- }
- }
-
- @Override
- public void destroy() {
- super.destroy();
- mBackgroundControl.destroy();
- mAppToken.removeSurfaceViewBackground(this);
- }
-
- @Override
- public void release() {
- super.release();
- mBackgroundControl.release();
- }
-
- @Override
- public void setTransparentRegionHint(Region region) {
- super.setTransparentRegionHint(region);
- mBackgroundControl.setTransparentRegionHint(region);
- }
-
- @Override
- public void deferTransactionUntil(IBinder handle, long frame) {
- super.deferTransactionUntil(handle, frame);
- mBackgroundControl.deferTransactionUntil(handle, frame);
- }
-
- void updateBackgroundVisibility(boolean forcedInvisible) {
- mAppForcedInvisible = forcedInvisible;
- if (mOpaque && mVisible && !mAppForcedInvisible) {
- mBackgroundControl.show();
- } else {
- mBackgroundControl.hide();
- }
- }
- }
}
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index a3b0429..3e3a19b 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -23,6 +23,7 @@
import android.net.apf.ApfCapabilities;
import android.net.apf.ApfFilter;
import android.net.DhcpResults;
+import android.net.INetd;
import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -34,10 +35,12 @@
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.IpManagerEvent;
import android.net.util.MultinetworkPolicyTracker;
+import android.net.util.NetdService;
import android.os.INetworkManagementService;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.LocalLog;
@@ -1027,14 +1030,16 @@
private boolean startIPv6() {
// Set privacy extensions.
+ final String PREFER_TEMPADDRS = "2";
try {
- mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
+ NetdService.run((INetd netd) -> {
+ netd.setProcSysNet(
+ INetd.IPV6, INetd.CONF, mInterfaceName, "use_tempaddr",
+ PREFER_TEMPADDRS);
+ });
mNwService.enableIpv6(mInterfaceName);
- } catch (RemoteException re) {
- logError("Unable to change interface settings: %s", re);
- return false;
- } catch (IllegalStateException ie) {
- logError("Unable to change interface settings: %s", ie);
+ } catch (IllegalStateException|RemoteException|ServiceSpecificException e) {
+ logError("Unable to change interface settings: %s", e);
return false;
}
diff --git a/services/net/java/android/net/util/NetdService.java b/services/net/java/android/net/util/NetdService.java
index 153cb50..6e69ff5 100644
--- a/services/net/java/android/net/util/NetdService.java
+++ b/services/net/java/android/net/util/NetdService.java
@@ -17,7 +17,10 @@
package android.net.util;
import android.net.INetd;
+import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
+import android.os.SystemClock;
import android.util.Log;
@@ -27,15 +30,24 @@
public class NetdService {
private static final String TAG = NetdService.class.getSimpleName();
private static final String NETD_SERVICE_NAME = "netd";
+ private static final long BASE_TIMEOUT_MS = 100;
+ private static final long MAX_TIMEOUT_MS = 1000;
+
/**
+ * Return an INetd instance, or null if not available.
+ *
* It is the caller's responsibility to check for a null return value
* and to handle RemoteException errors from invocations on the returned
* interface if, for example, netd dies and is restarted.
*
+ * Returned instances of INetd should not be cached.
+ *
* @return an INetd instance or null.
*/
public static INetd getInstance() {
+ // NOTE: ServiceManager does no caching for the netd service,
+ // because netd is not one of the defined common services.
final INetd netdInstance = INetd.Stub.asInterface(
ServiceManager.getService(NETD_SERVICE_NAME));
if (netdInstance == null) {
@@ -43,4 +55,82 @@
}
return netdInstance;
}
+
+ /**
+ * Blocks for a specified time until an INetd instance is available.
+ *
+ * It is the caller's responsibility to handle RemoteException errors
+ * from invocations on the returned interface if, for example, netd
+ * dies after this interface was returned.
+ *
+ * Returned instances of INetd should not be cached.
+ *
+ * Special values of maxTimeoutMs include: 0, meaning try to obtain an
+ * INetd instance only once, and -1 (or any value less than 0), meaning
+ * try to obtain an INetd instance indefinitely.
+ *
+ * @param maxTimeoutMs the maximum time to spend getting an INetd instance
+ * @return an INetd instance or null if no instance is available
+ * within |maxTimeoutMs| milliseconds.
+ */
+ public static INetd get(long maxTimeoutMs) {
+ if (maxTimeoutMs == 0) return getInstance();
+
+ final long stop = (maxTimeoutMs > 0)
+ ? SystemClock.elapsedRealtime() + maxTimeoutMs
+ : Long.MAX_VALUE;
+
+ long timeoutMs = 0;
+ while (true) {
+ final INetd netdInstance = getInstance();
+ if (netdInstance != null) {
+ return netdInstance;
+ }
+
+ final long remaining = stop - SystemClock.elapsedRealtime();
+ if (remaining <= 0) break;
+
+ // No netdInstance was received; sleep and retry.
+ timeoutMs = Math.min(timeoutMs + BASE_TIMEOUT_MS, MAX_TIMEOUT_MS);
+ timeoutMs = Math.min(timeoutMs, remaining);
+ try {
+ Thread.sleep(timeoutMs);
+ } catch (InterruptedException e) {}
+ }
+ return null;
+ }
+
+ /**
+ * Blocks until an INetd instance is available.
+ *
+ * It is the caller's responsibility to handle RemoteException errors
+ * from invocations on the returned interface if, for example, netd
+ * dies after this interface was returned.
+ *
+ * Returned instances of INetd should not be cached.
+ *
+ * @return an INetd instance.
+ */
+ public static INetd get() {
+ return get(-1);
+ }
+
+ public static interface NetdCommand {
+ void run(INetd netd) throws RemoteException;
+ }
+
+ /**
+ * Blocks until an INetd instance is availabe, and retries until either
+ * the command succeeds or a runtime exception is thrown.
+ */
+ public static void run(NetdCommand cmd) {
+ while (true) {
+ try {
+ cmd.run(get());
+ return;
+ } catch (RemoteException re) {
+ Log.e(TAG, "error communicating with netd: " + re);
+ }
+ }
+ }
}
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index 5f215f9..b538453 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -203,7 +203,6 @@
private void compareChannels(NotificationChannel expected, NotificationChannel actual) {
assertEquals(expected.getId(), actual.getId());
assertEquals(expected.getName(), actual.getName());
- assertEquals(expected.getNameResId(), actual.getNameResId());
assertEquals(expected.shouldVibrate(), actual.shouldVibrate());
assertEquals(expected.shouldShowLights(), actual.shouldShowLights());
assertEquals(expected.getImportance(), actual.getImportance());
@@ -219,7 +218,6 @@
private void compareGroups(NotificationChannelGroup expected, NotificationChannelGroup actual) {
assertEquals(expected.getId(), actual.getId());
assertEquals(expected.getName(), actual.getName());
- assertEquals(expected.getNameResId(), actual.getNameResId());
}
@Test
@@ -274,15 +272,12 @@
@Test
public void testChannelXml() throws Exception {
- int nameResId = 924896;
- int groupNameResId = 426272;
-
- NotificationChannelGroup ncg = new NotificationChannelGroup("1", groupNameResId);
+ NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye");
NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello");
NotificationChannel channel1 =
new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
NotificationChannel channel2 =
- new NotificationChannel("id2", nameResId, IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel2.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
channel2.enableLights(true);
channel2.setBypassDnd(true);
@@ -728,6 +723,25 @@
}
@Test
+ public void testGetDeletedChannelCount() throws Exception {
+ NotificationChannel channel =
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+ NotificationChannel channel2 =
+ new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH);
+ NotificationChannel channel3 =
+ new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH);
+ mHelper.createNotificationChannel(pkg, uid, channel, true);
+ mHelper.createNotificationChannel(pkg, uid, channel2, true);
+ mHelper.createNotificationChannel(pkg, uid, channel3, true);
+
+ mHelper.deleteNotificationChannel(pkg, uid, channel.getId());
+ mHelper.deleteNotificationChannel(pkg, uid, channel3.getId());
+
+ assertEquals(2, mHelper.getDeletedChannelCount(pkg, uid));
+ assertEquals(0, mHelper.getDeletedChannelCount(pkg2, uid2));
+ }
+
+ @Test
public void testUpdateDeletedChannels() throws Exception {
NotificationChannel channel =
new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
@@ -994,14 +1008,18 @@
}
@Test
- public void testCreateChannel_updateNameResId() throws Exception {
- NotificationChannel nc = new NotificationChannel("id", 1, IMPORTANCE_DEFAULT);
+ public void testCreateChannel_updateName() throws Exception {
+ NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT);
+ mHelper.createNotificationChannel(pkg, uid, nc, true);
+ NotificationChannel actual = mHelper.getNotificationChannel(pkg, uid, "id", false);
+ assertEquals("hello", actual.getName());
+
+ nc = new NotificationChannel("id", "goodbye", IMPORTANCE_HIGH);
mHelper.createNotificationChannel(pkg, uid, nc, true);
- nc = new NotificationChannel("id", 2, IMPORTANCE_DEFAULT);
- mHelper.createNotificationChannel(pkg, uid, nc, true);
-
- assertEquals(2, mHelper.getNotificationChannel(pkg, uid, "id", false).getNameResId());
+ actual = mHelper.getNotificationChannel(pkg, uid, "id", false);
+ assertEquals("goodbye", actual.getName());
+ assertEquals(IMPORTANCE_DEFAULT, actual.getImportance());
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java
index c6265bc..a2a4019 100644
--- a/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java
@@ -25,6 +25,8 @@
import android.app.IActivityManager;
import android.app.NotificationManager;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
import android.content.Context;
import android.content.pm.UserInfo;
import android.database.sqlite.SQLiteDatabase;
@@ -76,7 +78,7 @@
UserManager mUserManager;
MockStorageManager mStorageManager;
IActivityManager mActivityManager;
-
+ DevicePolicyManager mDevicePolicyManager;
KeyStore mKeyStore;
@Override
@@ -89,7 +91,9 @@
mUserManager = mock(UserManager.class);
mStorageManager = new MockStorageManager();
mActivityManager = mock(IActivityManager.class);
- mContext = new MockLockSettingsContext(getContext(), mUserManager, mNotificationManager);
+ mDevicePolicyManager = mock(DevicePolicyManager.class);
+ mContext = new MockLockSettingsContext(getContext(), mUserManager, mNotificationManager,
+ mDevicePolicyManager);
mStorage = new LockSettingsStorageTestable(mContext,
new File(getContext().getFilesDir(), "locksettings"));
File storageDir = mStorage.mStorageDir;
@@ -122,6 +126,10 @@
});
when(mLockPatternUtils.getLockSettings()).thenReturn(mService);
+
+ // Adding a fake Device Owner app which will enable escrow token support in LSS.
+ when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(
+ new ComponentName("com.dummy.package", ".FakeDeviceOwner"));
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java b/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java
index c68fbdc..4677904 100644
--- a/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java
+++ b/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java
@@ -21,6 +21,7 @@
import static org.mockito.Mockito.when;
import android.app.NotificationManager;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.UserInfo;
@@ -68,7 +69,7 @@
when(mockUserManager.getProfileParent(eq(3))).thenReturn(new UserInfo(0, "name", 0));
MockLockSettingsContext context = new MockLockSettingsContext(getContext(), mockUserManager,
- mock(NotificationManager.class));
+ mock(NotificationManager.class), mock(DevicePolicyManager.class));
mStorage = new LockSettingsStorageTestable(context,
new File(getContext().getFilesDir(), "locksettings"));
mStorage.setDatabaseOnCreateCallback(new LockSettingsStorage.Callback() {
diff --git a/services/tests/servicestests/src/com/android/server/MockLockSettingsContext.java b/services/tests/servicestests/src/com/android/server/MockLockSettingsContext.java
index b63936f..8bceed4 100644
--- a/services/tests/servicestests/src/com/android/server/MockLockSettingsContext.java
+++ b/services/tests/servicestests/src/com/android/server/MockLockSettingsContext.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.app.NotificationManager;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.ContextWrapper;
import android.os.UserManager;
@@ -25,12 +26,14 @@
private UserManager mUserManager;
private NotificationManager mNotificationManager;
+ private DevicePolicyManager mDevicePolicyManager;
public MockLockSettingsContext(Context base, UserManager userManager,
- NotificationManager notificationManager) {
+ NotificationManager notificationManager, DevicePolicyManager devicePolicyManager) {
super(base);
mUserManager = userManager;
mNotificationManager = notificationManager;
+ mDevicePolicyManager = devicePolicyManager;
}
@Override
@@ -39,6 +42,8 @@
return mUserManager;
} else if (NOTIFICATION_SERVICE.equals(name)) {
return mNotificationManager;
+ } else if (DEVICE_POLICY_SERVICE.equals(name)) {
+ return mDevicePolicyManager;
} else {
throw new RuntimeException("System service not mocked: " + name);
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 748e32a..7a226a0 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1374,6 +1374,22 @@
public static final String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG =
"data_limit_threshold_bytes_long";
+ /**
+ * Offset to be reduced from rsrp threshold while calculating signal strength level.
+ * @hide
+ */
+ public static final String KEY_LTE_EARFCNS_RSRP_BOOST_INT = "lte_earfcns_rsrp_boost_int";
+
+ /**
+ * List of EARFCN (E-UTRA Absolute Radio Frequency Channel Number,
+ * Reference: 3GPP TS 36.104 5.4.3) inclusive ranges on which lte_rsrp_boost_int
+ * will be applied. Format of the String array is expected to be {"erafcn1_start-earfcn1_end",
+ * "earfcn2_start-earfcn2_end" ... }
+ * @hide
+ */
+ public static final String KEY_BOOSTED_LTE_EARFCNS_STRING_ARRAY =
+ "boosted_lte_earfcns_string_array";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -1607,6 +1623,8 @@
sDefaults.putBoolean(KEY_EDITABLE_TETHER_APN_BOOL, false);
sDefaults.putStringArray(KEY_CALL_FORWARDING_BLOCKS_WHILE_ROAMING_STRING_ARRAY,
null);
+ sDefaults.putInt(KEY_LTE_EARFCNS_RSRP_BOOST_INT, 0);
+ sDefaults.putStringArray(KEY_BOOSTED_LTE_EARFCNS_STRING_ARRAY, null);
}
/**
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 7a83979..5fb83ab 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -243,6 +243,10 @@
private boolean mIsUsingCarrierAggregation;
+ /* EARFCN stands for E-UTRA Absolute Radio Frequency Channel Number,
+ * Reference: 3GPP TS 36.104 5.4.3 */
+ private int mLteEarfcnRsrpBoost = 0;
+
/**
* get String description of roaming type
* @hide
@@ -322,6 +326,7 @@
mIsEmergencyOnly = s.mIsEmergencyOnly;
mIsDataRoamingFromRegistration = s.mIsDataRoamingFromRegistration;
mIsUsingCarrierAggregation = s.mIsUsingCarrierAggregation;
+ mLteEarfcnRsrpBoost = s.mLteEarfcnRsrpBoost;
}
/**
@@ -351,6 +356,7 @@
mIsEmergencyOnly = in.readInt() != 0;
mIsDataRoamingFromRegistration = in.readInt() != 0;
mIsUsingCarrierAggregation = in.readInt() != 0;
+ mLteEarfcnRsrpBoost = in.readInt();
}
public void writeToParcel(Parcel out, int flags) {
@@ -377,6 +383,7 @@
out.writeInt(mIsEmergencyOnly ? 1 : 0);
out.writeInt(mIsDataRoamingFromRegistration ? 1 : 0);
out.writeInt(mIsUsingCarrierAggregation ? 1 : 0);
+ out.writeInt(mLteEarfcnRsrpBoost);
}
public int describeContents() {
@@ -814,7 +821,8 @@
+ " DefRoamInd=" + mCdmaDefaultRoamingIndicator
+ " EmergOnly=" + mIsEmergencyOnly
+ " IsDataRoamingFromRegistration=" + mIsDataRoamingFromRegistration
- + " IsUsingCarrierAggregation=" + mIsUsingCarrierAggregation);
+ + " IsUsingCarrierAggregation=" + mIsUsingCarrierAggregation
+ + " mLteEarfcnRsrpBoost=" + mLteEarfcnRsrpBoost);
}
private void setNullState(int state) {
@@ -842,6 +850,7 @@
mIsEmergencyOnly = false;
mIsDataRoamingFromRegistration = false;
mIsUsingCarrierAggregation = false;
+ mLteEarfcnRsrpBoost = 0;
}
public void setStateOutOfService() {
@@ -1016,6 +1025,7 @@
mIsEmergencyOnly = m.getBoolean("emergencyOnly");
mIsDataRoamingFromRegistration = m.getBoolean("isDataRoamingFromRegistration");
mIsUsingCarrierAggregation = m.getBoolean("isUsingCarrierAggregation");
+ mLteEarfcnRsrpBoost = m.getInt("LteEarfcnRsrpBoost");
}
/**
@@ -1046,6 +1056,7 @@
m.putBoolean("emergencyOnly", mIsEmergencyOnly);
m.putBoolean("isDataRoamingFromRegistration", mIsDataRoamingFromRegistration);
m.putBoolean("isUsingCarrierAggregation", mIsUsingCarrierAggregation);
+ m.putInt("LteEarfcnRsrpBoost", mLteEarfcnRsrpBoost);
}
/** @hide */
@@ -1081,6 +1092,16 @@
}
/** @hide */
+ public int getLteEarfcnRsrpBoost() {
+ return mLteEarfcnRsrpBoost;
+ }
+
+ /** @hide */
+ public void setLteEarfcnRsrpBoost(int LteEarfcnRsrpBoost) {
+ mLteEarfcnRsrpBoost = LteEarfcnRsrpBoost;
+ }
+
+ /** @hide */
public void setCssIndicator(int css) {
this.mCssIndicator = (css != 0);
}
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index c484fd3..9e02399 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -64,6 +64,8 @@
private int mLteRsrq;
private int mLteRssnr;
private int mLteCqi;
+ private int mLteRsrpBoost; // offset to be reduced from the rsrp threshold while calculating
+ // signal strength level
private int mTdScdmaRscp;
private boolean isGsm; // This value is set by the ServiceStateTracker onSignalStrengthResult
@@ -104,6 +106,7 @@
mLteRsrq = INVALID;
mLteRssnr = INVALID;
mLteCqi = INVALID;
+ mLteRsrpBoost = 0;
mTdScdmaRscp = INVALID;
isGsm = true;
}
@@ -129,6 +132,7 @@
mLteRsrq = INVALID;
mLteRssnr = INVALID;
mLteCqi = INVALID;
+ mLteRsrpBoost = 0;
mTdScdmaRscp = INVALID;
isGsm = gsmFlag;
}
@@ -142,10 +146,26 @@
int cdmaDbm, int cdmaEcio,
int evdoDbm, int evdoEcio, int evdoSnr,
int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
+ int lteRsrpBoost, int tdScdmaRscp, boolean gsmFlag) {
+ initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
+ evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
+ lteRsrq, lteRssnr, lteCqi, lteRsrpBoost, gsmFlag);
+ mTdScdmaRscp = tdScdmaRscp;
+ }
+
+ /**
+ * Constructor
+ *
+ * @hide
+ */
+ public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
+ int cdmaDbm, int cdmaEcio,
+ int evdoDbm, int evdoEcio, int evdoSnr,
+ int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
int tdScdmaRscp, boolean gsmFlag) {
initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
- lteRsrq, lteRssnr, lteCqi, gsmFlag);
+ lteRsrq, lteRssnr, lteCqi, 0, gsmFlag);
mTdScdmaRscp = tdScdmaRscp;
}
@@ -161,7 +181,7 @@
boolean gsmFlag) {
initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
- lteRsrq, lteRssnr, lteCqi, gsmFlag);
+ lteRsrq, lteRssnr, lteCqi, 0, gsmFlag);
}
/**
@@ -175,7 +195,7 @@
boolean gsmFlag) {
initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
evdoDbm, evdoEcio, evdoSnr, 99, INVALID,
- INVALID, INVALID, INVALID, gsmFlag);
+ INVALID, INVALID, INVALID, 0, gsmFlag);
}
/**
@@ -209,7 +229,7 @@
boolean gsm) {
initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
evdoDbm, evdoEcio, evdoSnr, 99, INVALID,
- INVALID, INVALID, INVALID, gsm);
+ INVALID, INVALID, INVALID, 0, gsm);
}
/**
@@ -227,6 +247,7 @@
* @param lteRsrq
* @param lteRssnr
* @param lteCqi
+ * @param lteRsrpBoost
* @param gsm
*
* @hide
@@ -235,7 +256,7 @@
int cdmaDbm, int cdmaEcio,
int evdoDbm, int evdoEcio, int evdoSnr,
int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
- boolean gsm) {
+ int lteRsrpBoost, boolean gsm) {
mGsmSignalStrength = gsmSignalStrength;
mGsmBitErrorRate = gsmBitErrorRate;
mCdmaDbm = cdmaDbm;
@@ -248,6 +269,7 @@
mLteRsrq = lteRsrq;
mLteRssnr = lteRssnr;
mLteCqi = lteCqi;
+ mLteRsrpBoost = lteRsrpBoost;
mTdScdmaRscp = INVALID;
isGsm = gsm;
if (DBG) log("initialize: " + toString());
@@ -269,6 +291,7 @@
mLteRsrq = s.mLteRsrq;
mLteRssnr = s.mLteRssnr;
mLteCqi = s.mLteCqi;
+ mLteRsrpBoost = s.mLteRsrpBoost;
mTdScdmaRscp = s.mTdScdmaRscp;
isGsm = s.isGsm;
}
@@ -293,6 +316,7 @@
mLteRsrq = in.readInt();
mLteRssnr = in.readInt();
mLteCqi = in.readInt();
+ mLteRsrpBoost = in.readInt();
mTdScdmaRscp = in.readInt();
isGsm = (in.readInt() != 0);
}
@@ -340,6 +364,7 @@
out.writeInt(mLteRsrq);
out.writeInt(mLteRssnr);
out.writeInt(mLteCqi);
+ out.writeInt(mLteRsrpBoost);
out.writeInt(mTdScdmaRscp);
out.writeInt(isGsm ? 1 : 0);
}
@@ -416,6 +441,18 @@
}
/**
+ * @param lteRsrpBoost - signal strength offset
+ *
+ * Used by phone to set the lte signal strength offset which will be
+ * reduced from rsrp threshold while calculating signal strength level
+ *
+ * @hide
+ */
+ public void setLteRsrpBoost(int lteRsrpBoost) {
+ mLteRsrpBoost = lteRsrpBoost;
+ }
+
+ /**
* Get the GSM Signal Strength, valid values are (0-31, 99) as defined in TS
* 27.007 8.5
*/
@@ -490,6 +527,11 @@
return mLteCqi;
}
+ /** @hide */
+ public int getLteRsrpBoost() {
+ return mLteRsrpBoost;
+ }
+
/**
* Retrieve an abstract level value for the overall signal strength.
*
@@ -793,12 +835,19 @@
Log.wtf(LOG_TAG, "getLteLevel - config_lteDbmThresholds has invalid num of elements."
+ " Cannot evaluate RSRP signal.");
} else {
- if (mLteRsrp > threshRsrp[5]) rsrpIconLevel = -1;
- else if (mLteRsrp >= threshRsrp[4]) rsrpIconLevel = SIGNAL_STRENGTH_GREAT;
- else if (mLteRsrp >= threshRsrp[3]) rsrpIconLevel = SIGNAL_STRENGTH_GOOD;
- else if (mLteRsrp >= threshRsrp[2]) rsrpIconLevel = SIGNAL_STRENGTH_MODERATE;
- else if (mLteRsrp >= threshRsrp[1]) rsrpIconLevel = SIGNAL_STRENGTH_POOR;
- else if (mLteRsrp >= threshRsrp[0]) rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ if (mLteRsrp > threshRsrp[5]) {
+ rsrpIconLevel = -1;
+ } else if (mLteRsrp >= (threshRsrp[4] - mLteRsrpBoost)) {
+ rsrpIconLevel = SIGNAL_STRENGTH_GREAT;
+ } else if (mLteRsrp >= (threshRsrp[3] - mLteRsrpBoost)) {
+ rsrpIconLevel = SIGNAL_STRENGTH_GOOD;
+ } else if (mLteRsrp >= (threshRsrp[2] - mLteRsrpBoost)) {
+ rsrpIconLevel = SIGNAL_STRENGTH_MODERATE;
+ } else if (mLteRsrp >= (threshRsrp[1] - mLteRsrpBoost)) {
+ rsrpIconLevel = SIGNAL_STRENGTH_POOR;
+ } else if (mLteRsrp >= threshRsrp[0]) {
+ rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ }
}
/*
@@ -816,7 +865,8 @@
snrIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
if (DBG) log("getLTELevel - rsrp:" + mLteRsrp + " snr:" + mLteRssnr + " rsrpIconLevel:"
- + rsrpIconLevel + " snrIconLevel:" + snrIconLevel);
+ + rsrpIconLevel + " snrIconLevel:" + snrIconLevel
+ + " lteRsrpBoost:" + mLteRsrpBoost);
/* Choose a measurement type to use for notification */
if (snrIconLevel != -1 && rsrpIconLevel != -1) {
@@ -939,7 +989,7 @@
+ (mEvdoDbm * primeNum) + (mEvdoEcio * primeNum) + (mEvdoSnr * primeNum)
+ (mLteSignalStrength * primeNum) + (mLteRsrp * primeNum)
+ (mLteRsrq * primeNum) + (mLteRssnr * primeNum) + (mLteCqi * primeNum)
- + (mTdScdmaRscp * primeNum) + (isGsm ? 1 : 0));
+ + (mLteRsrpBoost * primeNum) + (mTdScdmaRscp * primeNum) + (isGsm ? 1 : 0));
}
/**
@@ -971,6 +1021,7 @@
&& mLteRsrq == s.mLteRsrq
&& mLteRssnr == s.mLteRssnr
&& mLteCqi == s.mLteCqi
+ && mLteRsrpBoost == s.mLteRsrpBoost
&& mTdScdmaRscp == s.mTdScdmaRscp
&& isGsm == s.isGsm);
}
@@ -993,6 +1044,7 @@
+ " " + mLteRsrq
+ " " + mLteRssnr
+ " " + mLteCqi
+ + " " + mLteRsrpBoost
+ " " + mTdScdmaRscp
+ " " + (isGsm ? "gsm|lte" : "cdma"));
}
@@ -1016,6 +1068,7 @@
mLteRsrq = m.getInt("LteRsrq");
mLteRssnr = m.getInt("LteRssnr");
mLteCqi = m.getInt("LteCqi");
+ mLteRsrpBoost = m.getInt("lteRsrpBoost");
mTdScdmaRscp = m.getInt("TdScdma");
isGsm = m.getBoolean("isGsm");
}
@@ -1039,6 +1092,7 @@
m.putInt("LteRsrq", mLteRsrq);
m.putInt("LteRssnr", mLteRssnr);
m.putInt("LteCqi", mLteCqi);
+ m.putInt("lteRsrpBoost", mLteRsrpBoost);
m.putInt("TdScdma", mTdScdmaRscp);
m.putBoolean("isGsm", isGsm);
}
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index 58511b9..785e1ce 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -85,7 +85,7 @@
new Thread() {
public void run() {
for (int j = 0; j < nEvents; j++) {
- assertTrue(logger.log(i * 100 + j, FAKE_EV));
+ assertTrue(logger.log(1 + i * 100 + j, FAKE_EV));
}
}
}.start();
@@ -96,7 +96,7 @@
Iterator<ConnectivityMetricsEvent> iter = got.iterator();
for (int i = 0; i < nCallers; i++) {
for (int j = 0; j < nEvents; j++) {
- int expectedTimestamp = i * 100 + j;
+ int expectedTimestamp = 1 + i * 100 + j;
assertEventsEqual(expectedEvent(expectedTimestamp), iter.next());
}
}
@@ -315,14 +315,15 @@
}
static ConnectivityMetricsEvent expectedEvent(int timestamp) {
- return new ConnectivityMetricsEvent((long)timestamp, 0, 0, FAKE_EV);
+ ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
+ ev.timestamp = timestamp;
+ ev.data = FAKE_EV;
+ return ev;
}
/** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */
static void assertEventsEqual(ConnectivityMetricsEvent expected, ConnectivityMetricsEvent got) {
assertEquals(expected.timestamp, got.timestamp);
- assertEquals(expected.componentTag, got.componentTag);
- assertEquals(expected.eventTag, got.eventTag);
assertEquals(expected.data, got.data);
}
diff --git a/tests/net/java/com/android/server/connectivity/MetricsTestUtil.java b/tests/net/java/com/android/server/connectivity/MetricsTestUtil.java
index c5965e8..5064b9b 100644
--- a/tests/net/java/com/android/server/connectivity/MetricsTestUtil.java
+++ b/tests/net/java/com/android/server/connectivity/MetricsTestUtil.java
@@ -28,7 +28,10 @@
}
static ConnectivityMetricsEvent ev(Parcelable p) {
- return new ConnectivityMetricsEvent(1L, 0, 0, p);
+ ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
+ ev.timestamp = 1L;
+ ev.data = p;
+ return ev;
}
static ConnectivityMetricsEvent describeIpEvent(Consumer<Parcel>... fs) {
diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
index 9e0f3213..0ab4406 100644
--- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -23,6 +23,7 @@
import android.net.metrics.DnsEvent;
import android.net.metrics.INetdEventListener;
import android.net.metrics.IpConnectivityLog;
+import android.os.Parcelable;
import android.os.RemoteException;
import android.system.OsConstants;
import android.test.suitebuilder.annotation.SmallTest;
@@ -165,8 +166,8 @@
// call onLost() asynchronously to logDnsAsync's onDnsEvent() calls.
mCallbackCaptor.getValue().onLost(new Network(105));
- // do not verify unpredictable batch
- verify(mLog, timeout(500).times(1)).log(any());
+ // do not verify batch with unpredictable length
+ verify(mLog, timeout(500).times(1)).log(any(Parcelable.class));
}
@SmallTest
@@ -279,11 +280,7 @@
}
void logDnsAsync(int netId, int[] latencies) {
- new Thread() {
- public void run() {
- log(netId, latencies);
- }
- }.start();
+ new Thread(() -> log(netId, latencies)).start();
}
void verifyLoggedDnsEvents(DnsEvent... expected) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
index 7582fda..4dfe47b 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
@@ -96,18 +96,6 @@
}
@Override
- public void repositionChild(IWindow window, int left, int top, int right, int bottom,
- long deferTransactionUntilFrame, Rect outFrame) {
- // pass for now.
- return;
- }
-
- @Override
- public void performDeferredDestroy(IWindow window) {
- // pass for now.
- }
-
- @Override
public boolean outOfMemory(IWindow window) throws RemoteException {
return false;
}