Merge "Remove unused shared lib from statsd" into pi-dev
diff --git a/Android.mk b/Android.mk
index 308a85a..bbe2faf 100644
--- a/Android.mk
+++ b/Android.mk
@@ -333,8 +333,6 @@
$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
-referenceonly \
-api $(INTERNAL_PLATFORM_API_FILE) \
- -privateApi $(INTERNAL_PLATFORM_PRIVATE_API_FILE) \
- -privateDexApi $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) \
-removedApi $(INTERNAL_PLATFORM_REMOVED_API_FILE) \
-nodocs
@@ -345,8 +343,7 @@
include $(BUILD_DROIDDOC)
$(full_target): .KATI_IMPLICIT_OUTPUTS := $(INTERNAL_PLATFORM_API_FILE) \
- $(INTERNAL_PLATFORM_PRIVATE_API_FILE) \
- $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE)
+ $(INTERNAL_PLATFORM_REMOVED_API_FILE)
$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_API_FILE))
# ==== the system api stubs ===================================
@@ -371,8 +368,6 @@
-referenceonly \
-showAnnotation android.annotation.SystemApi \
-api $(INTERNAL_PLATFORM_SYSTEM_API_FILE) \
- -privateApi $(INTERNAL_PLATFORM_SYSTEM_PRIVATE_API_FILE) \
- -privateDexApi $(INTERNAL_PLATFORM_SYSTEM_PRIVATE_DEX_API_FILE) \
-removedApi $(INTERNAL_PLATFORM_SYSTEM_REMOVED_API_FILE) \
-exactApi $(INTERNAL_PLATFORM_SYSTEM_EXACT_API_FILE) \
-nodocs
@@ -384,8 +379,8 @@
include $(BUILD_DROIDDOC)
$(full_target): .KATI_IMPLICIT_OUTPUTS := $(INTERNAL_PLATFORM_SYSTEM_API_FILE) \
- $(INTERNAL_PLATFORM_SYSTEM_PRIVATE_API_FILE) \
- $(INTERNAL_PLATFORM_SYSTEM_PRIVATE_DEX_API_FILE)
+ $(INTERNAL_PLATFORM_SYSTEM_REMOVED_API_FILE) \
+ $(INTERNAL_PLATFORM_SYSTEM_EXACT_API_FILE)
$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_SYSTEM_API_FILE))
# ==== the test api stubs ===================================
@@ -421,9 +416,43 @@
include $(BUILD_DROIDDOC)
-$(INTERNAL_PLATFORM_TEST_API_FILE): $(full_target)
+$(full_target): .KATI_IMPLICIT_OUTPUTS := $(INTERNAL_PLATFORM_TEST_API_FILE) \
+ $(INTERNAL_PLATFORM_TEST_REMOVED_API_FILE) \
+ $(INTERNAL_PLATFORM_TEST_EXACT_API_FILE)
$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_TEST_API_FILE))
+# ==== the complete hidden api list ===================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=$(framework_docs_LOCAL_API_CHECK_SRC_FILES)
+LOCAL_GENERATED_SOURCES:=$(framework_docs_LOCAL_GENERATED_SOURCES)
+LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
+LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_API_CHECK_JAVA_LIBRARIES)
+LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
+LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
+LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
+LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_API_CHECK_ADDITIONAL_JAVA_DIR)
+LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
+
+LOCAL_MODULE := hidden-api-list
+
+LOCAL_DROIDDOC_OPTIONS:=\
+ $(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
+ -referenceonly \
+ -showUnannotated \
+ -showAnnotation android.annotation.SystemApi \
+ -showAnnotation android.annotation.TestApi \
+ -privateDexApi $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) \
+ -nodocs
+
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
+
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_DROIDDOC)
+
+$(full_target): .KATI_IMPLICIT_OUTPUTS := $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE)
+
# ==== check javadoc comments but don't generate docs ========
include $(CLEAR_VARS)
diff --git a/apct-tests/perftests/core/src/android/database/SQLiteDatabasePerfTest.java b/apct-tests/perftests/core/src/android/database/SQLiteDatabasePerfTest.java
index 7a32c0c..e2b75c3 100644
--- a/apct-tests/perftests/core/src/android/database/SQLiteDatabasePerfTest.java
+++ b/apct-tests/perftests/core/src/android/database/SQLiteDatabasePerfTest.java
@@ -118,6 +118,52 @@
}
@Test
+ public void testCursorIterateForward() {
+ // A larger dataset is needed to exceed default CursorWindow size
+ int datasetSize = DEFAULT_DATASET_SIZE * 50;
+ insertT1TestDataSet(datasetSize);
+
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ try (Cursor cursor = mDatabase
+ .rawQuery("SELECT _ID, COL_A, COL_B, COL_C FROM T1 ORDER BY _ID", null)) {
+ int i = 0;
+ while(cursor.moveToNext()) {
+ assertEquals(i, cursor.getInt(0));
+ assertEquals(i, cursor.getInt(1));
+ assertEquals("T1Value" + i, cursor.getString(2));
+ assertEquals(1.1 * i, cursor.getDouble(3), 0.0000001d);
+ i++;
+ }
+ assertEquals(datasetSize, i);
+ }
+ }
+ }
+
+ @Test
+ public void testCursorIterateBackwards() {
+ // A larger dataset is needed to exceed default CursorWindow size
+ int datasetSize = DEFAULT_DATASET_SIZE * 50;
+ insertT1TestDataSet(datasetSize);
+
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ try (Cursor cursor = mDatabase
+ .rawQuery("SELECT _ID, COL_A, COL_B, COL_C FROM T1 ORDER BY _ID", null)) {
+ int i = datasetSize - 1;
+ while(cursor.moveToPosition(i)) {
+ assertEquals(i, cursor.getInt(0));
+ assertEquals(i, cursor.getInt(1));
+ assertEquals("T1Value" + i, cursor.getString(2));
+ assertEquals(1.1 * i, cursor.getDouble(3), 0.0000001d);
+ i--;
+ }
+ assertEquals(-1, i);
+ }
+ }
+ }
+
+ @Test
public void testInnerJoin() {
mDatabase.setForeignKeyConstraintsEnabled(true);
mDatabase.beginTransaction();
@@ -201,8 +247,12 @@
}
private void insertT1TestDataSet() {
+ insertT1TestDataSet(DEFAULT_DATASET_SIZE);
+ }
+
+ private void insertT1TestDataSet(int size) {
mDatabase.beginTransaction();
- for (int i = 0; i < DEFAULT_DATASET_SIZE; i++) {
+ for (int i = 0; i < size; i++) {
mDatabase.execSQL("INSERT INTO T1 VALUES (?, ?, ?, ?)",
new Object[]{i, i, "T1Value" + i, i * 1.1});
}
diff --git a/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java b/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
index 55b97e7..dc34b7f 100644
--- a/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
+++ b/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
@@ -117,6 +117,26 @@
}
@Test
+ public void testNewLayout_RandomText_Selectable() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ BoringLayout.Metrics metrics = new BoringLayout.Metrics();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final TextView textView = new TextView(getContext());
+ textView.setTextIsSelectable(true);
+ textView.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
+ textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
+ textView.setText(text);
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.makeNewLayout(TEXT_WIDTH, TEXT_WIDTH, UNKNOWN_BORING, UNKNOWN_BORING,
+ TEXT_WIDTH, false);
+ }
+ }
+
+ @Test
public void testNewLayout_PrecomputedText() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
BoringLayout.Metrics metrics = new BoringLayout.Metrics();
@@ -179,6 +199,24 @@
}
@Test
+ public void testSetText_RandomText_Selectable() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ BoringLayout.Metrics metrics = new BoringLayout.Metrics();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final TextView textView = new TextView(getContext());
+ textView.setTextIsSelectable(true);
+ textView.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
+ textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.setText(text);
+ }
+ }
+
+ @Test
public void testSetText_PrecomputedText() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
BoringLayout.Metrics metrics = new BoringLayout.Metrics();
@@ -222,8 +260,8 @@
@Test
public void testOnMeasure_RandomText() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
- int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+ int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+ int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
while (state.keepRunning()) {
state.pauseTiming();
final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
@@ -240,10 +278,31 @@
}
@Test
+ public void testOnMeasure_RandomText_Selectable() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+ int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final TestableTextView textView = new TestableTextView(getContext());
+ textView.setTextIsSelectable(true);
+ textView.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
+ textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
+ textView.setText(text);
+ textView.nullLayouts();
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.onMeasure(width, height);
+ }
+ }
+
+ @Test
public void testOnMeasure_PrecomputedText() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
- int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+ int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+ int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
while (state.keepRunning()) {
state.pauseTiming();
final PrecomputedText.Params params = new PrecomputedText.Params.Builder(PAINT)
@@ -265,8 +324,8 @@
@Test
public void testOnMeasure_PrecomputedText_Selectable() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
- int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+ int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+ int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
while (state.keepRunning()) {
state.pauseTiming();
final PrecomputedText.Params params = new PrecomputedText.Params.Builder(PAINT)
@@ -289,8 +348,8 @@
@Test
public void testOnDraw_RandomText() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
- int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+ int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+ int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
final RenderNode node = RenderNode.create("benchmark", null);
while (state.keepRunning()) {
state.pauseTiming();
@@ -299,8 +358,34 @@
textView.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
textView.setText(text);
+ textView.measure(width, height);
+ textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
+ final DisplayListCanvas c = node.start(
+ textView.getMeasuredWidth(), textView.getMeasuredHeight());
textView.nullLayouts();
- textView.onMeasure(width, height);
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.onDraw(c);
+ }
+ }
+
+ @Test
+ public void testOnDraw_RandomText_Selectable() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+ int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ final RenderNode node = RenderNode.create("benchmark", null);
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final TestableTextView textView = new TestableTextView(getContext());
+ textView.setTextIsSelectable(true);
+ textView.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
+ textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
+ textView.setText(text);
+ textView.measure(width, height);
+ textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
final DisplayListCanvas c = node.start(
textView.getMeasuredWidth(), textView.getMeasuredHeight());
textView.nullLayouts();
@@ -314,8 +399,8 @@
@Test
public void testOnDraw_PrecomputedText() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
- int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+ int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+ int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
final RenderNode node = RenderNode.create("benchmark", null);
while (state.keepRunning()) {
state.pauseTiming();
@@ -327,8 +412,8 @@
final TestableTextView textView = new TestableTextView(getContext());
textView.setTextMetricsParams(params);
textView.setText(text);
- textView.nullLayouts();
- textView.onMeasure(width, height);
+ textView.measure(width, height);
+ textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
final DisplayListCanvas c = node.start(
textView.getMeasuredWidth(), textView.getMeasuredHeight());
textView.nullLayouts();
@@ -356,8 +441,8 @@
textView.setTextIsSelectable(true);
textView.setTextMetricsParams(params);
textView.setText(text);
- textView.nullLayouts();
- textView.onMeasure(width, height);
+ textView.measure(width, height);
+ textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
final DisplayListCanvas c = node.start(
textView.getMeasuredWidth(), textView.getMeasuredHeight());
textView.nullLayouts();
diff --git a/api/current.txt b/api/current.txt
index b2a6ba6..b3be727 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4265,6 +4265,7 @@
public class Application extends android.content.ContextWrapper implements android.content.ComponentCallbacks2 {
ctor public Application();
+ method public static java.lang.String getProcessName();
method public void onConfigurationChanged(android.content.res.Configuration);
method public void onCreate();
method public void onLowMemory();
@@ -5752,8 +5753,15 @@
field public static final int PRIORITY_SENDERS_ANY = 0; // 0x0
field public static final int PRIORITY_SENDERS_CONTACTS = 1; // 0x1
field public static final int PRIORITY_SENDERS_STARRED = 2; // 0x2
- field public static final int SUPPRESSED_EFFECT_SCREEN_OFF = 1; // 0x1
- field public static final int SUPPRESSED_EFFECT_SCREEN_ON = 2; // 0x2
+ field public static final int SUPPRESSED_EFFECT_AMBIENT = 128; // 0x80
+ field public static final int SUPPRESSED_EFFECT_BADGE = 64; // 0x40
+ field public static final int SUPPRESSED_EFFECT_FULL_SCREEN_INTENT = 4; // 0x4
+ field public static final int SUPPRESSED_EFFECT_LIGHTS = 8; // 0x8
+ field public static final int SUPPRESSED_EFFECT_NOTIFICATION_LIST = 256; // 0x100
+ field public static final int SUPPRESSED_EFFECT_PEEK = 16; // 0x10
+ field public static final deprecated int SUPPRESSED_EFFECT_SCREEN_OFF = 1; // 0x1
+ field public static final deprecated int SUPPRESSED_EFFECT_SCREEN_ON = 2; // 0x2
+ field public static final int SUPPRESSED_EFFECT_STATUS_BAR = 32; // 0x20
field public final int priorityCallSenders;
field public final int priorityCategories;
field public final int priorityMessageSenders;
@@ -7263,13 +7271,13 @@
method public android.net.Uri mapIntentToUri(android.content.Intent);
method public void pinSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>);
method public void unpinSlice(android.net.Uri);
+ field public static final java.lang.String CATEGORY_SLICE = "android.app.slice.category.SLICE";
field public static final java.lang.String SLICE_METADATA_KEY = "android.metadata.SLICE_URI";
}
public abstract class SliceProvider extends android.content.ContentProvider {
ctor public SliceProvider();
method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]);
- method public final java.lang.String getBindingPackage();
method public final java.lang.String getType(android.net.Uri);
method public final android.net.Uri insert(android.net.Uri, android.content.ContentValues);
method public android.app.slice.Slice onBindSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>);
@@ -13601,11 +13609,19 @@
method public static android.graphics.Bitmap decodeBitmap(android.graphics.ImageDecoder.Source) throws java.io.IOException;
method public static android.graphics.drawable.Drawable decodeDrawable(android.graphics.ImageDecoder.Source, android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException;
method public static android.graphics.drawable.Drawable decodeDrawable(android.graphics.ImageDecoder.Source) throws java.io.IOException;
+ method public int getAllocator();
+ method public boolean getConserveMemory();
+ method public android.graphics.Rect getCrop();
+ method public boolean getDecodeAsAlphaMask();
+ method public boolean getMutable();
+ method public android.graphics.ImageDecoder.OnPartialImageListener getOnPartialImageListener();
+ method public android.graphics.PostProcessor getPostProcessor();
+ method public boolean getRequireUnpremultiplied();
method public android.util.Size getSampledSize(int);
method public android.graphics.ImageDecoder setAllocator(int);
- method public android.graphics.ImageDecoder setAsAlphaMask(boolean);
method public android.graphics.ImageDecoder setConserveMemory(boolean);
method public android.graphics.ImageDecoder setCrop(android.graphics.Rect);
+ method public android.graphics.ImageDecoder setDecodeAsAlphaMask(boolean);
method public android.graphics.ImageDecoder setMutable(boolean);
method public android.graphics.ImageDecoder setOnPartialImageListener(android.graphics.ImageDecoder.OnPartialImageListener);
method public android.graphics.ImageDecoder setPostProcessor(android.graphics.PostProcessor);
@@ -14420,6 +14436,7 @@
method public static android.graphics.Typeface createFromFile(java.lang.String);
method public static android.graphics.Typeface defaultFromStyle(int);
method public int getStyle();
+ method public int getWeight();
method public final boolean isBold();
method public final boolean isItalic();
field public static final int BOLD = 1; // 0x1
@@ -21209,7 +21226,7 @@
method public void onWindowHidden();
method public void onWindowShown();
method public void requestHideSelf(int);
- method public void requestShowSelf(int);
+ method public final void requestShowSelf(int);
method public boolean sendDefaultEditorAction(boolean);
method public void sendDownUpKeyEvents(int);
method public void sendKeyChar(char);
@@ -21219,13 +21236,13 @@
method public void setExtractView(android.view.View);
method public void setExtractViewShown(boolean);
method public void setInputView(android.view.View);
- method public boolean shouldOfferSwitchingToNextInputMethod();
+ method public final boolean shouldOfferSwitchingToNextInputMethod();
method public void showStatusIcon(int);
method public void showWindow(boolean);
method public void switchInputMethod(java.lang.String);
- method public void switchInputMethod(java.lang.String, android.view.inputmethod.InputMethodSubtype);
- method public boolean switchToNextInputMethod(boolean);
- method public boolean switchToPreviousInputMethod();
+ method public final void switchInputMethod(java.lang.String, android.view.inputmethod.InputMethodSubtype);
+ method public final boolean switchToNextInputMethod(boolean);
+ method public final boolean switchToPreviousInputMethod();
method public void updateFullscreenMode();
method public void updateInputViewShown();
field public static final int BACK_DISPOSITION_DEFAULT = 0; // 0x0
@@ -23241,6 +23258,7 @@
field public static final int HEVCProfileMain = 1; // 0x1
field public static final int HEVCProfileMain10 = 2; // 0x2
field public static final int HEVCProfileMain10HDR10 = 4096; // 0x1000
+ field public static final int HEVCProfileMainStill = 4; // 0x4
field public static final int MPEG2LevelH14 = 2; // 0x2
field public static final int MPEG2LevelHL = 3; // 0x3
field public static final int MPEG2LevelHP = 4; // 0x4
@@ -24034,13 +24052,13 @@
ctor public MediaMetadataRetriever();
method public java.lang.String extractMetadata(int);
method public byte[] getEmbeddedPicture();
- method public android.graphics.Bitmap getFrameAtIndex(int);
+ method public android.graphics.Bitmap getFrameAtIndex(int, android.media.MediaMetadataRetriever.BitmapParams);
method public android.graphics.Bitmap getFrameAtTime(long, int);
method public android.graphics.Bitmap getFrameAtTime(long);
method public android.graphics.Bitmap getFrameAtTime();
- method public android.graphics.Bitmap[] getFramesAtIndex(int, int);
- method public android.graphics.Bitmap getImageAtIndex(int);
- method public android.graphics.Bitmap getPrimaryImage();
+ method public java.util.List<android.graphics.Bitmap> getFramesAtIndex(int, int, android.media.MediaMetadataRetriever.BitmapParams);
+ method public android.graphics.Bitmap getImageAtIndex(int, android.media.MediaMetadataRetriever.BitmapParams);
+ method public android.graphics.Bitmap getPrimaryImage(android.media.MediaMetadataRetriever.BitmapParams);
method public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int);
method public void release();
method public void setDataSource(java.lang.String) throws java.lang.IllegalArgumentException;
@@ -24086,6 +24104,13 @@
field public static final int OPTION_PREVIOUS_SYNC = 0; // 0x0
}
+ public static final class MediaMetadataRetriever.BitmapParams {
+ ctor public MediaMetadataRetriever.BitmapParams();
+ method public android.graphics.Bitmap.Config getActualConfig();
+ method public android.graphics.Bitmap.Config getPreferredConfig();
+ method public void setPreferredConfig(android.graphics.Bitmap.Config);
+ }
+
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;
@@ -24333,7 +24358,6 @@
method public abstract android.media.MediaDrm.KeyRequest getDrmKeyRequest(byte[], byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer2.NoDrmSchemeException;
method public abstract java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer2.NoDrmSchemeException;
method public abstract long getDuration();
- method public abstract int getMediaPlayer2State();
method public abstract android.os.PersistableBundle getMetrics();
method public abstract android.media.PlaybackParams getPlaybackParams();
method public abstract int getSelectedTrack(int);
@@ -24359,33 +24383,35 @@
method public abstract void setPlaybackParams(android.media.PlaybackParams);
method public abstract void setSurface(android.view.Surface);
method public abstract void setSyncParams(android.media.SyncParams);
- field public static final int MEDIAPLAYER2_STATE_ERROR = 5; // 0x5
- field public static final int MEDIAPLAYER2_STATE_IDLE = 1; // 0x1
- field public static final int MEDIAPLAYER2_STATE_PAUSED = 3; // 0x3
- field public static final int MEDIAPLAYER2_STATE_PLAYING = 4; // 0x4
- field public static final int MEDIAPLAYER2_STATE_PREPARED = 2; // 0x2
- field public static final int MEDIA_CALL_ATTACH_AUX_EFFECT = 1; // 0x1
- field public static final int MEDIA_CALL_DESELECT_TRACK = 2; // 0x2
- field public static final int MEDIA_CALL_LOOP_CURRENT = 3; // 0x3
- field public static final int MEDIA_CALL_PAUSE = 4; // 0x4
- field public static final int MEDIA_CALL_PLAY = 5; // 0x5
- field public static final int MEDIA_CALL_PREPARE = 6; // 0x6
- field public static final int MEDIA_CALL_RELEASE_DRM = 12; // 0xc
- field public static final int MEDIA_CALL_RESTORE_DRM_KEYS = 13; // 0xd
- field public static final int MEDIA_CALL_SEEK_TO = 14; // 0xe
- field public static final int MEDIA_CALL_SELECT_TRACK = 15; // 0xf
- field public static final int MEDIA_CALL_SET_AUDIO_ATTRIBUTES = 16; // 0x10
- field public static final int MEDIA_CALL_SET_AUDIO_SESSION_ID = 17; // 0x11
- field public static final int MEDIA_CALL_SET_AUX_EFFECT_SEND_LEVEL = 18; // 0x12
- field public static final int MEDIA_CALL_SET_DATA_SOURCE = 19; // 0x13
- field public static final int MEDIA_CALL_SET_NEXT_DATA_SOURCE = 22; // 0x16
- field public static final int MEDIA_CALL_SET_NEXT_DATA_SOURCES = 23; // 0x17
- field public static final int MEDIA_CALL_SET_PLAYBACK_PARAMS = 24; // 0x18
- field public static final int MEDIA_CALL_SET_PLAYBACK_SPEED = 25; // 0x19
- field public static final int MEDIA_CALL_SET_PLAYER_VOLUME = 26; // 0x1a
- field public static final int MEDIA_CALL_SET_SURFACE = 27; // 0x1b
- field public static final int MEDIA_CALL_SET_SYNC_PARAMS = 28; // 0x1c
- field public static final int MEDIA_CALL_SKIP_TO_NEXT = 29; // 0x1d
+ field public static final int CALL_COMPLETED_ATTACH_AUX_EFFECT = 1; // 0x1
+ field public static final int CALL_COMPLETED_DESELECT_TRACK = 2; // 0x2
+ field public static final int CALL_COMPLETED_LOOP_CURRENT = 3; // 0x3
+ field public static final int CALL_COMPLETED_PAUSE = 4; // 0x4
+ field public static final int CALL_COMPLETED_PLAY = 5; // 0x5
+ field public static final int CALL_COMPLETED_PREPARE = 6; // 0x6
+ field public static final int CALL_COMPLETED_RELEASE_DRM = 12; // 0xc
+ field public static final int CALL_COMPLETED_RESTORE_DRM_KEYS = 13; // 0xd
+ field public static final int CALL_COMPLETED_SEEK_TO = 14; // 0xe
+ field public static final int CALL_COMPLETED_SELECT_TRACK = 15; // 0xf
+ field public static final int CALL_COMPLETED_SET_AUDIO_ATTRIBUTES = 16; // 0x10
+ field public static final int CALL_COMPLETED_SET_AUDIO_SESSION_ID = 17; // 0x11
+ field public static final int CALL_COMPLETED_SET_AUX_EFFECT_SEND_LEVEL = 18; // 0x12
+ field public static final int CALL_COMPLETED_SET_DATA_SOURCE = 19; // 0x13
+ field public static final int CALL_COMPLETED_SET_NEXT_DATA_SOURCE = 22; // 0x16
+ field public static final int CALL_COMPLETED_SET_NEXT_DATA_SOURCES = 23; // 0x17
+ field public static final int CALL_COMPLETED_SET_PLAYBACK_PARAMS = 24; // 0x18
+ field public static final int CALL_COMPLETED_SET_PLAYBACK_SPEED = 25; // 0x19
+ field public static final int CALL_COMPLETED_SET_PLAYER_VOLUME = 26; // 0x1a
+ field public static final int CALL_COMPLETED_SET_SURFACE = 27; // 0x1b
+ field public static final int CALL_COMPLETED_SET_SYNC_PARAMS = 28; // 0x1c
+ field public static final int CALL_COMPLETED_SKIP_TO_NEXT = 29; // 0x1d
+ field public static final int CALL_STATUS_BAD_VALUE = 2; // 0x2
+ field public static final int CALL_STATUS_ERROR_IO = 4; // 0x4
+ field public static final int CALL_STATUS_ERROR_UNKNOWN = -2147483648; // 0x80000000
+ field public static final int CALL_STATUS_INVALID_OPERATION = 1; // 0x1
+ field public static final int CALL_STATUS_NO_DRM_SCHEME = 5; // 0x5
+ field public static final int CALL_STATUS_NO_ERROR = 0; // 0x0
+ field public static final int CALL_STATUS_PERMISSION_DENIED = 3; // 0x3
field public static final int MEDIA_ERROR_IO = -1004; // 0xfffffc14
field public static final int MEDIA_ERROR_MALFORMED = -1007; // 0xfffffc11
field public static final int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200; // 0xc8
@@ -24435,7 +24461,7 @@
public static abstract class MediaPlayer2.MediaPlayer2EventCallback {
ctor public MediaPlayer2.MediaPlayer2EventCallback();
- method public void onCallComplete(android.media.MediaPlayer2, android.media.DataSourceDesc, int, int);
+ method public void onCallCompleted(android.media.MediaPlayer2, android.media.DataSourceDesc, int, int);
method public void onCommandLabelReached(android.media.MediaPlayer2, java.lang.Object);
method public void onError(android.media.MediaPlayer2, android.media.DataSourceDesc, int, int);
method public void onInfo(android.media.MediaPlayer2, android.media.DataSourceDesc, int, int);
@@ -27573,17 +27599,17 @@
field public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1; // 0x1
field public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3; // 0x3
field public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2; // 0x2
- field public static final int TYPE_BLUETOOTH = 7; // 0x7
- field public static final int TYPE_DUMMY = 8; // 0x8
- field public static final int TYPE_ETHERNET = 9; // 0x9
- field public static final int TYPE_MOBILE = 0; // 0x0
- field public static final int TYPE_MOBILE_DUN = 4; // 0x4
+ field public static final deprecated int TYPE_BLUETOOTH = 7; // 0x7
+ field public static final deprecated int TYPE_DUMMY = 8; // 0x8
+ field public static final deprecated int TYPE_ETHERNET = 9; // 0x9
+ field public static final deprecated int TYPE_MOBILE = 0; // 0x0
+ field public static final deprecated int TYPE_MOBILE_DUN = 4; // 0x4
field public static final deprecated int TYPE_MOBILE_HIPRI = 5; // 0x5
field public static final deprecated int TYPE_MOBILE_MMS = 2; // 0x2
field public static final deprecated int TYPE_MOBILE_SUPL = 3; // 0x3
- field public static final int TYPE_VPN = 17; // 0x11
- field public static final int TYPE_WIFI = 1; // 0x1
- field public static final int TYPE_WIMAX = 6; // 0x6
+ field public static final deprecated int TYPE_VPN = 17; // 0x11
+ field public static final deprecated int TYPE_WIFI = 1; // 0x1
+ field public static final deprecated int TYPE_WIMAX = 6; // 0x6
}
public static class ConnectivityManager.NetworkCallback {
@@ -27860,16 +27886,16 @@
method public int describeContents();
method public android.net.NetworkInfo.DetailedState getDetailedState();
method public java.lang.String getExtraInfo();
- method public java.lang.String getReason();
- method public android.net.NetworkInfo.State getState();
+ method public deprecated java.lang.String getReason();
+ method public deprecated android.net.NetworkInfo.State getState();
method public int getSubtype();
method public java.lang.String getSubtypeName();
- method public int getType();
- method public java.lang.String getTypeName();
- method public boolean isAvailable();
+ method public deprecated int getType();
+ method public deprecated java.lang.String getTypeName();
+ method public deprecated boolean isAvailable();
method public boolean isConnected();
- method public boolean isConnectedOrConnecting();
- method public boolean isFailover();
+ method public deprecated boolean isConnectedOrConnecting();
+ method public deprecated boolean isFailover();
method public deprecated boolean isRoaming();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
@@ -37136,6 +37162,7 @@
field public static final java.lang.String ACTION_CAST_SETTINGS = "android.settings.CAST_SETTINGS";
field public static final java.lang.String ACTION_CHANNEL_NOTIFICATION_SETTINGS = "android.settings.CHANNEL_NOTIFICATION_SETTINGS";
field public static final java.lang.String ACTION_DATA_ROAMING_SETTINGS = "android.settings.DATA_ROAMING_SETTINGS";
+ field public static final java.lang.String ACTION_DATA_USAGE_SETTINGS = "android.settings.DATA_USAGE_SETTINGS";
field public static final java.lang.String ACTION_DATE_SETTINGS = "android.settings.DATE_SETTINGS";
field public static final java.lang.String ACTION_DEVICE_INFO_SETTINGS = "android.settings.DEVICE_INFO_SETTINGS";
field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
@@ -39992,8 +40019,8 @@
field public static final int REASON_UNAUTOBUNDLED = 16; // 0x10
field public static final int REASON_USER_STOPPED = 6; // 0x6
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
- field public static final int SUPPRESSED_EFFECT_SCREEN_OFF = 1; // 0x1
- field public static final int SUPPRESSED_EFFECT_SCREEN_ON = 2; // 0x2
+ field public static final deprecated int SUPPRESSED_EFFECT_SCREEN_OFF = 1; // 0x1
+ field public static final deprecated int SUPPRESSED_EFFECT_SCREEN_ON = 2; // 0x2
}
public static class NotificationListenerService.Ranking {
@@ -42131,11 +42158,9 @@
package android.telephony {
public final class AccessNetworkConstants {
- ctor public AccessNetworkConstants();
}
public static final class AccessNetworkConstants.AccessNetworkType {
- ctor public AccessNetworkConstants.AccessNetworkType();
field public static final int CDMA2000 = 4; // 0x4
field public static final int EUTRAN = 3; // 0x3
field public static final int GERAN = 1; // 0x1
@@ -42145,7 +42170,6 @@
}
public static final class AccessNetworkConstants.EutranBand {
- ctor public AccessNetworkConstants.EutranBand();
field public static final int BAND_1 = 1; // 0x1
field public static final int BAND_10 = 10; // 0xa
field public static final int BAND_11 = 11; // 0xb
@@ -42197,7 +42221,6 @@
}
public static final class AccessNetworkConstants.GeranBand {
- ctor public AccessNetworkConstants.GeranBand();
field public static final int BAND_450 = 3; // 0x3
field public static final int BAND_480 = 4; // 0x4
field public static final int BAND_710 = 5; // 0x5
@@ -42215,7 +42238,6 @@
}
public static final class AccessNetworkConstants.UtranBand {
- ctor public AccessNetworkConstants.UtranBand();
field public static final int BAND_1 = 1; // 0x1
field public static final int BAND_10 = 10; // 0xa
field public static final int BAND_11 = 11; // 0xb
@@ -42656,7 +42678,8 @@
}
public class NetworkScan {
- method public void stop() throws android.os.RemoteException;
+ method public deprecated void stop() throws android.os.RemoteException;
+ method public void stopScan();
field public static final int ERROR_INTERRUPTED = 10002; // 0x2712
field public static final int ERROR_INVALID_SCAN = 2; // 0x2
field public static final int ERROR_INVALID_SCANID = 10001; // 0x2711
@@ -43058,8 +43081,6 @@
method public android.telephony.TelephonyManager createForPhoneAccountHandle(android.telecom.PhoneAccountHandle);
method public android.telephony.TelephonyManager createForSubscriptionId(int);
method public java.util.List<android.telephony.CellInfo> getAllCellInfo();
- method public int getAndroidCarrierIdForSubscription();
- method public java.lang.CharSequence getAndroidCarrierNameForSubscription();
method public int getCallState();
method public android.os.PersistableBundle getCarrierConfig();
method public deprecated android.telephony.CellLocation getCellLocation();
@@ -43090,6 +43111,8 @@
method public int getPhoneType();
method public android.telephony.ServiceState getServiceState();
method public android.telephony.SignalStrength getSignalStrength();
+ method public int getSimCarrierId();
+ method public java.lang.CharSequence getSimCarrierIdName();
method public java.lang.String getSimCountryIso();
method public java.lang.String getSimOperator();
method public java.lang.String getSimOperatorName();
@@ -43121,7 +43144,8 @@
method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
method public boolean isWorldPhone();
method public void listen(android.telephony.PhoneStateListener, int);
- method public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, android.telephony.TelephonyScanManager.NetworkScanCallback);
+ method public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback);
+ method public deprecated android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, android.telephony.TelephonyScanManager.NetworkScanCallback);
method public void sendDialerSpecialCode(java.lang.String);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
@@ -46609,8 +46633,8 @@
}
public final class DisplayCutout {
- ctor public DisplayCutout(android.graphics.Rect, android.graphics.Region);
- method public android.graphics.Region getBounds();
+ ctor public DisplayCutout(android.graphics.Rect, java.util.List<android.graphics.Rect>);
+ method public java.util.List<android.graphics.Rect> getBoundingRects();
method public int getSafeInsetBottom();
method public int getSafeInsetLeft();
method public int getSafeInsetRight();
@@ -49684,9 +49708,9 @@
field public static final int LAST_SUB_WINDOW = 1999; // 0x7cf
field public static final int LAST_SYSTEM_WINDOW = 2999; // 0xbb7
field public static final int LAYOUT_CHANGED = 1; // 0x1
- field public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS = 1; // 0x1
field public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT = 0; // 0x0
field public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER = 2; // 0x2
+ field public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES = 1; // 0x1
field public static final int MEMORY_TYPE_CHANGED = 256; // 0x100
field public static final deprecated int MEMORY_TYPE_GPU = 2; // 0x2
field public static final deprecated int MEMORY_TYPE_HARDWARE = 1; // 0x1
@@ -51022,6 +51046,77 @@
package android.view.textclassifier {
+ public abstract class Logger {
+ ctor public Logger(android.view.textclassifier.Logger.Config);
+ method public java.text.BreakIterator getTokenIterator(java.util.Locale);
+ method public boolean isSmartSelection(java.lang.String);
+ method public final void logSelectionActionEvent(int, int, int);
+ method public final void logSelectionActionEvent(int, int, int, android.view.textclassifier.TextClassification);
+ method public final void logSelectionModifiedEvent(int, int);
+ method public final void logSelectionModifiedEvent(int, int, android.view.textclassifier.TextClassification);
+ method public final void logSelectionModifiedEvent(int, int, android.view.textclassifier.TextSelection);
+ method public final void logSelectionStartedEvent(int, int);
+ method public abstract void writeEvent(android.view.textclassifier.SelectionEvent);
+ field public static final int OUT_OF_BOUNDS = 2147483647; // 0x7fffffff
+ field public static final int OUT_OF_BOUNDS_NEGATIVE = -2147483648; // 0x80000000
+ field public static final java.lang.String WIDGET_CUSTOM_EDITTEXT = "customedit";
+ field public static final java.lang.String WIDGET_CUSTOM_TEXTVIEW = "customview";
+ field public static final java.lang.String WIDGET_CUSTOM_UNSELECTABLE_TEXTVIEW = "nosel-customview";
+ field public static final java.lang.String WIDGET_EDITTEXT = "edittext";
+ field public static final java.lang.String WIDGET_EDIT_WEBVIEW = "edit-webview";
+ field public static final java.lang.String WIDGET_TEXTVIEW = "textview";
+ field public static final java.lang.String WIDGET_UNKNOWN = "unknown";
+ field public static final java.lang.String WIDGET_UNSELECTABLE_TEXTVIEW = "nosel-textview";
+ field public static final java.lang.String WIDGET_WEBVIEW = "webview";
+ }
+
+ public static final class Logger.Config {
+ ctor public Logger.Config(android.content.Context, java.lang.String, java.lang.String);
+ method public java.lang.String getPackageName();
+ method public java.lang.String getWidgetType();
+ method public java.lang.String getWidgetVersion();
+ }
+
+ public final class SelectionEvent implements android.os.Parcelable {
+ method public int describeContents();
+ method public long getDurationSincePreviousEvent();
+ method public long getDurationSinceSessionStart();
+ method public int getEnd();
+ method public java.lang.String getEntityType();
+ method public int getEventIndex();
+ method public long getEventTime();
+ method public int getEventType();
+ method public int getInvocationMethod();
+ method public java.lang.String getPackageName();
+ method public java.lang.String getSessionId();
+ method public java.lang.String getSignature();
+ method public int getSmartEnd();
+ method public int getSmartStart();
+ method public int getStart();
+ method public java.lang.String getWidgetType();
+ method public java.lang.String getWidgetVersion();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int ACTION_ABANDON = 107; // 0x6b
+ field public static final int ACTION_COPY = 101; // 0x65
+ field public static final int ACTION_CUT = 103; // 0x67
+ field public static final int ACTION_DRAG = 106; // 0x6a
+ field public static final int ACTION_OTHER = 108; // 0x6c
+ field public static final int ACTION_OVERTYPE = 100; // 0x64
+ field public static final int ACTION_PASTE = 102; // 0x66
+ field public static final int ACTION_RESET = 201; // 0xc9
+ field public static final int ACTION_SELECT_ALL = 200; // 0xc8
+ field public static final int ACTION_SHARE = 104; // 0x68
+ field public static final int ACTION_SMART_SHARE = 105; // 0x69
+ field public static final android.os.Parcelable.Creator<android.view.textclassifier.SelectionEvent> CREATOR;
+ field public static final int EVENT_AUTO_SELECTION = 5; // 0x5
+ field public static final int EVENT_SELECTION_MODIFIED = 2; // 0x2
+ field public static final int EVENT_SELECTION_STARTED = 1; // 0x1
+ field public static final int EVENT_SMART_SELECTION_MULTI = 4; // 0x4
+ field public static final int EVENT_SMART_SELECTION_SINGLE = 3; // 0x3
+ field public static final int INVOCATION_LINK = 2; // 0x2
+ field public static final int INVOCATION_MANUAL = 1; // 0x1
+ }
+
public final class TextClassification implements android.os.Parcelable {
method public int describeContents();
method public float getConfidenceScore(java.lang.String);
@@ -51078,7 +51173,7 @@
method public default android.view.textclassifier.TextClassification classifyText(java.lang.CharSequence, int, int, android.os.LocaleList);
method public default android.view.textclassifier.TextLinks generateLinks(java.lang.CharSequence, android.view.textclassifier.TextLinks.Options);
method public default android.view.textclassifier.TextLinks generateLinks(java.lang.CharSequence);
- method public default android.view.textclassifier.logging.Logger getLogger(android.view.textclassifier.logging.Logger.Config);
+ method public default android.view.textclassifier.Logger getLogger(android.view.textclassifier.Logger.Config);
method public default int getMaxGenerateLinksTextLength();
method public default android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.view.textclassifier.TextSelection.Options);
method public default android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
@@ -51191,78 +51286,6 @@
}
-package android.view.textclassifier.logging {
-
- public abstract class Logger {
- ctor public Logger(android.view.textclassifier.logging.Logger.Config);
- method public java.text.BreakIterator getTokenIterator(java.util.Locale);
- method public boolean isSmartSelection(java.lang.String);
- method public final void logSelectionActionEvent(int, int, int);
- method public final void logSelectionActionEvent(int, int, int, android.view.textclassifier.TextClassification);
- method public final void logSelectionModifiedEvent(int, int);
- method public final void logSelectionModifiedEvent(int, int, android.view.textclassifier.TextClassification);
- method public final void logSelectionModifiedEvent(int, int, android.view.textclassifier.TextSelection);
- method public final void logSelectionStartedEvent(int, int);
- method public abstract void writeEvent(android.view.textclassifier.logging.SelectionEvent);
- field public static final int OUT_OF_BOUNDS = 2147483647; // 0x7fffffff
- field public static final int OUT_OF_BOUNDS_NEGATIVE = -2147483648; // 0x80000000
- field public static final java.lang.String WIDGET_CUSTOM_EDITTEXT = "customedit";
- field public static final java.lang.String WIDGET_CUSTOM_TEXTVIEW = "customview";
- field public static final java.lang.String WIDGET_CUSTOM_UNSELECTABLE_TEXTVIEW = "nosel-customview";
- field public static final java.lang.String WIDGET_EDITTEXT = "edittext";
- field public static final java.lang.String WIDGET_EDIT_WEBVIEW = "edit-webview";
- field public static final java.lang.String WIDGET_TEXTVIEW = "textview";
- field public static final java.lang.String WIDGET_UNKNOWN = "unknown";
- field public static final java.lang.String WIDGET_UNSELECTABLE_TEXTVIEW = "nosel-textview";
- field public static final java.lang.String WIDGET_WEBVIEW = "webview";
- }
-
- public static final class Logger.Config {
- ctor public Logger.Config(android.content.Context, java.lang.String, java.lang.String);
- method public java.lang.String getPackageName();
- method public java.lang.String getWidgetType();
- method public java.lang.String getWidgetVersion();
- }
-
- public final class SelectionEvent {
- method public long getDurationSincePreviousEvent();
- method public long getDurationSinceSessionStart();
- method public int getEnd();
- method public java.lang.String getEntityType();
- method public int getEventIndex();
- method public long getEventTime();
- method public int getEventType();
- method public int getInvocationMethod();
- method public java.lang.String getPackageName();
- method public java.lang.String getSessionId();
- method public java.lang.String getSignature();
- method public int getSmartEnd();
- method public int getSmartStart();
- method public int getStart();
- method public java.lang.String getWidgetType();
- method public java.lang.String getWidgetVersion();
- field public static final int ACTION_ABANDON = 107; // 0x6b
- field public static final int ACTION_COPY = 101; // 0x65
- field public static final int ACTION_CUT = 103; // 0x67
- field public static final int ACTION_DRAG = 106; // 0x6a
- field public static final int ACTION_OTHER = 108; // 0x6c
- field public static final int ACTION_OVERTYPE = 100; // 0x64
- field public static final int ACTION_PASTE = 102; // 0x66
- field public static final int ACTION_RESET = 201; // 0xc9
- field public static final int ACTION_SELECT_ALL = 200; // 0xc8
- field public static final int ACTION_SHARE = 104; // 0x68
- field public static final int ACTION_SMART_SHARE = 105; // 0x69
- field public static final int EVENT_AUTO_SELECTION = 5; // 0x5
- field public static final int EVENT_SELECTION_MODIFIED = 2; // 0x2
- field public static final int EVENT_SELECTION_STARTED = 1; // 0x1
- field public static final int EVENT_SMART_SELECTION_MULTI = 4; // 0x4
- field public static final int EVENT_SMART_SELECTION_SINGLE = 3; // 0x3
- field public static final int INVOCATION_LINK = 2; // 0x2
- field public static final int INVOCATION_MANUAL = 1; // 0x1
- }
-
-}
-
package android.view.textservice {
public final class SentenceSuggestionsInfo implements android.os.Parcelable {
@@ -53382,6 +53405,9 @@
public final class Magnifier {
ctor public Magnifier(android.view.View);
method public void dismiss();
+ method public int getHeight();
+ method public int getWidth();
+ method public float getZoom();
method public void show(float, float);
method public void update();
}
diff --git a/api/removed.txt b/api/removed.txt
index b8e2b98..a5370f4 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -152,6 +152,11 @@
method public deprecated boolean clipRegion(android.graphics.Region);
}
+ public final class ImageDecoder implements java.lang.AutoCloseable {
+ method public deprecated boolean getAsAlphaMask();
+ method public deprecated android.graphics.ImageDecoder setAsAlphaMask(boolean);
+ }
+
public deprecated class LayerRasterizer extends android.graphics.Rasterizer {
ctor public LayerRasterizer();
method public void addLayer(android.graphics.Paint, float, float);
diff --git a/api/system-current.txt b/api/system-current.txt
index 4fc2d21..5ec84fe 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -261,6 +261,7 @@
public class AppOpsManager {
method public static java.lang.String[] getOpStrs();
+ method public void setMode(java.lang.String, int, java.lang.String, int);
method public void setUidMode(java.lang.String, int, int);
field public static final java.lang.String OPSTR_ACCEPT_HANDOVER = "android:accept_handover";
field public static final java.lang.String OPSTR_ACCESS_NOTIFICATIONS = "android:access_notifications";
@@ -377,6 +378,7 @@
method public boolean setBroadcastSubscriber(long, long, android.app.PendingIntent);
method public boolean setDataFetchOperation(long, android.app.PendingIntent);
field public static final java.lang.String ACTION_STATSD_STARTED = "android.app.action.STATSD_STARTED";
+ field public static final java.lang.String EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES = "android.app.extra.STATS_BROADCAST_SUBSCRIBER_COOKIES";
field public static final java.lang.String EXTRA_STATS_CONFIG_KEY = "android.app.extra.STATS_CONFIG_KEY";
field public static final java.lang.String EXTRA_STATS_CONFIG_UID = "android.app.extra.STATS_CONFIG_UID";
field public static final java.lang.String EXTRA_STATS_DIMENSIONS_VALUE = "android.app.extra.STATS_DIMENSIONS_VALUE";
@@ -716,7 +718,9 @@
}
public static final class UsageEvents.Event {
+ method public java.lang.String getNotificationChannelId();
method public int getStandbyBucket();
+ field public static final int NOTIFICATION_INTERRUPTION = 12; // 0xc
field public static final int NOTIFICATION_SEEN = 10; // 0xa
field public static final int STANDBY_BUCKET_CHANGED = 11; // 0xb
}
@@ -840,6 +844,7 @@
}
public class Intent implements java.lang.Cloneable android.os.Parcelable {
+ field public static final java.lang.String ACTION_BATTERY_LEVEL_CHANGED = "android.intent.action.BATTERY_LEVEL_CHANGED";
field public static final java.lang.String ACTION_CALL_EMERGENCY = "android.intent.action.CALL_EMERGENCY";
field public static final java.lang.String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED";
field public static final java.lang.String ACTION_FACTORY_RESET = "android.intent.action.FACTORY_RESET";
@@ -3612,6 +3617,11 @@
package android.os {
+ public class BatteryManager {
+ field public static final java.lang.String EXTRA_EVENTS = "android.os.extra.EVENTS";
+ field public static final java.lang.String EXTRA_EVENT_TIMESTAMP = "android.os.extra.EVENT_TIMESTAMP";
+ }
+
public final class ConfigUpdate {
field public static final java.lang.String ACTION_UPDATE_CARRIER_PROVISIONING_URLS = "android.intent.action.UPDATE_CARRIER_PROVISIONING_URLS";
field public static final java.lang.String ACTION_UPDATE_CT_LOGS = "android.intent.action.UPDATE_CT_LOGS";
@@ -4697,9 +4707,11 @@
public abstract class TextClassifierService extends android.app.Service {
ctor public TextClassifierService();
+ method public final android.view.textclassifier.TextClassifier getLocalTextClassifier();
method public final android.os.IBinder onBind(android.content.Intent);
method public abstract void onClassifyText(java.lang.CharSequence, int, int, android.view.textclassifier.TextClassification.Options, android.os.CancellationSignal, android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextClassification>);
method public abstract void onGenerateLinks(java.lang.CharSequence, android.view.textclassifier.TextLinks.Options, android.os.CancellationSignal, android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextLinks>);
+ method public void onSelectionEvent(android.view.textclassifier.SelectionEvent);
method public abstract void onSuggestSelection(java.lang.CharSequence, int, int, android.view.textclassifier.TextSelection.Options, android.os.CancellationSignal, android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextSelection>);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.textclassifier.TextClassifierService";
}
@@ -4995,7 +5007,6 @@
package android.telephony {
public static final class AccessNetworkConstants.TransportType {
- ctor public AccessNetworkConstants.TransportType();
field public static final int WLAN = 2; // 0x2
field public static final int WWAN = 1; // 0x1
}
@@ -5251,12 +5262,13 @@
}
public class UiccSlotInfo implements android.os.Parcelable {
- ctor public UiccSlotInfo(boolean, boolean, java.lang.String, int, int);
+ ctor public UiccSlotInfo(boolean, boolean, java.lang.String, int, int, boolean);
method public int describeContents();
method public java.lang.String getCardId();
method public int getCardStateInfo();
method public boolean getIsActive();
method public boolean getIsEuicc();
+ method public boolean getIsExtendedApduSupported();
method public int getLogicalSlotIdx();
method public void writeToParcel(android.os.Parcel, int);
field public static final int CARD_STATE_INFO_ABSENT = 1; // 0x1
@@ -5495,6 +5507,9 @@
}
public final class ImsCallProfile implements android.os.Parcelable {
+ ctor public ImsCallProfile();
+ ctor public ImsCallProfile(int, int);
+ ctor public ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile);
method public int describeContents();
method public java.lang.String getCallExtra(java.lang.String);
method public java.lang.String getCallExtra(java.lang.String, java.lang.String);
@@ -5518,6 +5533,7 @@
method public void setCallExtraInt(java.lang.String, int);
method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
method public void updateCallType(android.telephony.ims.ImsCallProfile);
+ method public void updateMediaProfile(android.telephony.ims.ImsCallProfile);
method public void writeToParcel(android.os.Parcel, int);
field public static final int CALL_RESTRICT_CAUSE_DISABLED = 2; // 0x2
field public static final int CALL_RESTRICT_CAUSE_HD = 3; // 0x3
@@ -5855,6 +5871,7 @@
}
public final class ImsStreamMediaProfile implements android.os.Parcelable {
+ ctor public ImsStreamMediaProfile(int, int, int, int, int);
method public void copyFrom(android.telephony.ims.ImsStreamMediaProfile);
method public int describeContents();
method public int getAudioDirection();
@@ -6112,19 +6129,24 @@
}
public final class ImsFeatureConfiguration implements android.os.Parcelable {
- ctor public ImsFeatureConfiguration();
method public int describeContents();
- method public int[] getServiceFeatures();
+ method public java.util.Set<android.telephony.ims.stub.ImsFeatureConfiguration.FeatureSlotPair> getServiceFeatures();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.telephony.ims.stub.ImsFeatureConfiguration> CREATOR;
}
public static class ImsFeatureConfiguration.Builder {
ctor public ImsFeatureConfiguration.Builder();
- method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int);
+ method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int, int);
method public android.telephony.ims.stub.ImsFeatureConfiguration build();
}
+ public static final class ImsFeatureConfiguration.FeatureSlotPair {
+ ctor public ImsFeatureConfiguration.FeatureSlotPair(int, int);
+ field public final int featureType;
+ field public final int slotId;
+ }
+
public class ImsMultiEndpointImplBase {
ctor public ImsMultiEndpointImplBase();
method public final void onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>);
@@ -6662,8 +6684,10 @@
method public abstract android.view.View findFocus(android.view.View);
method public abstract android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider();
method public abstract android.os.Handler getHandler(android.os.Handler);
+ method public default boolean isVisibleToUserForAutofill(int);
method public abstract void onActivityResult(int, int, android.content.Intent);
method public abstract void onAttachedToWindow();
+ method public default boolean onCheckIsTextEditor();
method public abstract void onConfigurationChanged(android.content.res.Configuration);
method public abstract android.view.inputmethod.InputConnection onCreateInputConnection(android.view.inputmethod.EditorInfo);
method public abstract void onDetachedFromWindow();
diff --git a/api/test-current.txt b/api/test-current.txt
index 9d67f4c..54ddd5d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1,3 +1,12 @@
+package android {
+
+ public static final class Manifest.permission {
+ field public static final java.lang.String BRIGHTNESS_SLIDER_USAGE = "android.permission.BRIGHTNESS_SLIDER_USAGE";
+ field public static final java.lang.String CONFIGURE_DISPLAY_BRIGHTNESS = "android.permission.CONFIGURE_DISPLAY_BRIGHTNESS";
+ }
+
+}
+
package android.animation {
public class ValueAnimator extends android.animation.Animator {
diff --git a/cmds/incidentd/Android.mk b/cmds/incidentd/Android.mk
index 008a1bf..db864ae 100644
--- a/cmds/incidentd/Android.mk
+++ b/cmds/incidentd/Android.mk
@@ -41,20 +41,16 @@
LOCAL_CFLAGS += \
-Os
endif
-
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
LOCAL_SHARED_LIBRARIES := \
libbase \
libbinder \
- libcutils \
libdebuggerd_client \
libdumputils \
libincident \
liblog \
- libprotobuf-cpp-lite \
libprotoutil \
- libselinux \
libservices \
libutils
@@ -122,14 +118,12 @@
LOCAL_SHARED_LIBRARIES := \
libbase \
libbinder \
- libcutils \
libdebuggerd_client \
libdumputils \
libincident \
liblog \
libprotobuf-cpp-lite \
libprotoutil \
- libselinux \
libservices \
libutils \
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp
index 28fb38a..d02b4dd 100644
--- a/cmds/incidentd/src/IncidentService.cpp
+++ b/cmds/incidentd/src/IncidentService.cpp
@@ -358,8 +358,7 @@
return error;
}
fprintf(err, "Read %zu bytes\n", buf.size());
- auto data = buf.data();
- PrivacyBuffer pBuf(p, data);
+ PrivacyBuffer pBuf(p, buf.data());
PrivacySpec spec = PrivacySpec::new_spec(argCount > 3 ? atoi(args[3]) : -1);
error = pBuf.strip(spec);
diff --git a/cmds/incidentd/src/PrivacyBuffer.cpp b/cmds/incidentd/src/PrivacyBuffer.cpp
index 73ee1cb..f1f7c589 100644
--- a/cmds/incidentd/src/PrivacyBuffer.cpp
+++ b/cmds/incidentd/src/PrivacyBuffer.cpp
@@ -101,7 +101,7 @@
}
// ================================================================================
-PrivacyBuffer::PrivacyBuffer(const Privacy* policy, EncodedBuffer::iterator& data)
+PrivacyBuffer::PrivacyBuffer(const Privacy* policy, EncodedBuffer::iterator data)
: mPolicy(policy), mData(data), mProto(), mSize(0) {}
PrivacyBuffer::~PrivacyBuffer() {}
diff --git a/cmds/incidentd/src/PrivacyBuffer.h b/cmds/incidentd/src/PrivacyBuffer.h
index 92e1a25..cd29d8b 100644
--- a/cmds/incidentd/src/PrivacyBuffer.h
+++ b/cmds/incidentd/src/PrivacyBuffer.h
@@ -34,7 +34,7 @@
*/
class PrivacyBuffer {
public:
- PrivacyBuffer(const Privacy* policy, EncodedBuffer::iterator& data);
+ PrivacyBuffer(const Privacy* policy, EncodedBuffer::iterator data);
~PrivacyBuffer();
/**
@@ -60,7 +60,7 @@
private:
const Privacy* mPolicy;
- EncodedBuffer::iterator& mData;
+ EncodedBuffer::iterator mData;
ProtoOutputStream mProto;
size_t mSize;
diff --git a/cmds/incidentd/src/Reporter.cpp b/cmds/incidentd/src/Reporter.cpp
index 12764f8..fc8a6db 100644
--- a/cmds/incidentd/src/Reporter.cpp
+++ b/cmds/incidentd/src/Reporter.cpp
@@ -89,11 +89,11 @@
IncidentMetadata::SectionStats* ReportRequestSet::sectionStats(int id) {
if (mSectionStats.find(id) == mSectionStats.end()) {
- auto stats = mMetadata.add_sections();
- stats->set_id(id);
+ IncidentMetadata::SectionStats stats;
+ stats.set_id(id);
mSectionStats[id] = stats;
}
- return mSectionStats[id];
+ return &mSectionStats[id];
}
// ================================================================================
@@ -182,7 +182,7 @@
}
// Execute - go get the data and write it into the file descriptors.
- auto stats = batch.sectionStats(id);
+ IncidentMetadata::SectionStats* stats = batch.sectionStats(id);
int64_t startTime = uptimeMillis();
err = (*section)->Execute(&batch);
int64_t endTime = uptimeMillis();
diff --git a/cmds/incidentd/src/Reporter.h b/cmds/incidentd/src/Reporter.h
index ba8965e..f9a092a 100644
--- a/cmds/incidentd/src/Reporter.h
+++ b/cmds/incidentd/src/Reporter.h
@@ -66,6 +66,7 @@
int mainFd() { return mMainFd; }
int mainDest() { return mMainDest; }
IncidentMetadata& metadata() { return mMetadata; }
+ map<int, IncidentMetadata::SectionStats>& allSectionStats() { return mSectionStats; }
bool containsSection(int id);
IncidentMetadata::SectionStats* sectionStats(int id);
@@ -77,7 +78,7 @@
int mMainDest;
IncidentMetadata mMetadata;
- map<int, IncidentMetadata::SectionStats*> mSectionStats;
+ map<int, IncidentMetadata::SectionStats> mSectionStats;
};
// ================================================================================
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 6dd76a8..5cde5a9 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -109,7 +109,7 @@
EncodedBuffer::iterator data = buffer.data();
PrivacyBuffer privacyBuffer(get_privacy_of_section(id), data);
int writeable = 0;
- auto stats = requests->sectionStats(id);
+ IncidentMetadata::SectionStats* stats = requests->sectionStats(id);
stats->set_dump_size_bytes(data.size());
stats->set_dump_duration_ms(buffer.durationMs());
@@ -215,23 +215,48 @@
MetadataSection::~MetadataSection() {}
status_t MetadataSection::Execute(ReportRequestSet* requests) const {
- std::string metadataBuf;
- requests->metadata().SerializeToString(&metadataBuf);
+ ProtoOutputStream proto;
+ IncidentMetadata metadata = requests->metadata();
+ proto.write(FIELD_TYPE_ENUM | IncidentMetadata::kDestFieldNumber, metadata.dest());
+ proto.write(FIELD_TYPE_INT32 | IncidentMetadata::kRequestSizeFieldNumber,
+ metadata.request_size());
+ proto.write(FIELD_TYPE_BOOL | IncidentMetadata::kUseDropboxFieldNumber, metadata.use_dropbox());
+ for (auto iter = requests->allSectionStats().begin(); iter != requests->allSectionStats().end();
+ iter++) {
+ IncidentMetadata::SectionStats stats = iter->second;
+ uint64_t token = proto.start(FIELD_TYPE_MESSAGE | IncidentMetadata::kSectionsFieldNumber);
+ proto.write(FIELD_TYPE_INT32 | IncidentMetadata::SectionStats::kIdFieldNumber, stats.id());
+ proto.write(FIELD_TYPE_BOOL | IncidentMetadata::SectionStats::kSuccessFieldNumber,
+ stats.success());
+ proto.write(FIELD_TYPE_INT32 | IncidentMetadata::SectionStats::kReportSizeBytesFieldNumber,
+ stats.report_size_bytes());
+ proto.write(FIELD_TYPE_INT64 | IncidentMetadata::SectionStats::kExecDurationMsFieldNumber,
+ stats.exec_duration_ms());
+ proto.write(FIELD_TYPE_INT32 | IncidentMetadata::SectionStats::kDumpSizeBytesFieldNumber,
+ stats.dump_size_bytes());
+ proto.write(FIELD_TYPE_INT64 | IncidentMetadata::SectionStats::kDumpDurationMsFieldNumber,
+ stats.dump_duration_ms());
+ proto.write(FIELD_TYPE_BOOL | IncidentMetadata::SectionStats::kTimedOutFieldNumber,
+ stats.timed_out());
+ proto.write(FIELD_TYPE_BOOL | IncidentMetadata::SectionStats::kIsTruncatedFieldNumber,
+ stats.is_truncated());
+ proto.end(token);
+ }
+
for (ReportRequestSet::iterator it = requests->begin(); it != requests->end(); it++) {
const sp<ReportRequest> request = *it;
- if (metadataBuf.empty() || request->fd < 0 || request->err != NO_ERROR) {
+ if (request->fd < 0 || request->err != NO_ERROR) {
continue;
}
- write_section_header(request->fd, id, metadataBuf.size());
- if (!WriteFully(request->fd, (uint8_t const*)metadataBuf.data(), metadataBuf.size())) {
+ write_section_header(request->fd, id, proto.size());
+ if (!proto.flush(request->fd)) {
ALOGW("Failed to write metadata to fd %d", request->fd);
// we don't fail if we can't write to a single request's fd.
}
}
- if (requests->mainFd() >= 0 && !metadataBuf.empty()) {
- write_section_header(requests->mainFd(), id, metadataBuf.size());
- if (!WriteFully(requests->mainFd(), (uint8_t const*)metadataBuf.data(),
- metadataBuf.size())) {
+ if (requests->mainFd() >= 0) {
+ write_section_header(requests->mainFd(), id, proto.size());
+ if (!proto.flush(requests->mainFd())) {
ALOGW("Failed to write metadata to dropbox fd %d", requests->mainFd());
return -1;
}
diff --git a/cmds/incidentd/testdata/metadata.txt b/cmds/incidentd/testdata/metadata.txt
new file mode 100644
index 0000000..cb79a3d
--- /dev/null
+++ b/cmds/incidentd/testdata/metadata.txt
Binary files differ
diff --git a/cmds/incidentd/tests/Reporter_test.cpp b/cmds/incidentd/tests/Reporter_test.cpp
index 955dbac..42d94f0 100644
--- a/cmds/incidentd/tests/Reporter_test.cpp
+++ b/cmds/incidentd/tests/Reporter_test.cpp
@@ -191,7 +191,7 @@
reporter->batch.add(r);
ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport(&size));
- auto metadata = reporter->batch.metadata();
+ IncidentMetadata metadata = reporter->batch.metadata();
EXPECT_EQ(IncidentMetadata_Destination_EXPLICIT, metadata.dest());
EXPECT_EQ(1, metadata.request_size());
EXPECT_TRUE(metadata.use_dropbox());
diff --git a/cmds/incidentd/tests/Section_test.cpp b/cmds/incidentd/tests/Section_test.cpp
index 1528224..55192d0 100644
--- a/cmds/incidentd/tests/Section_test.cpp
+++ b/cmds/incidentd/tests/Section_test.cpp
@@ -48,6 +48,15 @@
public:
virtual void SetUp() override { ASSERT_NE(tf.fd, -1); }
+ void printDebugString(std::string s) {
+ fprintf(stderr, "size: %zu\n", s.length());
+ for (size_t i = 0; i < s.length(); i++) {
+ char c = s[i];
+ fprintf(stderr, "\\x%x", c);
+ }
+ fprintf(stderr, "\n");
+ }
+
protected:
TemporaryFile tf;
ReportRequestSet requests;
@@ -103,14 +112,18 @@
TEST_F(SectionTest, MetadataSection) {
MetadataSection ms;
+ const std::string testFile = kTestDataPath + "metadata.txt";
+ std::string expect;
+ ASSERT_TRUE(ReadFileToString(testFile, &expect));
requests.setMainFd(STDOUT_FILENO);
+ requests.setMainDest(android::os::DEST_LOCAL);
requests.sectionStats(1)->set_success(true);
CaptureStdout();
ASSERT_EQ(NO_ERROR, ms.Execute(&requests));
- EXPECT_THAT(GetCapturedStdout(), StrEq("\x12\b(\x1"
- "2\x4\b\x1\x10\x1"));
+ // Notice message_lite.h ParseFromString doesn't work so we just match the bytes directly.
+ EXPECT_THAT(GetCapturedStdout(), StrEq(expect));
}
TEST_F(SectionTest, FileSection) {
diff --git a/cmds/statsd/OWNERS b/cmds/statsd/OWNERS
index 362d411..1315750 100644
--- a/cmds/statsd/OWNERS
+++ b/cmds/statsd/OWNERS
@@ -1,6 +1,11 @@
bookatz@google.com
+cjyu@google.com
+dwchen@google.com
jinyithu@google.com
+joeo@google.com
kwekua@google.com
+singhtejinder@google.com
stlafon@google.com
yaochen@google.com
yanglu@google.com
+yro@google.com
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 3127e94..02d4dc9 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -355,7 +355,6 @@
const ConfigKey& key = pair.first;
vector<uint8_t> data;
onDumpReportLocked(key, getElapsedRealtimeNs(), &data);
- // TODO: Add a guardrail to prevent accumulation of file on disk.
string file_name = StringPrintf("%s/%ld_%d_%lld", STATS_DATA_DIR,
(long)getWallClockSec(), key.GetUid(), (long long)key.GetId());
StorageManager::writeFile(file_name.c_str(), &data[0], data.size());
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 280081e..c5dfc44 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -55,18 +55,22 @@
class CompanionDeathRecipient : public IBinder::DeathRecipient {
public:
CompanionDeathRecipient(const sp<AlarmMonitor>& anomalyAlarmMonitor,
- const sp<AlarmMonitor>& periodicAlarmMonitor) :
- mAnomalyAlarmMonitor(anomalyAlarmMonitor),
- mPeriodicAlarmMonitor(periodicAlarmMonitor) {}
+ const sp<AlarmMonitor>& periodicAlarmMonitor,
+ const sp<StatsLogProcessor>& processor)
+ : mAnomalyAlarmMonitor(anomalyAlarmMonitor),
+ mPeriodicAlarmMonitor(periodicAlarmMonitor),
+ mProcessor(processor) {}
virtual void binderDied(const wp<IBinder>& who);
private:
- sp<AlarmMonitor> mAnomalyAlarmMonitor;
- sp<AlarmMonitor> mPeriodicAlarmMonitor;
+ sp<AlarmMonitor> mAnomalyAlarmMonitor;
+ sp<AlarmMonitor> mPeriodicAlarmMonitor;
+ sp<StatsLogProcessor> mProcessor;
};
void CompanionDeathRecipient::binderDied(const wp<IBinder>& who) {
ALOGW("statscompanion service died");
+ mProcessor->WriteDataToDisk();
mAnomalyAlarmMonitor->setStatsCompanionService(nullptr);
mPeriodicAlarmMonitor->setStatsCompanionService(nullptr);
SubscriberReporter::getInstance().setStatsCompanionService(nullptr);
@@ -817,8 +821,9 @@
"statscompanion unavailable despite it contacting statsd!");
}
VLOG("StatsService::statsCompanionReady linking to statsCompanion.");
- IInterface::asBinder(statsCompanion)->linkToDeath(
- new CompanionDeathRecipient(mAnomalyAlarmMonitor, mPeriodicAlarmMonitor));
+ IInterface::asBinder(statsCompanion)
+ ->linkToDeath(new CompanionDeathRecipient(
+ mAnomalyAlarmMonitor, mPeriodicAlarmMonitor, mProcessor));
mAnomalyAlarmMonitor->setStatsCompanionService(statsCompanion);
mPeriodicAlarmMonitor->setStatsCompanionService(statsCompanion);
SubscriberReporter::getInstance().setStatsCompanionService(statsCompanion);
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 30896e6..02b6124 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -210,10 +210,10 @@
*/
status_t cmd_dump_memory_info(FILE* out);
- /*
+ /*
* Clear all puller cached data
*/
- status_t cmd_clear_puller_cache(FILE* out);
+ status_t cmd_clear_puller_cache(FILE* out);
/**
* Update a configuration.
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
index 6ee51f3..133f33b 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
@@ -59,6 +59,12 @@
}
size_t AnomalyTracker::index(int64_t bucketNum) const {
+ if (bucketNum < 0) {
+ // To support this use-case, we can easily modify index to wrap around. But currently
+ // AnomalyTracker should never need this, so if it happens, it's a bug we should log.
+ // TODO: Audit this.
+ ALOGE("index() was passed a negative bucket number (%lld)!", (long long)bucketNum);
+ }
return bucketNum % mNumOfPastBuckets;
}
@@ -72,9 +78,7 @@
// The past packets are ancient. Empty out old mPastBuckets[i] values and reset
// mSumOverPastBuckets.
if (latestPastBucketNum - mMostRecentBucketNum >= mNumOfPastBuckets) {
- mPastBuckets.clear();
- mPastBuckets.resize(mNumOfPastBuckets);
- mSumOverPastBuckets.clear();
+ resetStorage();
} else {
for (int64_t i = std::max(0LL, (long long)(mMostRecentBucketNum - mNumOfPastBuckets + 1));
i <= latestPastBucketNum - mNumOfPastBuckets; i++) {
@@ -150,7 +154,7 @@
int64_t AnomalyTracker::getPastBucketValue(const MetricDimensionKey& key,
const int64_t& bucketNum) const {
- if (mNumOfPastBuckets == 0) {
+ if (mNumOfPastBuckets == 0 || bucketNum < 0) {
return 0;
}
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.h b/cmds/statsd/src/anomaly/AnomalyTracker.h
index e3f493c..d27dee8 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.h
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.h
@@ -110,7 +110,7 @@
// Number of past buckets. One less than the total number of buckets needed
// for the anomaly detection (since the current bucket is not in the past).
- int mNumOfPastBuckets;
+ const int mNumOfPastBuckets;
// The existing bucket list.
std::vector<shared_ptr<DimToValMap>> mPastBuckets;
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 9bfbd38..298f494 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -23,6 +23,7 @@
import "frameworks/base/cmds/statsd/src/atom_field_options.proto";
import "frameworks/base/core/proto/android/app/enums.proto";
+import "frameworks/base/core/proto/android/bluetooth/enums.proto";
import "frameworks/base/core/proto/android/os/enums.proto";
import "frameworks/base/core/proto/android/server/enums.proto";
import "frameworks/base/core/proto/android/telecomm/enums.proto";
@@ -106,6 +107,14 @@
KeyguardBouncerPasswordEntered keyguard_bouncer_password_entered = 64;
AppDied app_died=65;
ResourceConfigurationChanged resource_configuration_changed = 66;
+ BluetoothEnabledStateChanged bluetooth_enabled_state_changed = 67;
+ BluetoothConnectionStateChanged bluetooth_connection_state_changed = 68;
+ BluetoothA2dpAudioStateChanged bluetooth_a2dp_audio_state_changed = 69;
+ UsbConnectorStateChanged usb_connector_changed = 70;
+ SpeakerImpedanceReported speaker_impedance_reported = 71;
+ HardwareFailed hardware_failed = 72;
+ PhysicalDropDetected physical_drop_detected = 73;
+ ChargeCyclesReported charge_cycles_reported = 74;
// TODO: Reorder the numbering so that the most frequent occur events occur in the first 15.
}
@@ -904,6 +913,165 @@
}
/**
+ * Logs when Bluetooth is enabled and disabled.
+ *
+ * Logged from:
+ * services/core/java/com/android/server/BluetoothManagerService.java
+ */
+message BluetoothEnabledStateChanged {
+ repeated AttributionNode attribution_node = 1;
+ // Whether or not bluetooth is enabled on the device.
+ enum State {
+ UNKNOWN = 0;
+ ENABLED = 1;
+ DISABLED = 2;
+ }
+ optional State state = 2;
+ // The reason for being enabled/disabled.
+ // Eg. Airplane mode, crash, application request.
+ optional android.bluetooth.EnableDisableReasonEnum reason = 3;
+ // If the reason is an application request, this will be the package name.
+ optional string pkgName = 4;
+}
+
+/**
+ * Logs when a Bluetooth device connects and disconnects.
+ *
+ * Logged from:
+ * packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterProperties.java
+ */
+message BluetoothConnectionStateChanged {
+ // The state of the connection.
+ // Eg: CONNECTING, CONNECTED, DISCONNECTING, DISCONNECTED.
+ optional android.bluetooth.ConnectionStateEnum state = 1;
+ // An identifier that can be used to match connect and disconnect events.
+ // Currently is last two bytes of a hash of a device level ID and
+ // the mac address of the bluetooth device that is connected.
+ optional int32 obfuscated_id = 2;
+ // The profile that is connected. Eg. GATT, A2DP, HEADSET.
+ // From android.bluetooth.BluetoothAdapter.java
+ optional int32 bt_profile = 3;
+}
+
+/**
+ * Logs when Bluetooth A2dp audio streaming state changes.
+ *
+ * Logged from:
+ * TODO(b/73971848)
+ */
+message BluetoothA2dpAudioStateChanged {
+ // Whether or not audio is being played using Bluetooth A2dp.
+ enum State {
+ UNKNOWN = 0;
+ PLAY = 1;
+ STOP = 2;
+ }
+ optional State state = 1;
+}
+
+/**
+ * Logs when something is plugged into or removed from the USB-C connector.
+ *
+ * Logged from:
+ * Vendor USB HAL.
+ */
+message UsbConnectorStateChanged {
+ enum State {
+ DISCONNECTED = 0;
+ CONNECTED = 1;
+ }
+ optional State state = 1;
+}
+
+/**
+ * Logs the reported speaker impedance.
+ *
+ * Logged from:
+ * Vendor audio implementation.
+ */
+message SpeakerImpedanceReported {
+ optional int32 speaker_location = 1;
+ optional int32 impedance = 2;
+}
+
+/**
+ * Logs the report of a failed hardware.
+ *
+ * Logged from:
+ * Vendor HALs.
+ *
+ */
+message HardwareFailed {
+ enum HardwareType {
+ HARDWARE_FAILED_UNKNOWN = 0;
+ HARDWARE_FAILED_MICROPHONE = 1;
+ HARDWARE_FAILED_CODEC = 2;
+ HARDWARE_FAILED_SPEAKER = 3;
+ HARDWARE_FAILED_FINGERPRINT = 4;
+ }
+ optional HardwareType hardware_type = 1;
+
+ /* hardware_location allows vendors to differentiate between multiple instances of
+ * the same hardware_type. The specific locations are vendor defined integers,
+ * referring to board-specific numbering schemes.
+ */
+ optional int32 hardware_location = 2;
+
+ /* failure_code is specific to the HardwareType of the failed hardware.
+ * It should use the enum values defined below.
+ */
+ enum MicrophoneFailureCode {
+ MICROPHONE_FAILURE_COMPLETE = 0;
+ }
+ enum CodecFailureCode {
+ CODEC_FAILURE_COMPLETE = 0;
+ }
+ enum SpeakerFailureCode {
+ SPEAKER_FAILURE_COMPLETE = 0;
+ SPEAKER_FAILURE_HIGH_Z = 1;
+ SPEAKER_FAILURE_SHORT = 2;
+ }
+ enum FingerprintFailureCode {
+ FINGERPRINT_FAILURE_COMPLETE = 0;
+ FINGERPRINT_SENSOR_BROKEN = 1;
+ FINGERPRINT_TOO_MANY_DEAD_PIXELS = 2;
+ }
+ optional int32 failure_code = 3;
+}
+
+/**
+ * Log an event when the device has been physically dropped.
+ * Reported from the /vendor partition.
+ */
+message PhysicalDropDetected {
+ // Confidence that the event was actually a drop, 0 -> 100
+ optional int32 confidence_pctg = 1;
+ // Peak acceleration of the drop, in 1/1000s of a g.
+ optional int32 accel_peak_thousandths_g = 2;
+}
+
+/**
+ * Log bucketed battery charge cycles.
+ *
+ * Each bucket represents cycles of the battery past
+ * a given charge point. For example, bucket 1 is the
+ * lowest 1/8th of the battery, and bucket 8 is 100%.
+ *
+ * Logged from:
+ * /sys/class/power_supply/bms/cycle_count, via Vendor.
+ */
+message ChargeCyclesReported {
+ optional int32 cycle_bucket_1 = 1;
+ optional int32 cycle_bucket_2 = 2;
+ optional int32 cycle_bucket_3 = 3;
+ optional int32 cycle_bucket_4 = 4;
+ optional int32 cycle_bucket_5 = 5;
+ optional int32 cycle_bucket_6 = 6;
+ optional int32 cycle_bucket_7 = 7;
+ optional int32 cycle_bucket_8 = 8;
+}
+
+/**
* Logs the duration of a davey (jank of >=700ms) when it occurs
*
* Logged from:
diff --git a/cmds/statsd/src/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp
index d0f55ab..f5310a4 100644
--- a/cmds/statsd/src/config/ConfigManager.cpp
+++ b/cmds/statsd/src/config/ConfigManager.cpp
@@ -68,12 +68,25 @@
{
lock_guard <mutex> lock(mMutex);
+ auto it = mConfigs.find(key);
+
+ const int numBytes = config.ByteSize();
+ vector<uint8_t> buffer(numBytes);
+ config.SerializeToArray(&buffer[0], numBytes);
+
+ const bool isDuplicate =
+ it != mConfigs.end() &&
+ StorageManager::hasIdenticalConfig(key, buffer);
+
+ // Update saved file on disk. We still update timestamp of file when
+ // there exists a duplicate configuration to avoid garbage collection.
+ update_saved_configs_locked(key, buffer, numBytes);
+
+ if (isDuplicate) return;
+
// Add to set
mConfigs.insert(key);
- // Save to disk
- update_saved_configs_locked(key, config);
-
for (sp<ConfigListener> listener : mListeners) {
broadcastList.push_back(listener);
}
@@ -137,7 +150,6 @@
{
lock_guard <mutex> lock(mMutex);
-
for (auto it = mConfigs.begin(); it != mConfigs.end();) {
// Remove from map
if (it->GetUid() == uid) {
@@ -230,16 +242,16 @@
}
}
-void ConfigManager::update_saved_configs_locked(const ConfigKey& key, const StatsdConfig& config) {
+void ConfigManager::update_saved_configs_locked(const ConfigKey& key,
+ const vector<uint8_t>& buffer,
+ const int numBytes) {
// If there is a pre-existing config with same key we should first delete it.
remove_saved_configs(key);
// Then we save the latest config.
- string file_name = StringPrintf("%s/%ld_%d_%lld", STATS_SERVICE_DIR, time(nullptr),
- key.GetUid(), (long long)key.GetId());
- const int numBytes = config.ByteSize();
- vector<uint8_t> buffer(numBytes);
- config.SerializeToArray(&buffer[0], numBytes);
+ string file_name =
+ StringPrintf("%s/%ld_%d_%lld", STATS_SERVICE_DIR, time(nullptr),
+ key.GetUid(), (long long)key.GetId());
StorageManager::writeFile(file_name.c_str(), &buffer[0], numBytes);
}
diff --git a/cmds/statsd/src/config/ConfigManager.h b/cmds/statsd/src/config/ConfigManager.h
index a0c1c1c..9a38188a 100644
--- a/cmds/statsd/src/config/ConfigManager.h
+++ b/cmds/statsd/src/config/ConfigManager.h
@@ -115,7 +115,9 @@
/**
* Save the configs to disk.
*/
- void update_saved_configs_locked(const ConfigKey& key, const StatsdConfig& config);
+ void update_saved_configs_locked(const ConfigKey& key,
+ const std::vector<uint8_t>& buffer,
+ const int numBytes);
/**
* Remove saved configs from disk.
@@ -123,7 +125,7 @@
void remove_saved_configs(const ConfigKey& key);
/**
- * The Configs that have been set. Each config should
+ * Config keys that have been set.
*/
std::set<ConfigKey> mConfigs;
diff --git a/cmds/statsd/src/external/StatsPuller.cpp b/cmds/statsd/src/external/StatsPuller.cpp
index 9513cc5..3b0cd34 100644
--- a/cmds/statsd/src/external/StatsPuller.cpp
+++ b/cmds/statsd/src/external/StatsPuller.cpp
@@ -21,6 +21,7 @@
#include "guardrail/StatsdStats.h"
#include "puller_util.h"
#include "stats_log_util.h"
+#include "StatsPullerManagerImpl.h"
namespace android {
namespace os {
@@ -34,11 +35,7 @@
// ValueMetric has a minimum bucket size of 10min so that we don't pull too frequently
StatsPuller::StatsPuller(const int tagId)
: mTagId(tagId) {
- if (StatsdStats::kPullerCooldownMap.find(tagId) == StatsdStats::kPullerCooldownMap.end()) {
- mCoolDownSec = StatsdStats::kDefaultPullerCooldown;
- } else {
- mCoolDownSec = StatsdStats::kPullerCooldownMap[tagId];
- }
+ mCoolDownSec = StatsPullerManagerImpl::kAllPullAtomInfo.find(tagId)->second.coolDownSec;
VLOG("Puller for tag %d created. Cooldown set to %ld", mTagId, mCoolDownSec);
}
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index d626d90..c6c4d13 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -91,18 +91,6 @@
const int FIELD_ID_UID_MAP_DROPPED_SNAPSHOTS = 4;
const int FIELD_ID_UID_MAP_DROPPED_CHANGES = 5;
-std::map<int, long> StatsdStats::kPullerCooldownMap = {
- {android::util::KERNEL_WAKELOCK, 1},
- {android::util::WIFI_BYTES_TRANSFER, 1},
- {android::util::MOBILE_BYTES_TRANSFER, 1},
- {android::util::WIFI_BYTES_TRANSFER_BY_FG_BG, 1},
- {android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG, 1},
- {android::util::SUBSYSTEM_SLEEP_STATE, 1},
- {android::util::CPU_TIME_PER_FREQ, 1},
- {android::util::CPU_TIME_PER_UID, 1},
- {android::util::CPU_TIME_PER_UID_FREQ, 1},
-};
-
// TODO: add stats for pulled atoms.
StatsdStats::StatsdStats() {
mPushedAtomStats.resize(android::util::kMaxPushedAtomId + 1);
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index c3f4013..d05c91b 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -111,13 +111,6 @@
/* Min period between two checks of byte size per config key in nanoseconds. */
static const unsigned long long kMinByteSizeCheckPeriodNs = 10 * NS_PER_SEC;
- // Default minimum interval between pulls for an atom. Pullers can return cached values if
- // another pull request happens within this interval.
- static std::map<int, long> kPullerCooldownMap;
-
- // Default cooldown time for a puller
- static const long kDefaultPullerCooldown = 1;
-
// Maximum age (30 days) that files on disk can exist in seconds.
static const int kMaxAgeSecond = 60 * 60 * 24 * 30;
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 22b2a30..8e8a529 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -99,6 +99,24 @@
VLOG("~CountMetricProducer() called");
}
+void CountMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
+ if (mCurrentSlicedCounter == nullptr ||
+ mCurrentSlicedCounter->size() == 0) {
+ return;
+ }
+
+ fprintf(out, "CountMetric %lld dimension size %lu\n", (long long)mMetricId,
+ (unsigned long)mCurrentSlicedCounter->size());
+ if (verbose) {
+ for (const auto& it : *mCurrentSlicedCounter) {
+ fprintf(out, "\t(what)%s\t(condition)%s %lld\n",
+ it.first.getDimensionKeyInWhat().toString().c_str(),
+ it.first.getDimensionKeyInCondition().toString().c_str(),
+ (unsigned long long)it.second);
+ }
+ }
+}
+
void CountMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
}
@@ -249,7 +267,6 @@
} else {
info.mBucketEndNs = fullBucketEndTimeNs;
}
- info.mBucketNum = mCurrentBucketNum;
for (const auto& counter : *mCurrentSlicedCounter) {
info.mCount = counter.second;
auto& bucketList = mPastBuckets[counter.first];
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index 1d8e42b..ef738ac 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -36,7 +36,6 @@
int64_t mBucketStartNs;
int64_t mBucketEndNs;
int64_t mCount;
- uint64_t mBucketNum;
};
class CountMetricProducer : public MetricProducer {
@@ -67,7 +66,7 @@
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
- void dumpStatesLocked(FILE* out, bool verbose) const override{};
+ void dumpStatesLocked(FILE* out, bool verbose) const override;
void dropDataLocked(const uint64_t dropTimeNs) override;
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 0dd3f70..bc09683 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -126,6 +126,13 @@
sp<AnomalyTracker> DurationMetricProducer::addAnomalyTracker(
const Alert &alert, const sp<AlarmMonitor>& anomalyAlarmMonitor) {
std::lock_guard<std::mutex> lock(mMutex);
+ if (mAggregationType == DurationMetric_AggregationType_SUM) {
+ if (alert.trigger_if_sum_gt() > alert.num_buckets() * mBucketSizeNs) {
+ ALOGW("invalid alert for SUM: threshold (%f) > possible recordable value (%d x %lld)",
+ alert.trigger_if_sum_gt(), alert.num_buckets(), (long long)mBucketSizeNs);
+ return nullptr;
+ }
+ }
sp<DurationAnomalyTracker> anomalyTracker =
new DurationAnomalyTracker(alert, mConfigKey, anomalyAlarmMonitor);
if (anomalyTracker != nullptr) {
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index e479e5c..079eb69 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -126,6 +126,24 @@
}
}
+void GaugeMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
+ if (mCurrentSlicedBucket == nullptr ||
+ mCurrentSlicedBucket->size() == 0) {
+ return;
+ }
+
+ fprintf(out, "GaugeMetric %lld dimension size %lu\n", (long long)mMetricId,
+ (unsigned long)mCurrentSlicedBucket->size());
+ if (verbose) {
+ for (const auto& it : *mCurrentSlicedBucket) {
+ fprintf(out, "\t(what)%s\t(condition)%s %d atoms\n",
+ it.first.getDimensionKeyInWhat().toString().c_str(),
+ it.first.getDimensionKeyInCondition().toString().c_str(),
+ (int)it.second.size());
+ }
+ }
+}
+
void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
ProtoOutputStream* protoOutput) {
VLOG("gauge metric %lld report now...", (long long)mMetricId);
@@ -393,7 +411,6 @@
} else {
info.mBucketEndNs = fullBucketEndTimeNs;
}
- info.mBucketNum = mCurrentBucketNum;
for (const auto& slice : *mCurrentSlicedBucket) {
info.mGaugeAtoms = slice.second;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index ca8dc75..dd6aff4 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -44,7 +44,6 @@
int64_t mBucketStartNs;
int64_t mBucketEndNs;
std::vector<GaugeAtom> mGaugeAtoms;
- uint64_t mBucketNum;
};
typedef std::unordered_map<MetricDimensionKey, std::vector<GaugeAtom>>
@@ -106,7 +105,7 @@
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
- void dumpStatesLocked(FILE* out, bool verbose) const override{};
+ void dumpStatesLocked(FILE* out, bool verbose) const override;
void dropDataLocked(const uint64_t dropTimeNs) override;
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 09913dc..767260d 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -243,6 +243,23 @@
}
}
+void ValueMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
+ if (mCurrentSlicedBucket.size() == 0) {
+ return;
+ }
+
+ fprintf(out, "ValueMetric %lld dimension size %lu\n", (long long)mMetricId,
+ (unsigned long)mCurrentSlicedBucket.size());
+ if (verbose) {
+ for (const auto& it : mCurrentSlicedBucket) {
+ fprintf(out, "\t(what)%s\t(condition)%s (value)%lld\n",
+ it.first.getDimensionKeyInWhat().toString().c_str(),
+ it.first.getDimensionKeyInCondition().toString().c_str(),
+ (unsigned long long)it.second.sum);
+ }
+ }
+}
+
bool ValueMetricProducer::hitGuardRailLocked(const MetricDimensionKey& newKey) {
// ===========GuardRail==============
// 1. Report the tuple count if the tuple count > soft limit
@@ -355,7 +372,6 @@
} else {
info.mBucketEndNs = fullBucketEndTimeNs;
}
- info.mBucketNum = mCurrentBucketNum;
int tainted = 0;
for (const auto& slice : mCurrentSlicedBucket) {
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 5e42bd2..be57183 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -34,7 +34,6 @@
int64_t mBucketStartNs;
int64_t mBucketEndNs;
int64_t mValue;
- uint64_t mBucketNum;
};
class ValueMetricProducer : public virtual MetricProducer, public virtual PullDataReceiver {
@@ -99,7 +98,7 @@
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
- void dumpStatesLocked(FILE* out, bool verbose) const override{};
+ void dumpStatesLocked(FILE* out, bool verbose) const override;
// Util function to flush the old packet.
void flushIfNeededLocked(const uint64_t& eventTime) override;
diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
index 7b3393f..bfb1ec7 100644
--- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
@@ -55,7 +55,6 @@
uint64_t mBucketStartNs;
uint64_t mBucketEndNs;
uint64_t mDuration;
- uint64_t mBucketNum;
};
class DurationTracker {
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
index 8e0bf26..058940d 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
@@ -219,7 +219,6 @@
DurationBucket info;
info.mBucketStartNs = mCurrentBucketStartTimeNs;
info.mBucketEndNs = currentBucketEndTimeNs;
- info.mBucketNum = mCurrentBucketNum;
info.mDuration = mDuration;
(*output)[mEventKey].push_back(info);
VLOG(" final duration for last bucket: %lld", (long long)mDuration);
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
index 2358415..c8a5016 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
@@ -165,13 +165,12 @@
DurationBucket current_info;
current_info.mBucketStartNs = mCurrentBucketStartTimeNs;
current_info.mBucketEndNs = currentBucketEndTimeNs;
- current_info.mBucketNum = mCurrentBucketNum;
current_info.mDuration = mDuration;
(*output)[mEventKey].push_back(current_info);
mDurationFullBucket += mDuration;
if (eventTimeNs > fullBucketEnd) {
// End of full bucket, can send to anomaly tracker now.
- addPastBucketToAnomalyTrackers(mDurationFullBucket, current_info.mBucketNum);
+ addPastBucketToAnomalyTrackers(mDurationFullBucket, mCurrentBucketNum);
mDurationFullBucket = 0;
}
VLOG(" duration: %lld", (long long)current_info.mDuration);
@@ -182,12 +181,11 @@
DurationBucket info;
info.mBucketStartNs = fullBucketEnd + mBucketSizeNs * (i - 1);
info.mBucketEndNs = info.mBucketStartNs + mBucketSizeNs;
- info.mBucketNum = mCurrentBucketNum + i;
info.mDuration = mBucketSizeNs;
(*output)[mEventKey].push_back(info);
// Safe to send these buckets to anomaly tracker since they must be full buckets.
// If it's a partial bucket, numBucketsForward would be 0.
- addPastBucketToAnomalyTrackers(info.mDuration, info.mBucketNum);
+ addPastBucketToAnomalyTrackers(info.mDuration, mCurrentBucketNum + i);
VLOG(" add filling bucket with duration %lld", (long long)info.mDuration);
}
}
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 1e8aa12..1c99e2a 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -295,6 +295,7 @@
message BroadcastSubscriberDetails {
optional int64 subscriber_id = 1;
+ repeated string cookie = 2;
}
message Subscription {
diff --git a/cmds/statsd/src/storage/StorageManager.cpp b/cmds/statsd/src/storage/StorageManager.cpp
index 781eced..77387cb 100644
--- a/cmds/statsd/src/storage/StorageManager.cpp
+++ b/cmds/statsd/src/storage/StorageManager.cpp
@@ -245,6 +245,45 @@
}
}
+bool StorageManager::hasIdenticalConfig(const ConfigKey& key,
+ const vector<uint8_t>& config) {
+ unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_SERVICE_DIR),
+ closedir);
+ if (dir == NULL) {
+ VLOG("Directory does not exist: %s", STATS_SERVICE_DIR);
+ return false;
+ }
+
+ const char* suffix =
+ StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId()).c_str();
+
+ dirent* de;
+ while ((de = readdir(dir.get()))) {
+ char* name = de->d_name;
+ if (name[0] == '.') {
+ continue;
+ }
+ size_t nameLen = strlen(name);
+ size_t suffixLen = strlen(suffix);
+ // There can be at most one file that matches this suffix (config key).
+ if (suffixLen <= nameLen &&
+ strncmp(name + nameLen - suffixLen, suffix, suffixLen) == 0) {
+ int fd = open(StringPrintf("%s/%s", STATS_SERVICE_DIR, name).c_str(),
+ O_RDONLY | O_CLOEXEC);
+ if (fd != -1) {
+ string content;
+ if (android::base::ReadFdToString(fd, &content)) {
+ vector<uint8_t> vec(content.begin(), content.end());
+ if (vec == config) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
void StorageManager::trimToFit(const char* path) {
unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir);
if (dir == NULL) {
diff --git a/cmds/statsd/src/storage/StorageManager.h b/cmds/statsd/src/storage/StorageManager.h
index 6c8ed0a..13ce5c6 100644
--- a/cmds/statsd/src/storage/StorageManager.h
+++ b/cmds/statsd/src/storage/StorageManager.h
@@ -78,6 +78,12 @@
* files, accumulation of outdated files.
*/
static void trimToFit(const char* dir);
+
+ /**
+ * Returns true if there already exists identical configuration on device.
+ */
+ static bool hasIdenticalConfig(const ConfigKey& key,
+ const vector<uint8_t>& config);
};
} // namespace statsd
diff --git a/cmds/statsd/src/subscriber/SubscriberReporter.cpp b/cmds/statsd/src/subscriber/SubscriberReporter.cpp
index 95ecf80..25d2257 100644
--- a/cmds/statsd/src/subscriber/SubscriberReporter.cpp
+++ b/cmds/statsd/src/subscriber/SubscriberReporter.cpp
@@ -77,6 +77,12 @@
}
int64_t subscriberId = subscription.broadcast_subscriber_details().subscriber_id();
+ vector<String16> cookies;
+ cookies.reserve(subscription.broadcast_subscriber_details().cookie_size());
+ for (auto& cookie : subscription.broadcast_subscriber_details().cookie()) {
+ cookies.push_back(String16(cookie.c_str()));
+ }
+
auto it1 = mIntentMap.find(configKey);
if (it1 == mIntentMap.end()) {
ALOGW("Cannot inform subscriber for missing config key %s ", configKey.ToString().c_str());
@@ -88,12 +94,13 @@
configKey.ToString().c_str(), (long long)subscriberId);
return;
}
- sendBroadcastLocked(it2->second, configKey, subscription, dimKey);
+ sendBroadcastLocked(it2->second, configKey, subscription, cookies, dimKey);
}
void SubscriberReporter::sendBroadcastLocked(const sp<IBinder>& intentSender,
const ConfigKey& configKey,
const Subscription& subscription,
+ const vector<String16>& cookies,
const MetricDimensionKey& dimKey) const {
VLOG("SubscriberReporter::sendBroadcastLocked called.");
if (mStatsCompanionService == nullptr) {
@@ -101,11 +108,16 @@
return;
}
mStatsCompanionService->sendSubscriberBroadcast(
- intentSender, configKey.GetUid(), configKey.GetId(), subscription.id(),
- subscription.rule_id(), getStatsDimensionsValue(dimKey.getDimensionKeyInWhat()));
+ intentSender,
+ configKey.GetUid(),
+ configKey.GetId(),
+ subscription.id(),
+ subscription.rule_id(),
+ cookies,
+ getStatsDimensionsValue(dimKey.getDimensionKeyInWhat()));
}
-void getStatsDimensionsValueHelper(const std::vector<FieldValue>& dims, size_t* index, int depth,
+void getStatsDimensionsValueHelper(const vector<FieldValue>& dims, size_t* index, int depth,
int prefix, vector<StatsDimensionsValue>* output) {
size_t count = dims.size();
while (*index < count) {
diff --git a/cmds/statsd/src/subscriber/SubscriberReporter.h b/cmds/statsd/src/subscriber/SubscriberReporter.h
index 50100df..2a7f771 100644
--- a/cmds/statsd/src/subscriber/SubscriberReporter.h
+++ b/cmds/statsd/src/subscriber/SubscriberReporter.h
@@ -26,6 +26,7 @@
#include <mutex>
#include <unordered_map>
+#include <vector>
namespace android {
namespace os {
@@ -102,6 +103,7 @@
void sendBroadcastLocked(const sp<android::IBinder>& intentSender,
const ConfigKey& configKey,
const Subscription& subscription,
+ const std::vector<String16>& cookies,
const MetricDimensionKey& dimKey) const;
};
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index 77b3ace..c0cc0b6 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -112,7 +112,6 @@
it++;
EXPECT_EQ(INT, it->mValue.getType());
EXPECT_EQ(11L, it->mValue.int_value);
- EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.back().mBucketNum);
gaugeProducer.flushIfNeededLocked(bucket4StartTimeNs);
EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
@@ -125,7 +124,6 @@
it++;
EXPECT_EQ(INT, it->mValue.getType());
EXPECT_EQ(25L, it->mValue.int_value);
- EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.back().mBucketNum);
}
TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade) {
@@ -337,7 +335,6 @@
.mGaugeAtoms.front()
.mFields->begin()
->mValue.int_value);
- EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.back().mBucketNum);
}
TEST(GaugeMetricProducerTest, TestAnomalyDetection) {
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 68f6546..9f71f26 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -3,19 +3,12 @@
Landroid/accounts/IAccountManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/animation/LayoutTransition;->cancel()V
Landroid/animation/ValueAnimator;->animateValue(F)V
-Landroid/animation/ValueAnimator;->getDurationScale()F
Landroid/animation/ValueAnimator;->sDurationScale:F
-Landroid/animation/ValueAnimator;->setDurationScale(F)V
-Landroid/app/Activity;->convertFromTranslucent()V
-Landroid/app/Activity;->convertToTranslucent(Landroid/app/Activity$TranslucentConversionListener;Landroid/app/ActivityOptions;)Z
Landroid/app/Activity;->getActivityOptions()Landroid/app/ActivityOptions;
Landroid/app/Activity;->getActivityToken()Landroid/os/IBinder;
Landroid/app/Activity;->mActivityInfo:Landroid/content/pm/ActivityInfo;
-Landroid/app/ActivityManager;->addOnUidImportanceListener(Landroid/app/ActivityManager$OnUidImportanceListener;I)V
Landroid/app/ActivityManager;->clearApplicationUserData(Ljava/lang/String;Landroid/content/pm/IPackageDataObserver;)Z
-Landroid/app/ActivityManager;->forceStopPackage(Ljava/lang/String;)V
-Landroid/app/ActivityManager;->getCurrentUser()I
-Landroid/app/ActivityManager;->getPackageImportance(Ljava/lang/String;)I
+Landroid/app/ActivityManager;->getMaxRecentTasksStatic()I
Landroid/app/ActivityManager;->getService()Landroid/app/IActivityManager;
Landroid/app/ActivityManager;->IActivityManagerSingleton:Landroid/util/Singleton;
Landroid/app/ActivityManager;->isLowRamDeviceStatic()Z
@@ -23,9 +16,9 @@
Landroid/app/ActivityManager;->mContext:Landroid/content/Context;
Landroid/app/ActivityManagerNative;->asInterface(Landroid/os/IBinder;)Landroid/app/IActivityManager;
Landroid/app/ActivityManagerNative;->getDefault()Landroid/app/IActivityManager;
+Landroid/app/ActivityManager;->PROCESS_STATE_IMPORTANT_BACKGROUND:I
Landroid/app/ActivityManager;->PROCESS_STATE_TOP:I
Landroid/app/ActivityManager$RecentTaskInfo;->firstActiveTime:J
-Landroid/app/ActivityManager;->removeOnUidImportanceListener(Landroid/app/ActivityManager$OnUidImportanceListener;)V
Landroid/app/ActivityManager$RunningAppProcessInfo;->flags:I
Landroid/app/ActivityManager$RunningAppProcessInfo;->processState:I
Landroid/app/Activity;->mApplication:Landroid/app/Application;
@@ -118,16 +111,11 @@
Landroid/app/ActivityThread$ServiceArgsData;->token:Landroid/os/IBinder;
Landroid/app/ActivityThread;->sPackageManager:Landroid/content/pm/IPackageManager;
Landroid/app/ActivityThread;->startActivityNow(Landroid/app/Activity;Ljava/lang/String;Landroid/content/Intent;Landroid/content/pm/ActivityInfo;Landroid/os/IBinder;Landroid/os/Bundle;Landroid/app/Activity$NonConfigurationInstances;)Landroid/app/Activity;
-Landroid/app/admin/DevicePolicyManager;->getDeviceOwnerComponentOnAnyUser()Landroid/content/ComponentName;
-Landroid/app/admin/DevicePolicyManager;->getDeviceOwner()Ljava/lang/String;
-Landroid/app/admin/DevicePolicyManager;->getProfileOwner()Landroid/content/ComponentName;
Landroid/app/admin/DevicePolicyManager;->getTrustAgentConfiguration(Landroid/content/ComponentName;Landroid/content/ComponentName;I)Ljava/util/List;
-Landroid/app/admin/DevicePolicyManager;->notifyPendingSystemUpdate(J)V
-Landroid/app/admin/DevicePolicyManager;->notifyPendingSystemUpdate(JZ)V
Landroid/app/admin/DevicePolicyManager;->packageHasActiveAdmins(Ljava/lang/String;I)Z
-Landroid/app/admin/DevicePolicyManager;->packageHasActiveAdmins(Ljava/lang/String;)Z
Landroid/app/admin/DevicePolicyManager;->setActiveAdmin(Landroid/content/ComponentName;ZI)V
Landroid/app/admin/DevicePolicyManager;->setActiveAdmin(Landroid/content/ComponentName;Z)V
+Landroid/app/admin/DevicePolicyManager;->throwIfParentInstance(Ljava/lang/String;)V
Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_packageHasActiveAdmins:I
Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_removeActiveAdmin:I
Landroid/app/admin/SecurityLog$SecurityEvent;-><init>([B)V
@@ -136,8 +124,6 @@
Landroid/app/AlarmManager;->FLAG_STANDALONE:I
Landroid/app/AlarmManager;->FLAG_WAKE_FROM_IDLE:I
Landroid/app/AlarmManager;->mService:Landroid/app/IAlarmManager;
-Landroid/app/AlarmManager;->set(IJJJLandroid/app/AlarmManager$OnAlarmListener;Landroid/os/Handler;Landroid/os/WorkSource;)V
-Landroid/app/AlarmManager;->set(IJJJLandroid/app/PendingIntent;Landroid/os/WorkSource;)V
Landroid/app/AlarmManager;->WINDOW_EXACT:J
Landroid/app/AlarmManager;->WINDOW_HEURISTIC:J
Landroid/app/AlertDialog$Builder;->P:Lcom/android/internal/app/AlertController$AlertParams;
@@ -161,8 +147,6 @@
Landroid/app/ApplicationPackageManager;->deletePackage(Ljava/lang/String;Landroid/content/pm/IPackageDeleteObserver;I)V
Landroid/app/ApplicationPackageManager;->getPackageSizeInfoAsUser(Ljava/lang/String;ILandroid/content/pm/IPackageStatsObserver;)V
Landroid/app/ApplicationPackageManager;-><init>(Landroid/app/ContextImpl;Landroid/content/pm/IPackageManager;)V
-Landroid/app/ApplicationPackageManager;->installExistingPackage(Ljava/lang/String;)I
-Landroid/app/ApplicationPackageManager;->installExistingPackage(Ljava/lang/String;I)I
Landroid/app/ApplicationPackageManager;->mPM:Landroid/content/pm/IPackageManager;
Landroid/app/AppOpsManager;->checkOp(IILjava/lang/String;)I
Landroid/app/AppOpsManager;->checkOpNoThrow(IILjava/lang/String;)I
@@ -175,46 +159,20 @@
Landroid/app/AppOpsManager;->OP_POST_NOTIFICATION:I
Landroid/app/AppOpsManager;->OP_READ_PHONE_STATE:I
Landroid/app/AppOpsManager;->OP_READ_SMS:I
-Landroid/app/AppOpsManager;->OP_SYSTEM_ALERT_WINDOW:I
Landroid/app/AppOpsManager;->OP_WIFI_SCAN:I
Landroid/app/AppOpsManager;->OP_WRITE_SMS:I
Landroid/app/AppOpsManager;->permissionToOpCode(Ljava/lang/String;)I
-Landroid/app/AppOpsManager;->setMode(IILjava/lang/String;I)V
Landroid/app/AppOpsManager;->strOpToOp(Ljava/lang/String;)I
Landroid/app/backup/BackupDataInput$EntityHeader;->dataSize:I
Landroid/app/backup/BackupDataInput$EntityHeader;->key:Ljava/lang/String;
-Landroid/app/backup/BackupDataInput;-><init>(Ljava/io/FileDescriptor;)V
Landroid/app/backup/BackupDataInputStream;->dataSize:I
Landroid/app/backup/BackupDataInputStream;->key:Ljava/lang/String;
-Landroid/app/backup/BackupDataOutput;-><init>(Ljava/io/FileDescriptor;)V
Landroid/app/backup/BackupDataOutput;->mBackupWriter:J
Landroid/app/backup/BackupHelperDispatcher$Header;->chunkSize:I
Landroid/app/backup/BackupHelperDispatcher$Header;->keyPrefix:Ljava/lang/String;
-Landroid/app/backup/BackupManager;->backupNow()V
-Landroid/app/backup/BackupManager;->beginRestoreSession()Landroid/app/backup/RestoreSession;
-Landroid/app/backup/BackupManager;->cancelBackups()V
-Landroid/app/backup/BackupManager;->getAvailableRestoreToken(Ljava/lang/String;)J
-Landroid/app/backup/BackupManager;->getCurrentTransport()Ljava/lang/String;
-Landroid/app/backup/BackupManager;->isBackupEnabled()Z
-Landroid/app/backup/BackupManager;->listAllTransports()[Ljava/lang/String;
-Landroid/app/backup/BackupManagerMonitor;-><init>()V
-Landroid/app/backup/BackupManager;->requestBackup([Ljava/lang/String;Landroid/app/backup/BackupObserver;Landroid/app/backup/BackupManagerMonitor;I)I
-Landroid/app/backup/BackupManager;->selectBackupTransport(Landroid/content/ComponentName;Landroid/app/backup/SelectBackupTransportCallback;)V
-Landroid/app/backup/BackupManager;->selectBackupTransport(Ljava/lang/String;)Ljava/lang/String;
-Landroid/app/backup/BackupManager;->setAutoRestore(Z)V
-Landroid/app/backup/BackupManager;->setBackupEnabled(Z)V
-Landroid/app/backup/BackupManager;->updateTransportAttributes(Landroid/content/ComponentName;Ljava/lang/String;Landroid/content/Intent;Ljava/lang/String;Landroid/content/Intent;Ljava/lang/String;)V
-Landroid/app/backup/BackupObserver;-><init>()V
-Landroid/app/backup/BackupTransport;-><init>()V
Landroid/app/backup/FullBackup;->backupToTar(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/backup/FullBackupDataOutput;)I
Landroid/app/backup/FullBackupDataOutput;->addSize(J)V
Landroid/app/backup/FullBackupDataOutput;->mData:Landroid/app/backup/BackupDataOutput;
-Landroid/app/backup/RestoreDescription;-><init>(Ljava/lang/String;I)V
-Landroid/app/backup/RestoreSession;->endRestoreSession()V
-Landroid/app/backup/RestoreSession;->getAvailableRestoreSets(Landroid/app/backup/RestoreObserver;)I
-Landroid/app/backup/RestoreSession;->restoreAll(JLandroid/app/backup/RestoreObserver;)I
-Landroid/app/backup/RestoreSet;-><init>(Ljava/lang/String;Ljava/lang/String;J)V
-Landroid/app/backup/SelectBackupTransportCallback;-><init>()V
Landroid/app/ContentProviderHolder;->info:Landroid/content/pm/ProviderInfo;
Landroid/app/ContentProviderHolder;-><init>(Landroid/content/pm/ProviderInfo;)V
Landroid/app/ContentProviderHolder;->provider:Landroid/content/IContentProvider;
@@ -272,8 +230,6 @@
Landroid/app/IApplicationThread;->scheduleTrimMemory(I)V
Landroid/app/INotificationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/INotificationManager;
Landroid/app/INotificationManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/app/InstantAppResolverService;-><init>()V
-Landroid/app/InstantAppResolverService$InstantAppResolutionCallback;->onInstantAppResolveInfo(Ljava/util/List;)V
Landroid/app/Instrumentation;->execStartActivity(Landroid/content/Context;Landroid/os/IBinder;Landroid/os/IBinder;Landroid/app/Activity;Landroid/content/Intent;ILandroid/os/Bundle;)Landroid/app/Instrumentation$ActivityResult;
Landroid/app/Instrumentation;->execStartActivity(Landroid/content/Context;Landroid/os/IBinder;Landroid/os/IBinder;Ljava/lang/String;Landroid/content/Intent;ILandroid/os/Bundle;)Landroid/app/Instrumentation$ActivityResult;
Landroid/app/Instrumentation;->execStartActivity(Landroid/content/Context;Landroid/os/IBinder;Landroid/os/IBinder;Ljava/lang/String;Landroid/content/Intent;ILandroid/os/Bundle;Landroid/os/UserHandle;)Landroid/app/Instrumentation$ActivityResult;
@@ -313,7 +269,6 @@
Landroid/app/NativeActivity;->showIme(I)V
Landroid/app/Notification$Builder;->mActions:Ljava/util/ArrayList;
Landroid/app/Notification$Builder;->setChannel(Ljava/lang/String;)Landroid/app/Notification$Builder;
-Landroid/app/Notification;->EXTRA_SUBSTITUTE_APP_NAME:Ljava/lang/String;
Landroid/app/Notification;->isGroupSummary()Z
Landroid/app/NotificationManager;->getService()Landroid/app/INotificationManager;
Landroid/app/NotificationManager;->notifyAsUser(Ljava/lang/String;ILandroid/app/Notification;Landroid/os/UserHandle;)V
@@ -349,13 +304,10 @@
Landroid/app/StatusBarManager;->expandSettingsPanel(Ljava/lang/String;)V
Landroid/app/StatusBarManager;->expandSettingsPanel()V
Landroid/app/StatusBarManager;->getService()Lcom/android/internal/statusbar/IStatusBarService;
+Landroid/app/TaskStackListener;-><init>()V
Landroid/app/TimePickerDialog;->mTimePicker:Landroid/widget/TimePicker;
Landroid/app/trust/ITrustManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/app/usage/UsageStatsManager;->getAppStandbyBucket(Ljava/lang/String;)I
-Landroid/app/usage/UsageStatsManager;->getAppStandbyBuckets()Ljava/util/Map;
Landroid/app/usage/UsageStatsManager;->mService:Landroid/app/usage/IUsageStatsManager;
-Landroid/app/usage/UsageStatsManager;->setAppStandbyBuckets(Ljava/util/Map;)V
-Landroid/app/usage/UsageStatsManager;->whitelistAppTemporarily(Ljava/lang/String;JLandroid/os/UserHandle;)V
Landroid/app/usage/UsageStats;->mLastEvent:I
Landroid/app/WallpaperColors;->getColorHints()I
Landroid/app/WallpaperManager;->getBitmap()Landroid/graphics/Bitmap;
@@ -369,37 +321,25 @@
Landroid/appwidget/AppWidgetManager;->bindAppWidgetId(ILandroid/content/ComponentName;)V
Landroid/appwidget/AppWidgetManager;->mService:Lcom/android/internal/appwidget/IAppWidgetService;
Landroid/bluetooth/BluetoothA2dp;->connect(Landroid/bluetooth/BluetoothDevice;)Z
-Landroid/bluetooth/BluetoothAdapter;->disableBLE()Z
Landroid/bluetooth/BluetoothAdapter;->disable(Z)Z
-Landroid/bluetooth/BluetoothAdapter;->enableBLE()Z
-Landroid/bluetooth/BluetoothAdapter;->enableNoAutoConnect()Z
Landroid/bluetooth/BluetoothAdapter;->getDiscoverableTimeout()I
-Landroid/bluetooth/BluetoothAdapter;->isBleScanAlwaysAvailable()Z
-Landroid/bluetooth/BluetoothAdapter;->isLeEnabled()Z
Landroid/bluetooth/BluetoothAdapter;->mService:Landroid/bluetooth/IBluetooth;
Landroid/bluetooth/BluetoothAdapter;->setScanMode(II)Z
Landroid/bluetooth/BluetoothAdapter;->setScanMode(I)Z
-Landroid/bluetooth/BluetoothDevice;->cancelBondProcess()Z
Landroid/bluetooth/BluetoothDevice;->createBond(I)Z
Landroid/bluetooth/BluetoothDevice;->getAliasName()Ljava/lang/String;
-Landroid/bluetooth/BluetoothDevice;->isConnected()Z
-Landroid/bluetooth/BluetoothDevice;->isEncrypted()Z
-Landroid/bluetooth/BluetoothDevice;->removeBond()Z
-Landroid/bluetooth/BluetoothDevice;->setPhonebookAccessPermission(I)Z
Landroid/bluetooth/BluetoothGattCharacteristic;->mInstance:I
Landroid/bluetooth/BluetoothGattCharacteristic;->mService:Landroid/bluetooth/BluetoothGattService;
Landroid/bluetooth/BluetoothGattDescriptor;->mCharacteristic:Landroid/bluetooth/BluetoothGattCharacteristic;
Landroid/bluetooth/BluetoothGattDescriptor;->mInstance:I
Landroid/bluetooth/BluetoothGatt;->refresh()Z
Landroid/bluetooth/BluetoothHeadset;->close()V
-Landroid/bluetooth/BluetoothHeadset;->setPriority(Landroid/bluetooth/BluetoothDevice;I)Z
Landroid/bluetooth/BluetoothUuid;->RESERVED_UUIDS:[Landroid/os/ParcelUuid;
Landroid/bluetooth/IBluetooth;->getAddress()Ljava/lang/String;
Landroid/bluetooth/IBluetoothManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/bluetooth/IBluetooth$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetooth;
Landroid/bluetooth/IBluetooth$Stub$Proxy;->getAddress()Ljava/lang/String;
-Landroid/bluetooth/le/BluetoothLeScanner;->startScanFromSource(Ljava/util/List;Landroid/bluetooth/le/ScanSettings;Landroid/os/WorkSource;Landroid/bluetooth/le/ScanCallback;)V
-Landroid/bluetooth/le/ScanSettings$Builder;->setScanResultType(I)Landroid/bluetooth/le/ScanSettings$Builder;
+Landroid/bluetooth/le/ScanRecord;->parseFromBytes([B)Landroid/bluetooth/le/ScanRecord;
Landroid/content/AsyncTaskLoader;->mExecutor:Ljava/util/concurrent/Executor;
Landroid/content/BroadcastReceiver$PendingResult;-><init>(ILjava/lang/String;Landroid/os/Bundle;IZZLandroid/os/IBinder;II)V
Landroid/content/BroadcastReceiver;->setPendingResult(Landroid/content/BroadcastReceiver$PendingResult;)V
@@ -421,18 +361,11 @@
Landroid/content/ContentResolver;->mPackageName:Ljava/lang/String;
Landroid/content/ContentValues;-><init>(Ljava/util/HashMap;)V
Landroid/content/ContentValues;->mValues:Ljava/util/HashMap;
-Landroid/content/Context;->bindServiceAsUser(Landroid/content/Intent;Landroid/content/ServiceConnection;ILandroid/os/UserHandle;)Z
-Landroid/content/Context;->createCredentialProtectedStorageContext()Landroid/content/Context;
-Landroid/content/Context;->createPackageContextAsUser(Ljava/lang/String;ILandroid/os/UserHandle;)Landroid/content/Context;
Landroid/content/Context;->getSharedPrefsFile(Ljava/lang/String;)Ljava/io/File;
Landroid/content/Context;->getThemeResId()I
-Landroid/content/Context;->isCredentialProtectedStorage()Z
-Landroid/content/Context;->PERSISTENT_DATA_BLOCK_SERVICE:Ljava/lang/String;
Landroid/content/Context;->sendBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;I)V
-Landroid/content/Context;->sendBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;Landroid/os/Bundle;)V
Landroid/content/Context;->sendOrderedBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;ILandroid/content/BroadcastReceiver;Landroid/os/Handler;ILjava/lang/String;Landroid/os/Bundle;)V
Landroid/content/Context;->sendOrderedBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;ILandroid/os/Bundle;Landroid/content/BroadcastReceiver;Landroid/os/Handler;ILjava/lang/String;Landroid/os/Bundle;)V
-Landroid/content/ContextWrapper;->createCredentialProtectedStorageContext()Landroid/content/Context;
Landroid/content/ContextWrapper;->getDisplay()Landroid/view/Display;
Landroid/content/ContextWrapper;->mBase:Landroid/content/Context;
Landroid/content/CursorLoader;->mCancellationSignal:Landroid/os/CancellationSignal;
@@ -447,26 +380,17 @@
Landroid/content/IContentService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/content/Intent;->ACTION_ALARM_CHANGED:Ljava/lang/String;
Landroid/content/IntentFilter;->mActions:Ljava/util/ArrayList;
-Landroid/content/IntentFilter;->setOrder(I)V
Landroid/content/Intent;->putExtra(Ljava/lang/String;Landroid/os/IBinder;)Landroid/content/Intent;
Landroid/content/pm/ActivityInfo;->resizeMode:I
Landroid/content/pm/ApplicationInfo;->enabledSetting:I
Landroid/content/pm/ApplicationInfo;->getBaseResourcePath()Ljava/lang/String;
Landroid/content/pm/ApplicationInfo;->installLocation:I
Landroid/content/pm/ApplicationInfo;->isForwardLocked()Z
-Landroid/content/pm/ApplicationInfo;->isInstantApp()Z
-Landroid/content/pm/ApplicationInfo;->isPrivilegedApp()Z
Landroid/content/pm/ApplicationInfo;->primaryCpuAbi:Ljava/lang/String;
Landroid/content/pm/ApplicationInfo;->privateFlags:I
Landroid/content/pm/ApplicationInfo;->scanPublicSourceDir:Ljava/lang/String;
Landroid/content/pm/ApplicationInfo;->scanSourceDir:Ljava/lang/String;
Landroid/content/pm/ApplicationInfo;->secondaryNativeLibraryDir:Ljava/lang/String;
-Landroid/content/pm/ApplicationInfo;->targetSandboxVersion:I
-Landroid/content/pm/InstantAppIntentFilter;-><init>(Ljava/lang/String;Ljava/util/List;)V
-Landroid/content/pm/InstantAppResolveInfo;->getPackageName()Ljava/lang/String;
-Landroid/content/pm/InstantAppResolveInfo;-><init>(Landroid/content/pm/InstantAppResolveInfo$InstantAppDigest;Ljava/lang/String;Ljava/util/List;I)V
-Landroid/content/pm/InstantAppResolveInfo$InstantAppDigest;->getDigestPrefix()[I
-Landroid/content/pm/InstantAppResolveInfo$InstantAppDigest;-><init>(Ljava/lang/String;)V
Landroid/content/pm/IPackageManager;->getInstallLocation()I
Landroid/content/pm/IPackageManager;->getLastChosenActivity(Landroid/content/Intent;Ljava/lang/String;I)Landroid/content/pm/ResolveInfo;
Landroid/content/pm/IPackageManager;->setApplicationEnabledSetting(Ljava/lang/String;IIILjava/lang/String;)V
@@ -480,10 +404,6 @@
Landroid/content/pm/LauncherActivityInfo;->mActivityInfo:Landroid/content/pm/ActivityInfo;
Landroid/content/pm/LauncherApps;->mPm:Landroid/content/pm/PackageManager;
Landroid/content/pm/LauncherApps;->startShortcut(Ljava/lang/String;Ljava/lang/String;Landroid/graphics/Rect;Landroid/os/Bundle;I)V
-Landroid/content/pm/PackageInstaller$SessionParams;->setAllocateAggressive(Z)V
-Landroid/content/pm/PackageInstaller$SessionParams;->setGrantedRuntimePermissions([Ljava/lang/String;)V
-Landroid/content/pm/PackageInstaller$SessionParams;->setInstallAsInstantApp(Z)V
-Landroid/content/pm/PackageManager;->addOnPermissionsChangeListener(Landroid/content/pm/PackageManager$OnPermissionsChangedListener;)V
Landroid/content/pm/PackageManager;->buildRequestPermissionsIntent([Ljava/lang/String;)Landroid/content/Intent;
Landroid/content/pm/PackageManager;->freeStorageAndNotify(JLandroid/content/pm/IPackageDataObserver;)V
Landroid/content/pm/PackageManager;->freeStorageAndNotify(Ljava/lang/String;JLandroid/content/pm/IPackageDataObserver;)V
@@ -497,8 +417,6 @@
Landroid/content/pm/PackageManager;->movePackage(Ljava/lang/String;Landroid/os/storage/VolumeInfo;)I
Landroid/content/pm/PackageManager;->NO_NATIVE_LIBRARIES:I
Landroid/content/pm/PackageManager;->queryBroadcastReceivers(Landroid/content/Intent;II)Ljava/util/List;
-Landroid/content/pm/PackageManager;->removeOnPermissionsChangeListener(Landroid/content/pm/PackageManager$OnPermissionsChangedListener;)V
-Landroid/content/pm/PackageManager;->verifyIntentFilter(IILjava/util/List;)V
Landroid/content/pm/PackageParser$Activity;->info:Landroid/content/pm/ActivityInfo;
Landroid/content/pm/PackageParser$ActivityIntentInfo;->activity:Landroid/content/pm/PackageParser$Activity;
Landroid/content/pm/PackageParser;->collectCertificates(Landroid/content/pm/PackageParser$Package;Ljava/io/File;Z)V
@@ -528,6 +446,7 @@
Landroid/content/pm/PackageUserState;-><init>()V
Landroid/content/pm/ParceledListSlice;-><init>(Ljava/util/List;)V
Landroid/content/pm/ResolveInfo;->instantAppAvailable:Z
+Landroid/content/pm/ShortcutManager;->mService:Landroid/content/pm/IShortcutService;
Landroid/content/pm/Signature;->getPublicKey()Ljava/security/PublicKey;
Landroid/content/pm/UserInfo;->id:I
Landroid/content/pm/UserInfo;->isPrimary()Z
@@ -679,6 +598,7 @@
Landroid/graphics/drawable/StateListDrawable;->extractStateSet(Landroid/util/AttributeSet;)[I
Landroid/graphics/drawable/StateListDrawable;->getStateCount()I
Landroid/graphics/drawable/StateListDrawable;->getStateDrawable(I)Landroid/graphics/drawable/Drawable;
+Landroid/graphics/drawable/StateListDrawable;->getStateDrawableIndex([I)I
Landroid/graphics/drawable/StateListDrawable;->getStateSet(I)[I
Landroid/graphics/drawable/StateListDrawable;->mStateListState:Landroid/graphics/drawable/StateListDrawable$StateListState;
Landroid/graphics/drawable/StateListDrawable;->updateStateFromTypedArray(Landroid/content/res/TypedArray;)V
@@ -709,6 +629,7 @@
Landroid/graphics/SurfaceTexture;->mSurfaceTexture:J
Landroid/graphics/SurfaceTexture;->nativeDetachFromGLContext()I
Landroid/graphics/SurfaceTexture;->postEventFromNative(Ljava/lang/ref/WeakReference;)V
+Landroid/graphics/Typeface;->createFromFamiliesWithDefault([Landroid/graphics/FontFamily;Ljava/lang/String;II)Landroid/graphics/Typeface;
Landroid/graphics/Typeface;->mStyle:I
Landroid/graphics/Typeface;->sDefaults:[Landroid/graphics/Typeface;
Landroid/graphics/Typeface;->setDefault(Landroid/graphics/Typeface;)V
@@ -721,7 +642,6 @@
Landroid/hardware/Camera;->mNativeContext:J
Landroid/hardware/Camera;->openLegacy(II)Landroid/hardware/Camera;
Landroid/hardware/Camera;->postEventFromNative(Ljava/lang/Object;IIILjava/lang/Object;)V
-Landroid/hardware/display/DisplayManager;->getStableDisplaySize()Landroid/graphics/Point;
Landroid/hardware/display/WifiDisplayStatus;->mActiveDisplay:Landroid/hardware/display/WifiDisplay;
Landroid/hardware/display/WifiDisplayStatus;->mDisplays:[Landroid/hardware/display/WifiDisplay;
Landroid/hardware/HardwareBuffer;-><init>(J)V
@@ -729,49 +649,16 @@
Landroid/hardware/input/IInputManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/input/IInputManager;
Landroid/hardware/input/IInputManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/hardware/input/InputManager;->getInstance()Landroid/hardware/input/InputManager;
+Landroid/hardware/input/InputManager;->injectInputEvent(Landroid/view/InputEvent;I)Z
+Landroid/hardware/input/InputManager;->INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH:I
Landroid/hardware/input/InputManager;->mIm:Landroid/hardware/input/IInputManager;
-Landroid/hardware/location/ContextHubInfo;->getId()I
-Landroid/hardware/location/ContextHubInfo;->getMaxPacketLengthBytes()I
-Landroid/hardware/location/ContextHubManager$Callback;-><init>()V
-Landroid/hardware/location/ContextHubManager;->findNanoAppOnHub(ILandroid/hardware/location/NanoAppFilter;)[I
-Landroid/hardware/location/ContextHubManager;->getContextHubHandles()[I
-Landroid/hardware/location/ContextHubManager;->getContextHubInfo(I)Landroid/hardware/location/ContextHubInfo;
-Landroid/hardware/location/ContextHubManager;->getNanoAppInstanceInfo(I)Landroid/hardware/location/NanoAppInstanceInfo;
-Landroid/hardware/location/ContextHubManager;->loadNanoApp(ILandroid/hardware/location/NanoApp;)I
-Landroid/hardware/location/ContextHubManager;->registerCallback(Landroid/hardware/location/ContextHubManager$Callback;)I
-Landroid/hardware/location/ContextHubManager;->sendMessage(IILandroid/hardware/location/ContextHubMessage;)I
-Landroid/hardware/location/ContextHubManager;->unloadNanoApp(I)I
-Landroid/hardware/location/ContextHubMessage;->getData()[B
-Landroid/hardware/location/ContextHubMessage;->getMsgType()I
-Landroid/hardware/location/ContextHubMessage;->getVersion()I
-Landroid/hardware/location/ContextHubMessage;-><init>(II[B)V
-Landroid/hardware/location/GeofenceHardware;->addGeofence(IILandroid/hardware/location/GeofenceHardwareRequest;Landroid/hardware/location/GeofenceHardwareCallback;)Z
-Landroid/hardware/location/GeofenceHardwareCallback;-><init>()V
-Landroid/hardware/location/GeofenceHardwareCallback;->onGeofenceAdd(II)V
-Landroid/hardware/location/GeofenceHardwareCallback;->onGeofenceRemove(II)V
-Landroid/hardware/location/GeofenceHardwareCallback;->onGeofenceTransition(IILandroid/location/Location;JI)V
-Landroid/hardware/location/GeofenceHardware;->getMonitoringTypes()[I
-Landroid/hardware/location/GeofenceHardware;->getStatusOfMonitoringType(I)I
-Landroid/hardware/location/GeofenceHardwareMonitorCallback;-><init>()V
-Landroid/hardware/location/GeofenceHardwareMonitorCallback;->onMonitoringSystemChange(IZLandroid/location/Location;)V
-Landroid/hardware/location/GeofenceHardware;->registerForMonitorStateChangeCallback(ILandroid/hardware/location/GeofenceHardwareMonitorCallback;)Z
-Landroid/hardware/location/GeofenceHardware;->removeGeofence(II)Z
-Landroid/hardware/location/GeofenceHardwareRequest;->createCircularGeofence(DDD)Landroid/hardware/location/GeofenceHardwareRequest;
-Landroid/hardware/location/GeofenceHardwareRequest;->setLastTransition(I)V
-Landroid/hardware/location/GeofenceHardwareRequest;->setMonitorTransitions(I)V
-Landroid/hardware/location/GeofenceHardwareRequest;->setNotificationResponsiveness(I)V
-Landroid/hardware/location/GeofenceHardwareRequest;->setUnknownTimer(I)V
-Landroid/hardware/location/NanoAppFilter;-><init>(JIIJ)V
-Landroid/hardware/location/NanoApp;-><init>(J[B)V
-Landroid/hardware/location/NanoAppInstanceInfo;->getAppId()J
-Landroid/hardware/location/NanoAppInstanceInfo;->getAppVersion()I
-Landroid/hardware/location/NanoAppInstanceInfo;->getHandle()I
-Landroid/hardware/location/NanoAppInstanceInfo;->getName()Ljava/lang/String;
+Landroid/hardware/location/IActivityRecognitionHardwareClient$Stub;-><init>()V
Landroid/hardware/SerialPort;->mNativeContext:I
Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;->confidenceLevel:I
Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;-><init>(II)V
Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;->userId:I
Landroid/hardware/soundtrigger/SoundTrigger$GenericRecognitionEvent;-><init>(IIZIIIZLandroid/media/AudioFormat;[B)V
+Landroid/hardware/soundtrigger/SoundTrigger$GenericSoundModel;-><init>(Ljava/util/UUID;Ljava/util/UUID;[B)V
Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;->id:I
Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;->locale:Ljava/lang/String;
Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionEvent;-><init>(IIZIIIZLandroid/media/AudioFormat;[B[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;)V
@@ -790,6 +677,7 @@
Landroid/hardware/soundtrigger/SoundTrigger$ModuleProperties;-><init>(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIIZIZIZ)V
Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;->captureRequested:Z
Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;->data:[B
+Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;-><init>(ZZ[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;[B)V
Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;->keyphrases:[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;
Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent;-><init>(IIZIIIZLandroid/media/AudioFormat;[B)V
Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;->data:[B
@@ -801,17 +689,32 @@
Landroid/hardware/SystemSensorManager$BaseEventQueue;->dispatchSensorEvent(I[FIJ)V
Landroid/hardware/usb/IUsbManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/hardware/usb/UsbDeviceConnection;->mNativeContext:J
+Landroid/hardware/usb/UsbManager;->getPorts()[Landroid/hardware/usb/UsbPort;
+Landroid/hardware/usb/UsbManager;->getPortStatus(Landroid/hardware/usb/UsbPort;)Landroid/hardware/usb/UsbPortStatus;
Landroid/hardware/usb/UsbManager;->setCurrentFunction(Ljava/lang/String;Z)V
+Landroid/hardware/usb/UsbManager;->setPortRoles(Landroid/hardware/usb/UsbPort;II)V
+Landroid/hardware/usb/UsbPortStatus;->getCurrentDataRole()I
+Landroid/hardware/usb/UsbPortStatus;->isConnected()Z
+Landroid/hardware/usb/UsbPortStatus;->isRoleCombinationSupported(II)Z
Landroid/hardware/usb/UsbRequest;->mNativeContext:J
+Landroid/icu/impl/CurrencyData;-><init>()V
Landroid/icu/impl/number/DecimalFormatProperties;->readObject(Ljava/io/ObjectInputStream;)V
Landroid/icu/impl/number/DecimalFormatProperties;->writeObject(Ljava/io/ObjectOutputStream;)V
Landroid/icu/impl/TimeZoneGenericNames;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/ArabicShaping;->isAlefMaksouraChar(C)Z
+Landroid/icu/text/ArabicShaping;->isSeenTailFamilyChar(C)I
+Landroid/icu/text/ArabicShaping;->isTailChar(C)Z
+Landroid/icu/text/ArabicShaping;->isYehHamzaChar(C)Z
Landroid/icu/text/DateFormat;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/DateFormatSymbols;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
Landroid/icu/text/DateFormatSymbols;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/DateIntervalFormat;-><init>()V
Landroid/icu/text/DateIntervalFormat;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/DateTimePatternGenerator$DistanceInfo;-><init>()V
Landroid/icu/text/DecimalFormat_ICU58_Android;->readObject(Ljava/io/ObjectInputStream;)V
Landroid/icu/text/DecimalFormat_ICU58_Android;->writeObject(Ljava/io/ObjectOutputStream;)V
Landroid/icu/text/DecimalFormat;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/DecimalFormatSymbols;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
Landroid/icu/text/DecimalFormatSymbols;->readObject(Ljava/io/ObjectInputStream;)V
Landroid/icu/text/DecimalFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
Landroid/icu/text/MessageFormat;->readObject(Ljava/io/ObjectInputStream;)V
@@ -823,13 +726,23 @@
Landroid/icu/text/PluralRules$FixedDecimal;->writeObject(Ljava/io/ObjectOutputStream;)V
Landroid/icu/text/PluralRules;->readObject(Ljava/io/ObjectInputStream;)V
Landroid/icu/text/PluralRules;->writeObject(Ljava/io/ObjectOutputStream;)V
+Landroid/icu/text/RuleBasedCollator;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
Landroid/icu/text/RuleBasedNumberFormat;->readObject(Ljava/io/ObjectInputStream;)V
Landroid/icu/text/RuleBasedNumberFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
Landroid/icu/text/SelectFormat;->readObject(Ljava/io/ObjectInputStream;)V
Landroid/icu/text/SimpleDateFormat;->readObject(Ljava/io/ObjectInputStream;)V
Landroid/icu/text/SimpleDateFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
+Landroid/icu/text/SpoofChecker$ScriptSet;->and(I)V
+Landroid/icu/text/SpoofChecker$ScriptSet;-><init>()V
+Landroid/icu/text/SpoofChecker$ScriptSet;->isFull()Z
+Landroid/icu/text/SpoofChecker$ScriptSet;->setAll()V
Landroid/icu/text/TimeZoneFormat;->readObject(Ljava/io/ObjectInputStream;)V
Landroid/icu/text/TimeZoneFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
+Landroid/icu/text/TimeZoneNames$DefaultTimeZoneNames$FactoryImpl;-><init>()V
+Landroid/icu/text/Transliterator;->createFromRules(Ljava/lang/String;Ljava/lang/String;I)Landroid/icu/text/Transliterator;
+Landroid/icu/text/Transliterator;->transliterate(Ljava/lang/String;)Ljava/lang/String;
+Landroid/icu/text/UFormat;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
+Landroid/icu/util/Calendar;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
Landroid/icu/util/Calendar;->readObject(Ljava/io/ObjectInputStream;)V
Landroid/icu/util/Calendar;->writeObject(Ljava/io/ObjectOutputStream;)V
Landroid/icu/util/ChineseCalendar;->readObject(Ljava/io/ObjectInputStream;)V
@@ -841,15 +754,12 @@
Landroid/location/Country;->getSource()I
Landroid/location/GeocoderParams;->getClientPackage()Ljava/lang/String;
Landroid/location/GeocoderParams;->getLocale()Ljava/util/Locale;
+Landroid/location/IFusedProvider$Stub;-><init>()V
+Landroid/location/IGeocodeProvider$Stub;-><init>()V
+Landroid/location/IGeofenceProvider$Stub;-><init>()V
+Landroid/location/ILocationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ILocationManager;
Landroid/location/ILocationManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/location/LocationManager;->mService:Landroid/location/ILocationManager;
-Landroid/location/LocationManager;->requestLocationUpdates(Landroid/location/LocationRequest;Landroid/location/LocationListener;Landroid/os/Looper;)V
-Landroid/location/LocationRequest;->createFromDeprecatedProvider(Ljava/lang/String;JFZ)Landroid/location/LocationRequest;
-Landroid/location/LocationRequest;->setHideFromAppOps(Z)V
-Landroid/location/LocationRequest;->setWorkSource(Landroid/os/WorkSource;)V
-Landroid/location/Location;->setIsFromMockProvider(Z)V
-Landroid/Manifest$permission;->REAL_GET_TASKS:Ljava/lang/String;
-Landroid/media/AudioAttributes$Builder;->setInternalCapturePreset(I)Landroid/media/AudioAttributes$Builder;
Landroid/media/AudioAttributes;->mContentType:I
Landroid/media/AudioAttributes;->mFlags:I
Landroid/media/AudioAttributes;->mFormattedTags:Ljava/lang/String;
@@ -857,13 +767,12 @@
Landroid/media/AudioAttributes;->mUsage:I
Landroid/media/AudioDevicePortConfig;-><init>(Landroid/media/AudioDevicePort;IIILandroid/media/AudioGainConfig;)V
Landroid/media/AudioDevicePort;-><init>(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V
-Landroid/media/AudioFocusInfo;->getClientId()Ljava/lang/String;
-Landroid/media/AudioFocusInfo;->getClientUid()I
-Landroid/media/AudioFocusInfo;->getLossReceived()I
Landroid/media/AudioFormat;-><init>(IIII)V
Landroid/media/AudioFormat;->mChannelMask:I
Landroid/media/AudioFormat;->mEncoding:I
Landroid/media/AudioFormat;->mSampleRate:I
+Landroid/media/audiofx/AudioEffect;->command(I[B[B)I
+Landroid/media/audiofx/AudioEffect;->getParameter([I[B)I
Landroid/media/audiofx/AudioEffect;-><init>(Ljava/util/UUID;Ljava/util/UUID;II)V
Landroid/media/AudioGainConfig;-><init>(ILandroid/media/AudioGain;II[II)V
Landroid/media/AudioGainConfig;->mChannelMask:I
@@ -874,33 +783,21 @@
Landroid/media/AudioGain;-><init>(IIIIIIIII)V
Landroid/media/AudioHandle;-><init>(I)V
Landroid/media/AudioHandle;->mId:I
-Landroid/media/AudioManager;->abandonAudioFocus(Landroid/media/AudioManager$OnAudioFocusChangeListener;Landroid/media/AudioAttributes;)I
+Landroid/media/AudioManager;->forceVolumeControlStream(I)V
Landroid/media/AudioManager;->getOutputLatency(I)I
Landroid/media/AudioManager;->getService()Landroid/media/IAudioService;
Landroid/media/AudioManager;->mAudioFocusIdListenerMap:Ljava/util/concurrent/ConcurrentHashMap;
-Landroid/media/AudioManager;->registerAudioPolicy(Landroid/media/audiopolicy/AudioPolicy;)I
-Landroid/media/AudioManager;->requestAudioFocus(Landroid/media/AudioFocusRequest;Landroid/media/audiopolicy/AudioPolicy;)I
-Landroid/media/AudioManager;->requestAudioFocus(Landroid/media/AudioManager$OnAudioFocusChangeListener;Landroid/media/AudioAttributes;II)I
-Landroid/media/AudioManager;->requestAudioFocus(Landroid/media/AudioManager$OnAudioFocusChangeListener;Landroid/media/AudioAttributes;IILandroid/media/audiopolicy/AudioPolicy;)I
Landroid/media/AudioManager;->setMasterMute(ZI)V
Landroid/media/AudioManager;->STREAM_BLUETOOTH_SCO:I
Landroid/media/AudioManager;->STREAM_SYSTEM_ENFORCED:I
Landroid/media/AudioManager;->STREAM_TTS:I
-Landroid/media/AudioManager;->unregisterAudioPolicyAsync(Landroid/media/audiopolicy/AudioPolicy;)V
Landroid/media/AudioMixPortConfig;-><init>(Landroid/media/AudioMixPort;IIILandroid/media/AudioGainConfig;)V
Landroid/media/AudioMixPort;-><init>(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V
Landroid/media/AudioPatch;-><init>(Landroid/media/AudioHandle;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)V
Landroid/media/AudioPatch;->mHandle:Landroid/media/AudioHandle;
-Landroid/media/audiopolicy/AudioMix$Builder;->build()Landroid/media/audiopolicy/AudioMix;
-Landroid/media/audiopolicy/AudioMix$Builder;-><init>(Landroid/media/audiopolicy/AudioMixingRule;)V
-Landroid/media/audiopolicy/AudioMix$Builder;->setFormat(Landroid/media/AudioFormat;)Landroid/media/audiopolicy/AudioMix$Builder;
-Landroid/media/audiopolicy/AudioMix$Builder;->setRouteFlags(I)Landroid/media/audiopolicy/AudioMix$Builder;
Landroid/media/audiopolicy/AudioMixingRule$AudioMixMatchCriterion;->mAttr:Landroid/media/AudioAttributes;
Landroid/media/audiopolicy/AudioMixingRule$AudioMixMatchCriterion;->mIntProp:I
Landroid/media/audiopolicy/AudioMixingRule$AudioMixMatchCriterion;->mRule:I
-Landroid/media/audiopolicy/AudioMixingRule$Builder;->addRule(Landroid/media/AudioAttributes;I)Landroid/media/audiopolicy/AudioMixingRule$Builder;
-Landroid/media/audiopolicy/AudioMixingRule$Builder;->build()Landroid/media/audiopolicy/AudioMixingRule;
-Landroid/media/audiopolicy/AudioMixingRule$Builder;-><init>()V
Landroid/media/audiopolicy/AudioMixingRule;->mCriteria:Ljava/util/ArrayList;
Landroid/media/audiopolicy/AudioMix;->mCallbackFlags:I
Landroid/media/audiopolicy/AudioMix;->mDeviceAddress:Ljava/lang/String;
@@ -909,13 +806,6 @@
Landroid/media/audiopolicy/AudioMix;->mMixType:I
Landroid/media/audiopolicy/AudioMix;->mRouteFlags:I
Landroid/media/audiopolicy/AudioMix;->mRule:Landroid/media/audiopolicy/AudioMixingRule;
-Landroid/media/audiopolicy/AudioPolicy$AudioPolicyFocusListener;-><init>()V
-Landroid/media/audiopolicy/AudioPolicy$Builder;->addMix(Landroid/media/audiopolicy/AudioMix;)Landroid/media/audiopolicy/AudioPolicy$Builder;
-Landroid/media/audiopolicy/AudioPolicy$Builder;->build()Landroid/media/audiopolicy/AudioPolicy;
-Landroid/media/audiopolicy/AudioPolicy$Builder;-><init>(Landroid/content/Context;)V
-Landroid/media/audiopolicy/AudioPolicy$Builder;->setAudioPolicyFocusListener(Landroid/media/audiopolicy/AudioPolicy$AudioPolicyFocusListener;)V
-Landroid/media/audiopolicy/AudioPolicy$Builder;->setLooper(Landroid/os/Looper;)Landroid/media/audiopolicy/AudioPolicy$Builder;
-Landroid/media/audiopolicy/AudioPolicy;->createAudioRecordSink(Landroid/media/audiopolicy/AudioMix;)Landroid/media/AudioRecord;
Landroid/media/AudioPortConfig;-><init>(Landroid/media/AudioPort;IIILandroid/media/AudioGainConfig;)V
Landroid/media/AudioPortConfig;->mChannelMask:I
Landroid/media/AudioPortConfig;->mConfigMask:I
@@ -930,9 +820,12 @@
Landroid/media/AudioPort;->mGains:[Landroid/media/AudioGain;
Landroid/media/AudioPort;->mHandle:Landroid/media/AudioHandle;
Landroid/media/AudioPort;->mRole:I
+Landroid/media/AudioRecordingConfiguration;->getClientPackageName()Ljava/lang/String;
+Landroid/media/AudioRecordingConfiguration;->getClientUid()I
Landroid/media/AudioRecord;->mNativeCallbackCookie:J
Landroid/media/AudioRecord;->mNativeDeviceCallback:J
Landroid/media/AudioRecord;->mNativeRecorderInJavaObj:J
+Landroid/media/AudioRecord;->native_release()V
Landroid/media/AudioRecord;->postEventFromNative(Ljava/lang/Object;IIILjava/lang/Object;)V
Landroid/media/AudioSystem;->dynamicPolicyCallbackFromNative(ILjava/lang/String;I)V
Landroid/media/AudioSystem;->errorCallbackFromNative(I)V
@@ -940,15 +833,18 @@
Landroid/media/AudioSystem;->getPrimaryOutputSamplingRate()I
Landroid/media/AudioSystem;->recordingCallbackFromNative(IIII[I)V
Landroid/media/AudioSystem;->setDeviceConnectionState(IILjava/lang/String;Ljava/lang/String;)I
+Landroid/media/AudioTrack;->deferred_connect(J)V
Landroid/media/AudioTrack;->getLatency()I
Landroid/media/AudioTrack;->mJniData:J
Landroid/media/AudioTrack;->mNativeTrackInJavaObj:J
Landroid/media/AudioTrack;->mStreamType:I
+Landroid/media/AudioTrack;->native_release()V
Landroid/media/AudioTrack;->postEventFromNative(Ljava/lang/Object;IIILjava/lang/Object;)V
Landroid/media/IAudioService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IAudioService;
Landroid/media/IAudioService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/media/JetPlayer;->mNativePlayerInJavaObj:J
Landroid/media/JetPlayer;->postEventFromNative(Ljava/lang/Object;III)V
+Landroid/media/MediaCodec$CodecException;-><init>(IILjava/lang/String;)V
Landroid/media/MediaCodec;->releaseOutputBuffer(IZZJ)V
Landroid/media/MediaFile;->FIRST_AUDIO_FILE_TYPE:I
Landroid/media/MediaFile;->getFileType(Ljava/lang/String;)Landroid/media/MediaFile$MediaFileType;
@@ -972,7 +868,6 @@
Landroid/media/MediaPlayer;->setDataSource(Ljava/lang/String;Ljava/util/Map;Ljava/util/List;)V
Landroid/media/MediaPlayer;->setDataSource(Ljava/lang/String;Ljava/util/Map;)V
Landroid/media/MediaPlayer;->setRetransmitEndpoint(Ljava/net/InetSocketAddress;)V
-Landroid/media/MediaRecorder$AudioSource;->RADIO_TUNER:I
Landroid/media/MediaRouter$RouteInfo;->getStatusCode()I
Landroid/media/MediaRouter$RouteInfo;->STATUS_CONNECTING:I
Landroid/media/MediaRouter;->selectRouteInt(ILandroid/media/MediaRouter$RouteInfo;Z)V
@@ -999,6 +894,10 @@
Landroid/media/RemoteDisplay;->notifyDisplayError(I)V
Landroid/media/RingtoneManager;->getRingtone(Landroid/content/Context;Landroid/net/Uri;I)Landroid/media/Ringtone;
Landroid/media/session/MediaSessionLegacyHelper;->getHelper(Landroid/content/Context;)Landroid/media/session/MediaSessionLegacyHelper;
+Landroid/media/soundtrigger/SoundTriggerDetector$EventPayload;->getCaptureSession()Ljava/lang/Integer;
+Landroid/media/soundtrigger/SoundTriggerDetector$EventPayload;->getData()[B
+Landroid/media/soundtrigger/SoundTriggerManager;->loadSoundModel(Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;)I
+Landroid/media/soundtrigger/SoundTriggerManager;->startRecognition(Ljava/util/UUID;Landroid/app/PendingIntent;Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;)I
Landroid/media/soundtrigger/SoundTriggerManager;->stopRecognition(Ljava/util/UUID;)I
Landroid/media/soundtrigger/SoundTriggerManager;->unloadSoundModel(Ljava/util/UUID;)I
Landroid/media/SubtitleController;->mHandler:Landroid/os/Handler;
@@ -1019,19 +918,6 @@
Landroid/media/VolumeShaper$State;-><init>(FF)V
Landroid/media/VolumeShaper$State;->mVolume:F
Landroid/media/VolumeShaper$State;->mXOffset:F
-Landroid/metrics/LogMaker;->getCategory()I
-Landroid/metrics/LogMaker;->getCounterBucket()J
-Landroid/metrics/LogMaker;->getCounterName()Ljava/lang/String;
-Landroid/metrics/LogMaker;->getCounterValue()I
-Landroid/metrics/LogMaker;->getTimestamp()J
-Landroid/metrics/LogMaker;->isLongCounterBucket()Z
-Landroid/metrics/LogMaker;->serialize()[Ljava/lang/Object;
-Landroid/metrics/MetricsReader;->checkpoint()V
-Landroid/metrics/MetricsReader;->hasNext()Z
-Landroid/metrics/MetricsReader;-><init>()V
-Landroid/metrics/MetricsReader;->next()Landroid/metrics/LogMaker;
-Landroid/metrics/MetricsReader;->read(J)V
-Landroid/metrics/MetricsReader;->reset()V
Landroid/net/ConnectivityManager;->ACTION_TETHER_STATE_CHANGED:Ljava/lang/String;
Landroid/net/ConnectivityManager;->EXTRA_ACTIVE_TETHER:Ljava/lang/String;
Landroid/net/ConnectivityManager;->getActiveLinkProperties()Landroid/net/LinkProperties;
@@ -1042,14 +928,9 @@
Landroid/net/ConnectivityManager;->getTetheredIfaces()[Ljava/lang/String;
Landroid/net/ConnectivityManager;->isNetworkSupported(I)Z
Landroid/net/ConnectivityManager;->isNetworkTypeMobile(I)Z
-Landroid/net/ConnectivityManager;->isTetheringSupported()Z
Landroid/net/ConnectivityManager;->mService:Landroid/net/IConnectivityManager;
-Landroid/net/ConnectivityManager$OnStartTetheringCallback;-><init>()V
Landroid/net/ConnectivityManager;->requestRouteToHostAddress(ILjava/net/InetAddress;)Z
Landroid/net/ConnectivityManager;->requestRouteToHost(II)Z
-Landroid/net/ConnectivityManager;->startTethering(IZLandroid/net/ConnectivityManager$OnStartTetheringCallback;Landroid/os/Handler;)V
-Landroid/net/ConnectivityManager;->startTethering(IZLandroid/net/ConnectivityManager$OnStartTetheringCallback;)V
-Landroid/net/ConnectivityManager;->stopTethering(I)V
Landroid/net/ConnectivityManager;->TYPE_MOBILE_CBS:I
Landroid/net/ConnectivityManager;->TYPE_MOBILE_EMERGENCY:I
Landroid/net/ConnectivityManager;->TYPE_MOBILE_FOTA:I
@@ -1070,12 +951,7 @@
Landroid/net/LocalSocketImpl;->outboundFileDescriptors:[Ljava/io/FileDescriptor;
Landroid/net/NetworkCapabilities;->getCapabilities()[I
Landroid/net/NetworkCapabilities;->getTransportTypes()[I
-Landroid/net/NetworkKey;-><init>(Landroid/net/WifiKey;)V
Landroid/net/NetworkPolicyManager;->mService:Landroid/net/INetworkPolicyManager;
-Landroid/net/NetworkRecommendationProvider;-><init>(Landroid/content/Context;Ljava/util/concurrent/Executor;)V
-Landroid/net/NetworkScoreManager;->clearScores()Z
-Landroid/net/NetworkScoreManager;->getActiveScorerPackage()Ljava/lang/String;
-Landroid/net/NetworkScoreManager;->updateScores([Landroid/net/ScoredNetwork;)Z
Landroid/net/NetworkStats;->capacity:I
Landroid/net/NetworkStats;->defaultNetwork:[I
Landroid/net/NetworkStats;->iface:[Ljava/lang/String;
@@ -1091,12 +967,6 @@
Landroid/net/NetworkStats;->txPackets:[J
Landroid/net/NetworkStats;->uid:[I
Landroid/net/ProxyInfo;-><init>(Ljava/lang/String;ILjava/lang/String;)V
-Landroid/net/RssiCurve;-><init>(II[BI)V
-Landroid/net/RssiCurve;-><init>(II[B)V
-Landroid/net/RssiCurve;->lookupScore(IZ)B
-Landroid/net/ScoredNetwork;-><init>(Landroid/net/NetworkKey;Landroid/net/RssiCurve;)V
-Landroid/net/ScoredNetwork;-><init>(Landroid/net/NetworkKey;Landroid/net/RssiCurve;ZLandroid/os/Bundle;)V
-Landroid/net/ScoredNetwork;-><init>(Landroid/net/NetworkKey;Landroid/net/RssiCurve;Z)V
Landroid/net/SSLCertificateSocketFactory;->castToOpenSSLSocket(Ljava/net/Socket;)Lcom/android/org/conscrypt/OpenSSLSocketImpl;
Landroid/net/SSLCertificateSocketFactory;->getAlpnSelectedProtocol(Ljava/net/Socket;)[B
Landroid/net/SSLCertificateSocketFactory;->getDelegate()Ljavax/net/ssl/SSLSocketFactory;
@@ -1119,28 +989,19 @@
Landroid/net/SSLCertificateSocketFactory;->setChannelIdPrivateKey(Ljava/security/PrivateKey;)V
Landroid/net/SSLCertificateSocketFactory;->setSoWriteTimeout(Ljava/net/Socket;I)V
Landroid/net/SSLCertificateSocketFactory;->TAG:Ljava/lang/String;
-Landroid/net/SSLCertificateSocketFactory;->toLengthPrefixedList([[[B)[B
Landroid/net/SSLCertificateSocketFactory;->verifyHostname(Ljava/net/Socket;Ljava/lang/String;)V
Landroid/net/SSLSessionCache;->mSessionCache:Lcom/android/org/conscrypt/SSLClientSessionCache;
Landroid/net/TrafficStats;->getRxBytes(Ljava/lang/String;)J
Landroid/net/TrafficStats;->getStatsService()Landroid/net/INetworkStatsService;
Landroid/net/TrafficStats;->getTxBytes(Ljava/lang/String;)J
-Landroid/net/TrafficStats;->setThreadStatsTagBackup()V
-Landroid/net/TrafficStats;->setThreadStatsTagRestore()V
-Landroid/net/TrafficStats;->setThreadStatsUid(I)V
Landroid/net/Uri;-><init>()V
-Landroid/net/WebAddress;-><init>(Ljava/lang/String;)V
Landroid/net/wifi/IWifiManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/IWifiManager;
Landroid/net/wifi/IWifiManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/net/WifiKey;-><init>(Ljava/lang/String;Ljava/lang/String;)V
Landroid/net/wifi/p2p/WifiP2pGroup;->getNetworkId()I
Landroid/net/wifi/p2p/WifiP2pGroupList;->getGroupList()Ljava/util/Collection;
Landroid/net/wifi/p2p/WifiP2pManager;->deletePersistentGroup(Landroid/net/wifi/p2p/WifiP2pManager$Channel;ILandroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V
Landroid/net/wifi/p2p/WifiP2pManager;->requestPersistentGroupInfo(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Landroid/net/wifi/p2p/WifiP2pManager$PersistentGroupInfoListener;)V
Landroid/net/wifi/p2p/WifiP2pManager;->setDeviceName(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Ljava/lang/String;Landroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V
-Landroid/net/wifi/RttManager;->getRttCapabilities()Landroid/net/wifi/RttManager$RttCapabilities;
-Landroid/net/wifi/RttManager$RttParams;-><init>()V
-Landroid/net/wifi/RttManager;->startRanging([Landroid/net/wifi/RttManager$RttParams;Landroid/net/wifi/RttManager$RttListener;)V
Landroid/net/wifi/ScanResult;->anqpDomainId:I
Landroid/net/wifi/ScanResult;->anqpLines:Ljava/util/List;
Landroid/net/wifi/ScanResult;->distanceCm:I
@@ -1153,54 +1014,23 @@
Landroid/net/wifi/ScanResult;->wifiSsid:Landroid/net/wifi/WifiSsid;
Landroid/net/wifi/WifiConfiguration;->apBand:I
Landroid/net/wifi/WifiConfiguration;->apChannel:I
-Landroid/net/wifi/WifiConfiguration;->creatorUid:I
-Landroid/net/wifi/WifiConfiguration;->hasNoInternetAccess()Z
-Landroid/net/wifi/WifiConfiguration;->isEphemeral()Z
-Landroid/net/wifi/WifiConfiguration;->isNoInternetAccessExpected()Z
-Landroid/net/wifi/WifiConfiguration;->lastUpdateUid:I
+Landroid/net/wifi/WifiConfiguration;->defaultGwMacAddress:Ljava/lang/String;
Landroid/net/wifi/WifiConfiguration;->mIpConfiguration:Landroid/net/IpConfiguration;
-Landroid/net/wifi/WifiConfiguration;->numAssociation:I
Landroid/net/wifi/WifiConfiguration;->validatedInternetAccess:Z
Landroid/net/wifi/WifiEnterpriseConfig;->getCaCertificateAlias()Ljava/lang/String;
Landroid/net/wifi/WifiEnterpriseConfig;->getClientCertificateAlias()Ljava/lang/String;
Landroid/net/wifi/WifiInfo;->getMeteredHint()Z
Landroid/net/wifi/WifiInfo;->mMacAddress:Ljava/lang/String;
+Landroid/net/wifi/WifiInfo;->removeDoubleQuotes(Ljava/lang/String;)Ljava/lang/String;
Landroid/net/wifi/WifiManager;->cancelLocalOnlyHotspotRequest()V
Landroid/net/wifi/WifiManager;->connect(ILandroid/net/wifi/WifiManager$ActionListener;)V
-Landroid/net/wifi/WifiManager;->connect(Landroid/net/wifi/WifiConfiguration;Landroid/net/wifi/WifiManager$ActionListener;)V
-Landroid/net/wifi/WifiManager;->EXTRA_WIFI_AP_STATE:Ljava/lang/String;
Landroid/net/wifi/WifiManager;->forget(ILandroid/net/wifi/WifiManager$ActionListener;)V
-Landroid/net/wifi/WifiManager;->getPrivilegedConfiguredNetworks()Ljava/util/List;
-Landroid/net/wifi/WifiManager;->getWifiApConfiguration()Landroid/net/wifi/WifiConfiguration;
-Landroid/net/wifi/WifiManager;->getWifiApState()I
Landroid/net/wifi/WifiManager;->isDualBandSupported()Z
-Landroid/net/wifi/WifiManager;->isWifiApEnabled()Z
-Landroid/net/wifi/WifiManager;->isWifiScannerSupported()Z
Landroid/net/wifi/WifiManager;->mService:Landroid/net/wifi/IWifiManager;
Landroid/net/wifi/WifiManager;->save(Landroid/net/wifi/WifiConfiguration;Landroid/net/wifi/WifiManager$ActionListener;)V
-Landroid/net/wifi/WifiManager;->setWifiApConfiguration(Landroid/net/wifi/WifiConfiguration;)Z
-Landroid/net/wifi/WifiManager;->startScan(Landroid/os/WorkSource;)Z
-Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_CHANGED_ACTION:Ljava/lang/String;
-Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_DISABLED:I
-Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_DISABLING:I
-Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_ENABLED:I
-Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_ENABLING:I
-Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_FAILED:I
-Landroid/net/wifi/WifiScanner;->getScanResults()Z
-Landroid/net/wifi/WifiScanner$ScanData;->getResults()[Landroid/net/wifi/ScanResult;
-Landroid/net/wifi/WifiScanner$ScanSettings;-><init>()V
-Landroid/net/wifi/WifiScanner;->startBackgroundScan(Landroid/net/wifi/WifiScanner$ScanSettings;Landroid/net/wifi/WifiScanner$ScanListener;)V
-Landroid/net/wifi/WifiScanner;->startScan(Landroid/net/wifi/WifiScanner$ScanSettings;Landroid/net/wifi/WifiScanner$ScanListener;Landroid/os/WorkSource;)V
-Landroid/net/wifi/WifiScanner;->startScan(Landroid/net/wifi/WifiScanner$ScanSettings;Landroid/net/wifi/WifiScanner$ScanListener;)V
-Landroid/net/wifi/WifiScanner;->stopBackgroundScan(Landroid/net/wifi/WifiScanner$ScanListener;)V
Landroid/net/wifi/WifiSsid;->NONE:Ljava/lang/String;
-Landroid/nfc/NfcAdapter;->addNfcUnlockHandler(Landroid/nfc/NfcAdapter$NfcUnlockHandler;[Ljava/lang/String;)Z
-Landroid/nfc/NfcAdapter;->disable()Z
-Landroid/nfc/NfcAdapter;->enable()Z
Landroid/nfc/NfcAdapter;->getDefaultAdapter()Landroid/nfc/NfcAdapter;
-Landroid/nfc/NfcAdapter;->removeNfcUnlockHandler(Landroid/nfc/NfcAdapter$NfcUnlockHandler;)Z
Landroid/nfc/NfcAdapter;->setNdefPushMessageCallback(Landroid/nfc/NfcAdapter$CreateNdefMessageCallback;Landroid/app/Activity;I)V
-Landroid/nfc/NfcAdapter;->setNdefPushMessage(Landroid/nfc/NdefMessage;Landroid/app/Activity;I)V
Landroid/opengl/GLSurfaceView$EglHelper;->mEglContext:Ljavax/microedition/khronos/egl/EGLContext;
Landroid/opengl/GLSurfaceView$GLThread;->mEglHelper:Landroid/opengl/GLSurfaceView$EglHelper;
Landroid/opengl/GLSurfaceView;->mGLThread:Landroid/opengl/GLSurfaceView$GLThread;
@@ -1229,7 +1059,6 @@
Landroid/os/Binder;->mObject:J
Landroid/os/Build;->getString(Ljava/lang/String;)Ljava/lang/String;
Landroid/os/Build$VERSION;->ACTIVE_CODENAMES:[Ljava/lang/String;
-Landroid/os/Build$VERSION;->RESOURCES_SDK_INT:I
Landroid/os/Bundle;->getIBinder(Ljava/lang/String;)Landroid/os/IBinder;
Landroid/os/Bundle;->putIBinder(Ljava/lang/String;Landroid/os/IBinder;)V
Landroid/os/Debug;->countInstancesOfClass(Ljava/lang/Class;)J
@@ -1264,6 +1093,7 @@
Landroid/os/Debug$MemoryInfo;->otherSwappedOut:I
Landroid/os/Debug$MemoryInfo;->otherSwappedOutPss:I
Landroid/os/Environment;->buildExternalStorageAppDataDirs(Ljava/lang/String;)[Ljava/io/File;
+Landroid/os/Environment;->getVendorDirectory()Ljava/io/File;
Landroid/os/FileObserver$ObserverThread;->onEvent(IILjava/lang/String;)V
Landroid/os/FileUtils;->checksumCrc32(Ljava/io/File;)J
Landroid/os/FileUtils;->copyFile(Ljava/io/File;Ljava/io/File;)Z
@@ -1279,7 +1109,6 @@
Landroid/os/Handler;->hasCallbacks(Ljava/lang/Runnable;)Z
Landroid/os/Handler;->mCallback:Landroid/os/Handler$Callback;
Landroid/os/Handler;->mMessenger:Landroid/os/IMessenger;
-Landroid/os/HwBlob;-><init>(I)V
Landroid/os/HwParcel;-><init>(Z)V
Landroid/os/HwRemoteBinder;-><init>()V
Landroid/os/IBatteryPropertiesRegistrar$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -1311,12 +1140,13 @@
Landroid/os/Message;->when:J
Landroid/os/ParcelFileDescriptor;-><init>(Ljava/io/FileDescriptor;)V
Landroid/os/Parcel;->mNativePtr:J
+Landroid/os/Parcel;->readArrayMap(Landroid/util/ArrayMap;Ljava/lang/ClassLoader;)V
Landroid/os/Parcel$ReadWriteHelper;-><init>()V
+Landroid/os/Parcel;->writeArrayMap(Landroid/util/ArrayMap;)V
Landroid/os/PowerManager;->getMaximumScreenBrightnessSetting()I
Landroid/os/PowerManager;->getMinimumScreenBrightnessSetting()I
Landroid/os/PowerManager;->isLightDeviceIdleMode()Z
Landroid/os/PowerManager;->mService:Landroid/os/IPowerManager;
-Landroid/os/PowerManager;->userActivity(JII)V
Landroid/os/PowerManager;->userActivity(JZ)V
Landroid/os/PowerManager;->validateWakeLockParameters(ILjava/lang/String;)V
Landroid/os/PowerManager;->wakeUp(JLjava/lang/String;)V
@@ -1328,12 +1158,6 @@
Landroid/os/Process;->isIsolated(I)Z
Landroid/os/Process;->readProcFile(Ljava/lang/String;[I[Ljava/lang/String;[J[F)Z
Landroid/os/Process;->readProcLines(Ljava/lang/String;[Ljava/lang/String;[J)V
-Landroid/os/RecoverySystem;->cancelScheduledUpdate(Landroid/content/Context;)V
-Landroid/os/RecoverySystem;->installPackage(Landroid/content/Context;Ljava/io/File;Z)V
-Landroid/os/RecoverySystem;->processPackage(Landroid/content/Context;Ljava/io/File;Landroid/os/RecoverySystem$ProgressListener;Landroid/os/Handler;)V
-Landroid/os/RecoverySystem;->processPackage(Landroid/content/Context;Ljava/io/File;Landroid/os/RecoverySystem$ProgressListener;)V
-Landroid/os/RecoverySystem;->rebootWipeAb(Landroid/content/Context;Ljava/io/File;Ljava/lang/String;)V
-Landroid/os/RecoverySystem;->scheduleUpdateOnBoot(Landroid/content/Context;Ljava/io/File;)V
Landroid/os/SELinux;->isSELinuxEnabled()Z
Landroid/os/SELinux;->isSELinuxEnforced()Z
Landroid/os/ServiceManager;->addService(Ljava/lang/String;Landroid/os/IBinder;)V
@@ -1345,6 +1169,7 @@
Landroid/os/ServiceManagerNative;->asInterface(Landroid/os/IBinder;)Landroid/os/IServiceManager;
Landroid/os/ServiceManager;->sCache:Ljava/util/HashMap;
Landroid/os/ServiceManager;->sServiceManager:Landroid/os/IServiceManager;
+Landroid/os/SharedMemory;->getFd()I
Landroid/os/storage/DiskInfo;->getDescription()Ljava/lang/String;
Landroid/os/storage/IStorageManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/storage/IStorageManager;
Landroid/os/storage/IStorageManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -1373,13 +1198,9 @@
Landroid/os/StrictMode;->disableDeathOnFileUriExposure()V
Landroid/os/StrictMode;->getThreadPolicyMask()I
Landroid/os/StrictMode;->onBinderStrictModePolicyChange(I)V
+Landroid/os/StrictMode$ThreadPolicy$Builder;->penaltyListener(Landroid/os/StrictMode$OnThreadViolationListener;Ljava/util/concurrent/Executor;)Landroid/os/StrictMode$ThreadPolicy$Builder;
Landroid/os/StrictMode;->violationsBeingTimed:Ljava/lang/ThreadLocal;
Landroid/os/SystemProperties;->addChangeCallback(Ljava/lang/Runnable;)V
-Landroid/os/SystemProperties;->getBoolean(Ljava/lang/String;Z)Z
-Landroid/os/SystemProperties;->getInt(Ljava/lang/String;I)I
-Landroid/os/SystemProperties;->get(Ljava/lang/String;)Ljava/lang/String;
-Landroid/os/SystemProperties;->get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
-Landroid/os/SystemProperties;->getLong(Ljava/lang/String;J)J
Landroid/os/SystemProperties;-><init>()V
Landroid/os/SystemProperties;->native_get(Ljava/lang/String;)Ljava/lang/String;
Landroid/os/SystemProperties;->PROP_NAME_MAX:I
@@ -1393,15 +1214,6 @@
Landroid/os/Trace;->traceEnd(J)V
Landroid/os/Trace;->TRACE_TAG_APP:J
Landroid/os/Trace;->TRACE_TAG_VIEW:J
-Landroid/os/UpdateEngine;->applyPayload(Ljava/lang/String;JJ[Ljava/lang/String;)V
-Landroid/os/UpdateEngine;->bind(Landroid/os/UpdateEngineCallback;Landroid/os/Handler;)Z
-Landroid/os/UpdateEngine;->bind(Landroid/os/UpdateEngineCallback;)Z
-Landroid/os/UpdateEngineCallback;-><init>()V
-Landroid/os/UpdateEngineCallback;->onPayloadApplicationComplete(I)V
-Landroid/os/UpdateEngineCallback;->onStatusUpdate(IF)V
-Landroid/os/UpdateEngine;->cancel()V
-Landroid/os/UpdateEngine;-><init>()V
-Landroid/os/UpdateEngine;->resetStatus()V
Landroid/os/UpdateLock;->acquire()V
Landroid/os/UpdateLock;->isHeld()Z
Landroid/os/UpdateLock;->NOW_IS_CONVENIENT:Ljava/lang/String;
@@ -1411,13 +1223,9 @@
Landroid/os/UserHandle;->ALL:Landroid/os/UserHandle;
Landroid/os/UserHandle;->getAppIdFromSharedAppGid(I)I
Landroid/os/UserHandle;->getCallingUserId()I
-Landroid/os/UserHandle;->getIdentifier()I
Landroid/os/UserHandle;->getUid(II)I
Landroid/os/UserHandle;->getUserId(I)I
Landroid/os/UserHandle;-><init>(I)V
-Landroid/os/UserHandle;->isOwner()Z
-Landroid/os/UserHandle;->myUserId()I
-Landroid/os/UserHandle;->of(I)Landroid/os/UserHandle;
Landroid/os/UserHandle;->PER_USER_RANGE:I
Landroid/os/UserHandle;->USER_OWNER:I
Landroid/os/UserManager;->getBadgedLabelForUser(Ljava/lang/CharSequence;Landroid/os/UserHandle;)Ljava/lang/CharSequence;
@@ -1426,25 +1234,25 @@
Landroid/os/UserManager;->getProfiles(I)Ljava/util/List;
Landroid/os/UserManager;->getUserHandle()I
Landroid/os/UserManager;->getUserHandle(I)I
+Landroid/os/UserManager;->getUserIcon(I)Landroid/graphics/Bitmap;
Landroid/os/UserManager;->getUserInfo(I)Landroid/content/pm/UserInfo;
-Landroid/os/UserManager;->getUserRestrictionSource(Ljava/lang/String;Landroid/os/UserHandle;)I
Landroid/os/UserManager;->getUserSerialNumber(I)I
Landroid/os/UserManager;->getUsers()Ljava/util/List;
Landroid/os/UserManager;->hasBaseUserRestriction(Ljava/lang/String;Landroid/os/UserHandle;)Z
Landroid/os/UserManager;->isLinkedUser()Z
-Landroid/os/UserManager;->isManagedProfile()Z
Landroid/os/UserManager;->isUserUnlocked(I)Z
Landroid/os/VintfObject;->report()[Ljava/lang/String;
Landroid/os/WorkSource;->add(ILjava/lang/String;)Z
Landroid/os/WorkSource;->add(I)Z
-Landroid/os/WorkSource;->createWorkChain()Landroid/os/WorkSource$WorkChain;
+Landroid/os/WorkSource;->addReturningNewbs(Landroid/os/WorkSource;)Landroid/os/WorkSource;
Landroid/os/WorkSource;->get(I)I
Landroid/os/WorkSource;->getName(I)Ljava/lang/String;
+Landroid/os/WorkSource;-><init>(I)V
Landroid/os/WorkSource;->mNames:[Ljava/lang/String;
Landroid/os/WorkSource;->mNum:I
Landroid/os/WorkSource;->mUids:[I
+Landroid/os/WorkSource;->setReturningDiffs(Landroid/os/WorkSource;)[Landroid/os/WorkSource;
Landroid/os/WorkSource;->size()I
-Landroid/os/WorkSource$WorkChain;->addNode(ILjava/lang/String;)Landroid/os/WorkSource$WorkChain;
Landroid/preference/DialogPreference;->mBuilder:Landroid/app/AlertDialog$Builder;
Landroid/preference/DialogPreference;->mDialogIcon:Landroid/graphics/drawable/Drawable;
Landroid/preference/DialogPreference;->mDialog:Landroid/app/Dialog;
@@ -1490,20 +1298,17 @@
Landroid/provider/Browser;->sendString(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)V
Landroid/provider/Settings$ContentProviderHolder;->mContentProvider:Landroid/content/IContentProvider;
Landroid/provider/Settings$Global;->ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED:Ljava/lang/String;
-Landroid/provider/Settings$Global;->OTA_DISABLE_AUTOMATIC_UPDATE:Ljava/lang/String;
Landroid/provider/Settings$Global;->PACKAGE_VERIFIER_ENABLE:Ljava/lang/String;
Landroid/provider/Settings$Global;->sNameValueCache:Landroid/provider/Settings$NameValueCache;
Landroid/provider/Settings$NameValueCache;->mProviderHolder:Landroid/provider/Settings$ContentProviderHolder;
Landroid/provider/Settings$Secure;->ACCESSIBILITY_AUTOCLICK_ENABLED:Ljava/lang/String;
Landroid/provider/Settings$Secure;->ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED:Ljava/lang/String;
Landroid/provider/Settings$Secure;->ACCESSIBILITY_LARGE_POINTER_ICON:Ljava/lang/String;
Landroid/provider/Settings$Secure;->ENABLED_NOTIFICATION_LISTENERS:Ljava/lang/String;
Landroid/provider/Settings$Secure;->INCALL_POWER_BUTTON_BEHAVIOR:Ljava/lang/String;
Landroid/provider/Settings$Secure;->LONG_PRESS_TIMEOUT:Ljava/lang/String;
Landroid/provider/Settings$Secure;->PACKAGE_VERIFIER_USER_CONSENT:Ljava/lang/String;
Landroid/provider/Settings$Secure;->sNameValueCache:Landroid/provider/Settings$NameValueCache;
-Landroid/provider/Settings$Secure;->USER_SETUP_COMPLETE:Ljava/lang/String;
Landroid/provider/Settings$System;->AIRPLANE_MODE_TOGGLEABLE_RADIOS:Ljava/lang/String;
Landroid/provider/Settings$System;->getStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;I)Ljava/lang/String;
Landroid/provider/Settings$System;->HEARING_AID:Ljava/lang/String;
@@ -1712,11 +1517,43 @@
Landroid/R$styleable;->Window_windowBackground:I
Landroid/R$styleable;->Window_windowFrame:I
Landroid/security/KeyStore;->getInstance()Landroid/security/KeyStore;
+Landroid/security/keystore/KeychainProtectionParams;->clearSecret()V
+Landroid/security/keystore/KeychainProtectionParams;->getKeyDerivationParams()Landroid/security/keystore/KeyDerivationParams;
+Landroid/security/keystore/KeychainProtectionParams;->getLockScreenUiFormat()I
+Landroid/security/keystore/KeychainProtectionParams;->getSecret()[B
+Landroid/security/keystore/KeychainProtectionParams;->getUserSecretType()I
+Landroid/security/keystore/KeychainProtectionParams;-><init>(IILandroid/security/keystore/KeyDerivationParams;[B)V
+Landroid/security/keystore/KeychainProtectionParams;-><init>(Landroid/os/Parcel;)V
+Landroid/security/keystore/KeychainProtectionParams;-><init>()V
+Landroid/security/keystore/KeychainSnapshot;->getCounterId()J
+Landroid/security/keystore/KeychainSnapshot;->getEncryptedRecoveryKeyBlob()[B
+Landroid/security/keystore/KeychainSnapshot;->getKeychainProtectionParams()Ljava/util/List;
+Landroid/security/keystore/KeychainSnapshot;->getMaxAttempts()I
+Landroid/security/keystore/KeychainSnapshot;->getServerParams()[B
+Landroid/security/keystore/KeychainSnapshot;->getSnapshotVersion()I
+Landroid/security/keystore/KeychainSnapshot;->getTrustedHardwarePublicKey()[B
+Landroid/security/keystore/KeychainSnapshot;->getWrappedApplicationKeys()Ljava/util/List;
+Landroid/security/keystore/KeyDerivationParams;->ALGORITHM_ARGON2ID:I
+Landroid/security/keystore/KeyDerivationParams;->ALGORITHM_SHA256:I
+Landroid/security/keystore/KeyDerivationParams;->createSha256Params([B)Landroid/security/keystore/KeyDerivationParams;
+Landroid/security/keystore/KeyDerivationParams;->getAlgorithm()I
+Landroid/security/keystore/KeyDerivationParams;->getSalt()[B
+Landroid/security/keystore/KeyDerivationParams;-><init>(I[B)V
+Landroid/security/keystore/KeyDerivationParams;-><init>(Landroid/os/Parcel;)V
+Landroid/security/keystore/RecoveryClaim;->getClaimBytes()[B
+Landroid/security/keystore/RecoveryClaim;->getRecoverySession()Landroid/security/keystore/RecoverySession;
Landroid/security/keystore/RecoveryController;->getInstance()Landroid/security/keystore/RecoveryController;
+Landroid/security/keystore/RecoveryController;->getRecoveryData([B)Landroid/security/keystore/KeychainSnapshot;
Landroid/security/keystore/RecoveryController;->initRecoveryService(Ljava/lang/String;[B)V
+Landroid/security/keystore/RecoveryController;->recoverKeys(Landroid/security/keystore/RecoverySession;[BLjava/util/List;)Ljava/util/Map;
Landroid/security/keystore/RecoveryController;->setRecoverySecretTypes([I)V
+Landroid/security/keystore/RecoveryController;->setRecoveryStatus(Ljava/lang/String;[Ljava/lang/String;I)V
Landroid/security/keystore/RecoveryController;->setServerParams([B)V
Landroid/security/keystore/RecoveryController;->setSnapshotCreatedPendingIntent(Landroid/app/PendingIntent;)V
+Landroid/security/keystore/RecoveryController;->startRecoverySession([B[B[BLjava/util/List;)Landroid/security/keystore/RecoveryClaim;
+Landroid/security/keystore/WrappedApplicationKey;->getAlias()Ljava/lang/String;
+Landroid/security/keystore/WrappedApplicationKey;->getEncryptedKeyMaterial()[B
+Landroid/security/keystore/WrappedApplicationKey;-><init>(Ljava/lang/String;[B)V
Landroid/security/net/config/RootTrustManager;->checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
Landroid/service/media/IMediaBrowserServiceCallbacks;->onConnectFailed()V
Landroid/service/media/IMediaBrowserServiceCallbacks;->onConnect(Ljava/lang/String;Landroid/media/session/MediaSession$Token;Landroid/os/Bundle;)V
@@ -1727,38 +1564,12 @@
Landroid/service/media/MediaBrowserService$Result;->mFlags:I
Landroid/service/notification/NotificationListenerService;->registerAsSystemService(Landroid/content/Context;Landroid/content/ComponentName;I)V
Landroid/service/notification/NotificationListenerService;->unregisterAsSystemService()V
-Landroid/service/persistentdata/PersistentDataBlockManager;->getFlashLockState()I
-Landroid/service/persistentdata/PersistentDataBlockManager;->getMaximumDataBlockSize()J
-Landroid/service/persistentdata/PersistentDataBlockManager;->read()[B
-Landroid/service/persistentdata/PersistentDataBlockManager;->write([B)I
-Landroid/service/resolver/ResolverRankerService;-><init>()V
-Landroid/service/resolver/ResolverTarget;->getChooserScore()F
-Landroid/service/resolver/ResolverTarget;->getLaunchScore()F
-Landroid/service/resolver/ResolverTarget;->getRecencyScore()F
-Landroid/service/resolver/ResolverTarget;->getSelectProbability()F
-Landroid/service/resolver/ResolverTarget;->getTimeSpentScore()F
-Landroid/service/resolver/ResolverTarget;->setSelectProbability(F)V
-Landroid/service/trust/TrustAgentService;-><init>()V
+Landroid/service/voice/AlwaysOnHotwordDetector$EventPayload;->getCaptureSession()Ljava/lang/Integer;
Landroid/service/voice/VoiceInteractionService;->isKeyphraseAndLocaleSupportedForHotword(Ljava/lang/String;Ljava/util/Locale;)Z
Landroid/service/wallpaper/WallpaperService$Engine;->setFixedSizeAllowed(Z)V
Landroid/speech/tts/TextToSpeech;->getCurrentEngine()Ljava/lang/String;
Landroid/system/Int32Ref;->value:I
Landroid/system/StructTimeval;->fromMillis(J)Landroid/system/StructTimeval;
-Landroid/telecom/AudioState;->getRoute()I
-Landroid/telecom/AudioState;->getSupportedRouteMask()I
-Landroid/telecom/AudioState;->isMuted()Z
-Landroid/telecom/Call;->addListener(Landroid/telecom/Call$Listener;)V
-Landroid/telecom/Call$Listener;-><init>()V
-Landroid/telecom/Call;->removeListener(Landroid/telecom/Call$Listener;)V
-Landroid/telecom/Phone;->addListener(Landroid/telecom/Phone$Listener;)V
-Landroid/telecom/Phone;->getAudioState()Landroid/telecom/AudioState;
-Landroid/telecom/Phone;->getCallAudioState()Landroid/telecom/CallAudioState;
-Landroid/telecom/Phone;->getCalls()Ljava/util/List;
-Landroid/telecom/Phone$Listener;-><init>()V
-Landroid/telecom/Phone;->removeListener(Landroid/telecom/Phone$Listener;)V
-Landroid/telecom/Phone;->setAudioRoute(I)V
-Landroid/telecom/Phone;->setMuted(Z)V
-Landroid/telecom/TelecomManager;->endCall()Z
Landroid/telecom/TelecomManager;->EXTRA_IS_HANDOVER:Ljava/lang/String;
Landroid/telecom/TelecomManager;->getUserSelectedOutgoingPhoneAccount()Landroid/telecom/PhoneAccountHandle;
Landroid/telecom/TelecomManager;->setUserSelectedOutgoingPhoneAccount(Landroid/telecom/PhoneAccountHandle;)V
@@ -1769,6 +1580,7 @@
Landroid/telephony/CellSignalStrengthLte;->mSignalStrength:I
Landroid/telephony/CellSignalStrengthWcdma;->mBitErrorRate:I
Landroid/telephony/CellSignalStrengthWcdma;->mSignalStrength:I
+Landroid/telephony/PhoneNumberUtils;->isLocalEmergencyNumber(Landroid/content/Context;ILjava/lang/String;)Z
Landroid/telephony/PhoneStateListener;->mSubId:Ljava/lang/Integer;
Landroid/telephony/ServiceState;->newFromBundle(Landroid/os/Bundle;)Landroid/telephony/ServiceState;
Landroid/telephony/SignalStrength;->getAsuLevel()I
@@ -1791,24 +1603,20 @@
Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_MODERATE:I
Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_NONE_OR_UNKNOWN:I
Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_POOR:I
-Landroid/telephony/SmsManager;->RESULT_ERROR_FDN_CHECK_FAILURE:I
Landroid/telephony/SmsMessage;->getSubId()I
Landroid/telephony/SmsMessage;->mWrappedSmsMessage:Lcom/android/internal/telephony/SmsMessageBase;
+Landroid/telephony/SubscriptionManager;->getActiveSubscriptionIdList()[I
Landroid/telephony/SubscriptionManager;->getAllSubscriptionInfoCount()I
+Landroid/telephony/SubscriptionManager;->getAllSubscriptionInfoList()Ljava/util/List;
Landroid/telephony/SubscriptionManager;->getDefaultDataSubscriptionInfo()Landroid/telephony/SubscriptionInfo;
Landroid/telephony/SubscriptionManager;->getDefaultSmsPhoneId()I
+Landroid/telephony/SubscriptionManager;->getDefaultVoiceSubscriptionInfo()Landroid/telephony/SubscriptionInfo;
Landroid/telephony/SubscriptionManager;->getPhoneId(I)I
Landroid/telephony/SubscriptionManager;->getSlotIndex(I)I
Landroid/telephony/SubscriptionManager;->getSubId(I)[I
Landroid/telephony/SubscriptionManager;->setDefaultSmsSubId(I)V
-Landroid/telephony/TelephonyManager;->checkCarrierPrivilegesForPackage(Ljava/lang/String;)I
Landroid/telephony/TelephonyManager;->from(Landroid/content/Context;)Landroid/telephony/TelephonyManager;
Landroid/telephony/TelephonyManager;->getCallState(I)I
-Landroid/telephony/TelephonyManager;->getCarrierPackageNamesForIntent(Landroid/content/Intent;)Ljava/util/List;
-Landroid/telephony/TelephonyManager;->getCurrentPhoneType()I
-Landroid/telephony/TelephonyManager;->getCurrentPhoneType(I)I
-Landroid/telephony/TelephonyManager;->getDataEnabled(I)Z
-Landroid/telephony/TelephonyManager;->getDataEnabled()Z
Landroid/telephony/TelephonyManager;->getDataNetworkType(I)I
Landroid/telephony/TelephonyManager;->getDefault()Landroid/telephony/TelephonyManager;
Landroid/telephony/TelephonyManager;->getGroupIdLevel1(I)Ljava/lang/String;
@@ -1839,7 +1647,6 @@
Landroid/telephony/TelephonyManager;->isMultiSimEnabled()Z
Landroid/telephony/TelephonyManager;->isNetworkRoaming(I)Z
Landroid/telephony/TelephonyManager;->isVolteAvailable()Z
-Landroid/telephony/TelephonyManager;->setDataEnabled(IZ)V
Landroid/text/AndroidBidi;->bidi(I[C[B)I
Landroid/text/DynamicLayout;-><init>(Ljava/lang/CharSequence;Ljava/lang/CharSequence;Landroid/text/TextPaint;ILandroid/text/Layout$Alignment;Landroid/text/TextDirectionHeuristic;FFZIIILandroid/text/TextUtils$TruncateAt;I)V
Landroid/text/DynamicLayout;->sStaticLayout:Landroid/text/StaticLayout;
@@ -1903,6 +1710,8 @@
Landroid/text/TextPaint;->setUnderlineText(IF)V
Landroid/transition/ChangeBounds;->BOTTOM_RIGHT_ONLY_PROPERTY:Landroid/util/Property;
Landroid/transition/ChangeBounds;->POSITION_PROPERTY:Landroid/util/Property;
+Landroid/transition/TransitionManager;->sRunningTransitions:Ljava/lang/ThreadLocal;
+Landroid/util/ArrayMap;->append(Ljava/lang/Object;Ljava/lang/Object;)V
Landroid/util/ArrayMap;->mBaseCacheSize:I
Landroid/util/ArrayMap;->mTwiceBaseCacheSize:I
Landroid/util/DisplayMetrics;->noncompatHeightPixels:I
@@ -1918,6 +1727,8 @@
Landroid/util/NtpTrustedTime;->getInstance(Landroid/content/Context;)Landroid/util/NtpTrustedTime;
Landroid/util/NtpTrustedTime;->hasCache()Z
Landroid/util/Pools$SynchronizedPool;->acquire()Ljava/lang/Object;
+Landroid/util/Rational;->mDenominator:I
+Landroid/util/Rational;->mNumerator:I
Landroid/util/Rational;->readObject(Ljava/io/ObjectInputStream;)V
Landroid/util/Singleton;->mInstance:Ljava/lang/Object;
Landroid/util/SparseIntArray;->mKeys:[I
@@ -1930,10 +1741,10 @@
Landroid/view/accessibility/AccessibilityManager;->sInstance:Landroid/view/accessibility/AccessibilityManager;
Landroid/view/accessibility/AccessibilityManager;->sInstanceSync:Ljava/lang/Object;
Landroid/view/accessibility/AccessibilityNodeInfo;->refresh(Landroid/os/Bundle;Z)Z
+Landroid/view/accessibility/AccessibilityRecord;->getSourceNodeId()J
Landroid/view/accessibility/IAccessibilityManager;->getEnabledAccessibilityServiceList(II)Ljava/util/List;
Landroid/view/accessibility/IAccessibilityManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/accessibility/IAccessibilityManager;
Landroid/view/accessibility/IAccessibilityManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/view/ActionMode;->isUiFocusable()Z
Landroid/view/animation/Animation;->mListener:Landroid/view/animation/Animation$AnimationListener;
Landroid/view/autofill/IAutoFillManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/view/Choreographer$CallbackQueue;->addCallbackLocked(JLjava/lang/Object;Ljava/lang/Object;)V
@@ -1942,8 +1753,6 @@
Landroid/view/Choreographer;->mCallbackQueues:[Landroid/view/Choreographer$CallbackQueue;
Landroid/view/Choreographer;->mLastFrameTimeNanos:J
Landroid/view/Choreographer;->mLock:Ljava/lang/Object;
-Landroid/view/Choreographer;->postCallback(ILjava/lang/Runnable;Ljava/lang/Object;)V
-Landroid/view/Choreographer;->removeCallbacks(ILjava/lang/Runnable;Ljava/lang/Object;)V
Landroid/view/Choreographer;->scheduleVsyncLocked()V
Landroid/view/Choreographer;->USE_VSYNC:Z
Landroid/view/ContextThemeWrapper;->getThemeResId()I
@@ -1969,6 +1778,7 @@
Landroid/view/InputDevice;->addMotionRange(IIFFFFF)V
Landroid/view/InputDevice;-><init>(IIILjava/lang/String;IILjava/lang/String;ZIILandroid/view/KeyCharacterMap;ZZZ)V
Landroid/view/InputDevice;->isExternal()Z
+Landroid/view/InputEvent;->getSequenceNumber()I
Landroid/view/InputEventReceiver;->dispatchBatchedInputEventPending()V
Landroid/view/InputEventReceiver;->dispatchInputEvent(ILandroid/view/InputEvent;I)V
Landroid/view/InputEventSender;->dispatchInputEventFinished(IZ)V
@@ -2087,6 +1897,7 @@
Landroid/view/View;->clearAccessibilityFocus()V
Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z
Landroid/view/View;->computeOpaqueFlags()V
+Landroid/view/ViewConfiguration;->getDoubleTapMinTime()I
Landroid/view/ViewConfiguration;->mFadingMarqueeEnabled:Z
Landroid/view/ViewConfiguration;->sHasPermanentMenuKeySet:Z
Landroid/view/ViewConfiguration;->sHasPermanentMenuKey:Z
@@ -2197,89 +2008,28 @@
Landroid/view/WindowManager$LayoutParams;->hideTimeoutMilliseconds:J
Landroid/view/WindowManager$LayoutParams;->needsMenuKey:I
Landroid/view/WindowManager$LayoutParams;->NEEDS_MENU_SET_TRUE:I
-Landroid/view/WindowManager$LayoutParams;->PRIVATE_FLAG_NO_MOVE_ANIMATION:I
-Landroid/view/WindowManager$LayoutParams;->privateFlags:I
Landroid/view/WindowManager$LayoutParams;->userActivityTimeout:J
Landroid/view/Window;->mAppName:Ljava/lang/String;
Landroid/view/Window;->mAppToken:Landroid/os/IBinder;
Landroid/view/Window;->mHardwareAccelerated:Z
-Landroid/webkit/FindActionModeCallback;->findAll()V
-Landroid/webkit/FindActionModeCallback;-><init>(Landroid/content/Context;)V
-Landroid/webkit/FindActionModeCallback;->setText(Ljava/lang/String;)V
-Landroid/webkit/FindActionModeCallback;->setWebView(Landroid/webkit/WebView;)V
-Landroid/webkit/FindActionModeCallback;->showSoftInput()V
-Landroid/webkit/GeolocationPermissions;-><init>()V
-Landroid/webkit/HttpAuthHandler;-><init>()V
Landroid/webkit/IWebViewUpdateService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/webkit/JsDialogHelper;-><init>(Landroid/webkit/JsPromptResult;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-Landroid/webkit/JsDialogHelper;->showDialog(Landroid/content/Context;)V
-Landroid/webkit/JsPromptResult;->getStringResult()Ljava/lang/String;
-Landroid/webkit/JsPromptResult;-><init>(Landroid/webkit/JsResult$ResultReceiver;)V
-Landroid/webkit/SslErrorHandler;-><init>()V
-Landroid/webkit/TokenBindingService;-><init>()V
-Landroid/webkit/TokenBindingService$TokenBindingKey;-><init>()V
-Landroid/webkit/WebChromeClient;->openFileChooser(Landroid/webkit/ValueCallback;Ljava/lang/String;Ljava/lang/String;)V
-Landroid/webkit/WebMessagePort;-><init>()V
-Landroid/webkit/WebResourceError;-><init>()V
-Landroid/webkit/WebResourceResponse;-><init>(ZLjava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/util/Map;Ljava/io/InputStream;)V
Landroid/webkit/WebResourceResponse;->mImmutable:Z
-Landroid/webkit/WebSettings;->getAcceptThirdPartyCookies()Z
-Landroid/webkit/WebSettings;->setAcceptThirdPartyCookies(Z)V
-Landroid/webkit/WebSettings;->setNavDump(Z)V
-Landroid/webkit/WebSettings;->setPluginsEnabled(Z)V
-Landroid/webkit/WebStorage;-><init>()V
-Landroid/webkit/WebStorage$Origin;-><init>(Ljava/lang/String;JJ)V
Landroid/webkit/WebSyncManager;->mHandler:Landroid/os/Handler;
Landroid/webkit/WebView;->debugDump()V
-Landroid/webkit/WebViewDelegate;->addWebViewAssetPath(Landroid/content/Context;)V
-Landroid/webkit/WebViewDelegate;->callDrawGlFunction(Landroid/graphics/Canvas;JLjava/lang/Runnable;)V
-Landroid/webkit/WebViewDelegate;->callDrawGlFunction(Landroid/graphics/Canvas;J)V
-Landroid/webkit/WebViewDelegate;->canInvokeDrawGlFunctor(Landroid/view/View;)Z
-Landroid/webkit/WebViewDelegate;->detachDrawGlFunctor(Landroid/view/View;J)V
-Landroid/webkit/WebViewDelegate;->getApplication()Landroid/app/Application;
-Landroid/webkit/WebViewDelegate;->getDataDirectorySuffix()Ljava/lang/String;
-Landroid/webkit/WebViewDelegate;->getErrorString(Landroid/content/Context;I)Ljava/lang/String;
-Landroid/webkit/WebViewDelegate;->getPackageId(Landroid/content/res/Resources;Ljava/lang/String;)I
-Landroid/webkit/WebViewDelegate;->invokeDrawGlFunctor(Landroid/view/View;JZ)V
-Landroid/webkit/WebViewDelegate;->isMultiProcessEnabled()Z
-Landroid/webkit/WebViewDelegate;->isTraceTagEnabled()Z
-Landroid/webkit/WebViewDelegate;->setOnTraceEnabledChangeListener(Landroid/webkit/WebViewDelegate$OnTraceEnabledChangeListener;)V
Landroid/webkit/WebView;->disablePlatformNotifications()V
Landroid/webkit/WebView;->emulateShiftHeld()V
Landroid/webkit/WebView;->enablePlatformNotifications()V
-Landroid/webkit/WebViewFactory;->getLoadedPackageInfo()Landroid/content/pm/PackageInfo;
Landroid/webkit/WebViewFactory;->getProvider()Landroid/webkit/WebViewFactoryProvider;
Landroid/webkit/WebViewFactory;->getWebViewContextAndSetProvider()Landroid/content/Context;
-Landroid/webkit/WebViewFactory;->loadWebViewNativeLibraryFromPackage(Ljava/lang/String;Ljava/lang/ClassLoader;)I
-Landroid/webkit/WebViewFactoryProvider;->getStatics()Landroid/webkit/WebViewFactoryProvider$Statics;
-Landroid/webkit/WebViewFactoryProvider$Statics;->getDefaultUserAgent(Landroid/content/Context;)Ljava/lang/String;
Landroid/webkit/WebViewFactory;->sPackageInfo:Landroid/content/pm/PackageInfo;
Landroid/webkit/WebViewFactory;->sProviderInstance:Landroid/webkit/WebViewFactoryProvider;
Landroid/webkit/WebView;->getVisibleTitleHeight()I
-Landroid/webkit/WebView;->getWebViewProvider()Landroid/webkit/WebViewProvider;
-Landroid/webkit/WebView$HitTestResult;-><init>()V
-Landroid/webkit/WebView$HitTestResult;->setExtra(Ljava/lang/String;)V
-Landroid/webkit/WebView$HitTestResult;->setType(I)V
Landroid/webkit/WebView;->isPaused()Z
Landroid/webkit/WebView;->mProvider:Landroid/webkit/WebViewProvider;
Landroid/webkit/WebView;->notifyFindDialogDismissed()V
-Landroid/webkit/WebView$PrivateAccess;->overScrollBy(IIIIIIIIZ)V
-Landroid/webkit/WebView$PrivateAccess;->setMeasuredDimension(II)V
-Landroid/webkit/WebView$PrivateAccess;->super_dispatchKeyEvent(Landroid/view/KeyEvent;)Z
-Landroid/webkit/WebView$PrivateAccess;->super_getScrollBarStyle()I
-Landroid/webkit/WebView$PrivateAccess;->super_onDrawVerticalScrollBar(Landroid/graphics/Canvas;Landroid/graphics/drawable/Drawable;IIII)V
-Landroid/webkit/WebView$PrivateAccess;->super_onGenericMotionEvent(Landroid/view/MotionEvent;)Z
-Landroid/webkit/WebView$PrivateAccess;->super_performAccessibilityAction(ILandroid/os/Bundle;)Z
-Landroid/webkit/WebView$PrivateAccess;->super_performLongClick()Z
-Landroid/webkit/WebView$PrivateAccess;->super_requestFocus(ILandroid/graphics/Rect;)Z
-Landroid/webkit/WebView$PrivateAccess;->super_scrollTo(II)V
-Landroid/webkit/WebView$PrivateAccess;->super_setFrame(IIII)Z
-Landroid/webkit/WebView$PrivateAccess;->super_setLayoutParams(Landroid/view/ViewGroup$LayoutParams;)V
-Landroid/webkit/WebView$PrivateAccess;->super_startActivityForResult(Landroid/content/Intent;I)V
Landroid/webkit/WebView;->restorePicture(Landroid/os/Bundle;Ljava/io/File;)Z
Landroid/webkit/WebView;->savePicture(Landroid/os/Bundle;Ljava/io/File;)Z
Landroid/webkit/WebView;->sEnforceThreadChecking:Z
-Landroid/webkit/WebViewUpdateService;->getCurrentWebViewPackageName()Ljava/lang/String;
Landroid/widget/AbsListView$FlingRunnable;->endFling()V
Landroid/widget/AbsListView$FlingRunnable;->mScroller:Landroid/widget/OverScroller;
Landroid/widget/AbsListView$FlingRunnable;->start(I)V
@@ -2476,6 +2226,74 @@
Landroid/widget/VideoView;->mUri:Landroid/net/Uri;
Landroid/widget/VideoView;->mVideoHeight:I
Landroid/widget/VideoView;->mVideoWidth:I
+Lcom/android/ims/internal/uce/common/CapInfo;-><init>()V
+Lcom/android/ims/internal/uce/common/CapInfo;->setCapTimestamp(J)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setCdViaPresenceSupported(Z)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setExts([Ljava/lang/String;)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setFtHttpSupported(Z)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setFtSnFSupported(Z)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setFtSupported(Z)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setFtThumbSupported(Z)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setFullSnFGroupChatSupported(Z)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setGeoPullFtSupported(Z)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setGeoPullSupported(Z)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setGeoPushSupported(Z)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setImSupported(Z)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setIpVideoSupported(Z)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setIpVoiceSupported(Z)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setIsSupported(Z)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setRcsIpVideoCallSupported(Z)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setRcsIpVideoOnlyCallSupported(Z)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setRcsIpVoiceCallSupported(Z)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setSmSupported(Z)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setSpSupported(Z)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setVsDuringCSSupported(Z)V
+Lcom/android/ims/internal/uce/common/CapInfo;->setVsSupported(Z)V
+Lcom/android/ims/internal/uce/common/StatusCode;-><init>()V
+Lcom/android/ims/internal/uce/common/StatusCode;->setStatusCode(I)V
+Lcom/android/ims/internal/uce/common/UceLong;->getUceLong()J
+Lcom/android/ims/internal/uce/common/UceLong;->setUceLong(J)V
+Lcom/android/ims/internal/uce/presence/PresCmdId;-><init>()V
+Lcom/android/ims/internal/uce/presence/PresCmdId;->setCmdId(I)V
+Lcom/android/ims/internal/uce/presence/PresCmdStatus;-><init>()V
+Lcom/android/ims/internal/uce/presence/PresCmdStatus;->setCmdId(Lcom/android/ims/internal/uce/presence/PresCmdId;)V
+Lcom/android/ims/internal/uce/presence/PresCmdStatus;->setRequestId(I)V
+Lcom/android/ims/internal/uce/presence/PresCmdStatus;->setStatus(Lcom/android/ims/internal/uce/common/StatusCode;)V
+Lcom/android/ims/internal/uce/presence/PresCmdStatus;->setUserData(I)V
+Lcom/android/ims/internal/uce/presence/PresPublishTriggerType;-><init>()V
+Lcom/android/ims/internal/uce/presence/PresPublishTriggerType;->setPublishTrigeerType(I)V
+Lcom/android/ims/internal/uce/presence/PresResInfo;-><init>()V
+Lcom/android/ims/internal/uce/presence/PresResInfo;->setDisplayName(Ljava/lang/String;)V
+Lcom/android/ims/internal/uce/presence/PresResInfo;->setInstanceInfo(Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;)V
+Lcom/android/ims/internal/uce/presence/PresResInfo;->setResUri(Ljava/lang/String;)V
+Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;-><init>()V
+Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;->setPresentityUri(Ljava/lang/String;)V
+Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;->setReason(Ljava/lang/String;)V
+Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;->setResId(Ljava/lang/String;)V
+Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;->setResInstanceState(I)V
+Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;->setTupleInfo([Lcom/android/ims/internal/uce/presence/PresTupleInfo;)V
+Lcom/android/ims/internal/uce/presence/PresRlmiInfo;-><init>()V
+Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setFullState(Z)V
+Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setListName(Ljava/lang/String;)V
+Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setPresSubscriptionState(Lcom/android/ims/internal/uce/presence/PresSubscriptionState;)V
+Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setRequestId(I)V
+Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setSubscriptionExpireTime(I)V
+Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setSubscriptionTerminatedReason(Ljava/lang/String;)V
+Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setUri(Ljava/lang/String;)V
+Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setVersion(I)V
+Lcom/android/ims/internal/uce/presence/PresSipResponse;-><init>()V
+Lcom/android/ims/internal/uce/presence/PresSipResponse;->setCmdId(Lcom/android/ims/internal/uce/presence/PresCmdId;)V
+Lcom/android/ims/internal/uce/presence/PresSipResponse;->setReasonPhrase(Ljava/lang/String;)V
+Lcom/android/ims/internal/uce/presence/PresSipResponse;->setRequestId(I)V
+Lcom/android/ims/internal/uce/presence/PresSipResponse;->setRetryAfter(I)V
+Lcom/android/ims/internal/uce/presence/PresSipResponse;->setSipResponseCode(I)V
+Lcom/android/ims/internal/uce/presence/PresSubscriptionState;-><init>()V
+Lcom/android/ims/internal/uce/presence/PresSubscriptionState;->setPresSubscriptionState(I)V
+Lcom/android/ims/internal/uce/presence/PresTupleInfo;-><init>()V
+Lcom/android/ims/internal/uce/presence/PresTupleInfo;->setContactUri(Ljava/lang/String;)V
+Lcom/android/ims/internal/uce/presence/PresTupleInfo;->setFeatureTag(Ljava/lang/String;)V
+Lcom/android/ims/internal/uce/presence/PresTupleInfo;->setTimestamp(Ljava/lang/String;)V
+Lcom/android/internal/app/AlertController$RecycleListView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
Lcom/android/internal/app/IAppOpsService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IAppOpsService;
Lcom/android/internal/app/IAppOpsService$Stub$Proxy;->checkOperation(IILjava/lang/String;)I
Lcom/android/internal/app/IAppOpsService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -2484,6 +2302,7 @@
Lcom/android/internal/app/IBatteryStats$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Lcom/android/internal/app/IVoiceInteractionManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IVoiceInteractionManagerService;
Lcom/android/internal/app/IVoiceInteractionManagerService$Stub$Proxy;->showSessionFromSession(Landroid/os/IBinder;Landroid/os/Bundle;I)Z
+Lcom/android/internal/location/ILocationProvider$Stub;-><init>()V
Lcom/android/internal/os/BatterySipper;->add(Lcom/android/internal/os/BatterySipper;)V
Lcom/android/internal/os/BatterySipper;->drainType:Lcom/android/internal/os/BatterySipper$DrainType;
Lcom/android/internal/os/BatterySipper;->getUid()I
@@ -2679,6 +2498,7 @@
Lcom/android/internal/telephony/ITelephony$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_getDeviceId:I
Lcom/android/internal/textservice/ITextServicesManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Lcom/android/internal/util/FastPrintWriter;-><init>(Ljava/io/OutputStream;)V
Lcom/android/internal/util/XmlUtils;->readMapXml(Ljava/io/InputStream;)Ljava/util/HashMap;
Lcom/android/internal/view/IInputMethodManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethodManager;
Lcom/android/internal/view/IInputMethodManager$Stub$Proxy;->getEnabledInputMethodList()Ljava/util/List;
@@ -2694,7 +2514,13 @@
Lcom/android/okhttp/ConnectionPool;->keepAliveDurationNs:J
Lcom/android/okhttp/ConnectionPool;->maxIdleConnections:I
Lcom/android/okhttp/ConnectionPool;->systemDefault:Lcom/android/okhttp/ConnectionPool;
+Lcom/android/okhttp/HttpUrl;->encodedPath()Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->query()Ljava/lang/String;
Lcom/android/okhttp/internal/http/HttpEngine;->httpStream:Lcom/android/okhttp/internal/http/HttpStream;
+Lcom/android/okhttp/internal/http/HttpEngine;->networkRequest:Lcom/android/okhttp/Request;
+Lcom/android/okhttp/internal/http/HttpEngine;->networkRequest(Lcom/android/okhttp/Request;)Lcom/android/okhttp/Request;
+Lcom/android/okhttp/internal/http/HttpEngine;->priorResponse:Lcom/android/okhttp/Response;
+Lcom/android/okhttp/internal/http/HttpEngine;->userResponse:Lcom/android/okhttp/Response;
Lcom/android/okhttp/OkHttpClient;->connectionPool:Lcom/android/okhttp/ConnectionPool;
Lcom/android/okhttp/OkHttpClient;->DEFAULT_PROTOCOLS:Ljava/util/List;
Lcom/android/okhttp/OkHttpClient;->dns:Lcom/android/okhttp/Dns;
@@ -2702,6 +2528,14 @@
Lcom/android/okhttp/OkHttpClient;->setRetryOnConnectionFailure(Z)V
Lcom/android/okhttp/okio/ByteString;->readObject(Ljava/io/ObjectInputStream;)V
Lcom/android/okhttp/okio/ByteString;->writeObject(Ljava/io/ObjectOutputStream;)V
+Lcom/android/okhttp/Request;->headers:Lcom/android/okhttp/Headers;
+Lcom/android/okhttp/Request;->method:Ljava/lang/String;
+Lcom/android/okhttp/Request;->url:Lcom/android/okhttp/HttpUrl;
+Lcom/android/okhttp/Response;->code:I
+Lcom/android/okhttp/Response;->headers:Lcom/android/okhttp/Headers;
+Lcom/android/okhttp/Response;->message:Ljava/lang/String;
+Lcom/android/okhttp/Response;->networkResponse:Lcom/android/okhttp/Response;
+Lcom/android/okhttp/Response;->protocol:Lcom/android/okhttp/Protocol;
Lcom/android/org/conscrypt/AbstractConscryptSocket;->getAlpnSelectedProtocol()[B
Lcom/android/org/conscrypt/AbstractConscryptSocket;->getApplicationProtocol()Ljava/lang/String;
Lcom/android/org/conscrypt/AbstractConscryptSocket;->getApplicationProtocols()[Ljava/lang/String;
@@ -2744,6 +2578,7 @@
Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setUseSessionTickets(Z)V
Lcom/android/org/conscrypt/OpenSSLX509Certificate;->mContext:J
Lcom/android/org/conscrypt/TrustManagerImpl;-><init>(Ljava/security/KeyStore;)V
+Ldalvik/system/BaseDexClassLoader;->addDexPath(Ljava/lang/String;)V
Ldalvik/system/BaseDexClassLoader;->getLdLibraryPath()Ljava/lang/String;
Ldalvik/system/BaseDexClassLoader;->pathList:Ldalvik/system/DexPathList;
Ldalvik/system/BlockGuard;->getThreadPolicy()Ldalvik/system/BlockGuard$Policy;
@@ -2753,6 +2588,7 @@
Ldalvik/system/CloseGuard;->open(Ljava/lang/String;)V
Ldalvik/system/CloseGuard;->warnIfOpen()V
Ldalvik/system/DexFile;->getClassNameList(Ljava/lang/Object;)[Ljava/lang/String;
+Ldalvik/system/DexFile;->isBackedByOatFile()Z
Ldalvik/system/DexFile;->loadClassBinaryName(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/util/List;)Ljava/lang/Class;
Ldalvik/system/DexFile;->mCookie:Ljava/lang/Object;
Ldalvik/system/DexFile;->mFileName:Ljava/lang/String;
@@ -2873,6 +2709,7 @@
Ljava/lang/Throwable;->backtrace:Ljava/lang/Object;
Ljava/lang/Throwable;->cause:Ljava/lang/Throwable;
Ljava/lang/Throwable;->detailMessage:Ljava/lang/String;
+Ljava/lang/Throwable;->nativeFillInStackTrace()Ljava/lang/Object;
Ljava/lang/Throwable;->readObject(Ljava/io/ObjectInputStream;)V
Ljava/lang/Throwable;->stackTrace:[Ljava/lang/StackTraceElement;
Ljava/lang/Throwable;->suppressedExceptions:Ljava/util/List;
@@ -2942,6 +2779,7 @@
Ljava/security/spec/ECParameterSpec;->setCurveName(Ljava/lang/String;)V
Ljava/security/Timestamp;->readObject(Ljava/io/ObjectInputStream;)V
Ljava/text/ChoiceFormat;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/text/DateFormat;->is24Hour:Ljava/lang/Boolean;
Ljava/text/DateFormatSymbols;->readObject(Ljava/io/ObjectInputStream;)V
Ljava/text/DateFormatSymbols;->writeObject(Ljava/io/ObjectOutputStream;)V
Ljava/text/DecimalFormat;->readObject(Ljava/io/ObjectInputStream;)V
@@ -2964,11 +2802,13 @@
Ljava/time/chrono/ThaiBuddhistChronology;->readObject(Ljava/io/ObjectInputStream;)V
Ljava/time/chrono/ThaiBuddhistDate;->readObject(Ljava/io/ObjectInputStream;)V
Ljava/time/Duration;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/Duration;->toSeconds()Ljava/math/BigDecimal;
Ljava/time/Instant;->readObject(Ljava/io/ObjectInputStream;)V
Ljava/time/LocalDate;->readObject(Ljava/io/ObjectInputStream;)V
Ljava/time/LocalDateTime;->readObject(Ljava/io/ObjectInputStream;)V
Ljava/time/LocalTime;->readObject(Ljava/io/ObjectInputStream;)V
Ljava/time/MonthDay;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/OffsetDateTime;-><init>(Ljava/time/LocalDateTime;Ljava/time/ZoneOffset;)V
Ljava/time/OffsetDateTime;->readObject(Ljava/io/ObjectInputStream;)V
Ljava/time/OffsetTime;->readObject(Ljava/io/ObjectInputStream;)V
Ljava/time/Period;->readObject(Ljava/io/ObjectInputStream;)V
@@ -3075,6 +2915,7 @@
Ljava/util/PriorityQueue;->readObject(Ljava/io/ObjectInputStream;)V
Ljava/util/PriorityQueue;->writeObject(Ljava/io/ObjectOutputStream;)V
Ljava/util/Random;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/Random;->seedUniquifier()J
Ljava/util/Random;->writeObject(Ljava/io/ObjectOutputStream;)V
Ljava/util/regex/Matcher;->appendPos:I
Ljava/util/regex/Pattern;->readObject(Ljava/io/ObjectInputStream;)V
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 99c5d2b..a1a10a5 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -124,6 +124,7 @@
import android.widget.Toolbar;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.app.ToolbarActionBar;
import com.android.internal.app.WindowDecorActionBar;
@@ -995,9 +996,9 @@
* cursors for data being displayed, etc.
*
* <p>You can call {@link #finish} from within this function, in
- * which case onDestroy() will be immediately called without any of the rest
- * of the activity lifecycle ({@link #onStart}, {@link #onResume},
- * {@link #onPause}, etc) executing.
+ * which case onDestroy() will be immediately called after {@link #onCreate} without any of the
+ * rest of the activity lifecycle ({@link #onStart}, {@link #onResume}, {@link #onPause}, etc)
+ * executing.
*
* <p><em>Derived classes must call through to the super class's
* implementation of this method. If they do not, an exception will be
@@ -7110,6 +7111,12 @@
return mParent != null ? mParent.getActivityToken() : mToken;
}
+ /** @hide */
+ @VisibleForTesting
+ public final ActivityThread getActivityThread() {
+ return mMainThread;
+ }
+
final void performCreate(Bundle icicle) {
performCreate(icicle, null);
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 2d73ce0..a18ba71 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2101,15 +2101,17 @@
private final int mOrientation;
private final Rect mContentInsets;
private final boolean mReducedResolution;
+ private final boolean mIsRealSnapshot;
private final float mScale;
public TaskSnapshot(GraphicBuffer snapshot, int orientation, Rect contentInsets,
- boolean reducedResolution, float scale) {
+ boolean reducedResolution, float scale, boolean isRealSnapshot) {
mSnapshot = snapshot;
mOrientation = orientation;
mContentInsets = new Rect(contentInsets);
mReducedResolution = reducedResolution;
mScale = scale;
+ mIsRealSnapshot = isRealSnapshot;
}
private TaskSnapshot(Parcel source) {
@@ -2118,6 +2120,7 @@
mContentInsets = source.readParcelable(null /* classLoader */);
mReducedResolution = source.readBoolean();
mScale = source.readFloat();
+ mIsRealSnapshot = source.readBoolean();
}
/**
@@ -2150,6 +2153,14 @@
}
/**
+ * @return Whether or not the snapshot is a real snapshot or an app-theme generated snapshot
+ * due to the task having a secure window or having previews disabled.
+ */
+ public boolean isRealSnapshot() {
+ return mIsRealSnapshot;
+ }
+
+ /**
* @return The scale this snapshot was taken in.
*/
public float getScale() {
@@ -2168,13 +2179,15 @@
dest.writeParcelable(mContentInsets, 0);
dest.writeBoolean(mReducedResolution);
dest.writeFloat(mScale);
+ dest.writeBoolean(mIsRealSnapshot);
}
@Override
public String toString() {
return "TaskSnapshot{mSnapshot=" + mSnapshot + " mOrientation=" + mOrientation
+ " mContentInsets=" + mContentInsets.toShortString()
- + " mReducedResolution=" + mReducedResolution + " mScale=" + mScale;
+ + " mReducedResolution=" + mReducedResolution + " mScale=" + mScale
+ + " mIsRealSnapshot=" + mIsRealSnapshot;
}
public static final Creator<TaskSnapshot> CREATOR = new Creator<TaskSnapshot>() {
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index c78255f..cab6744 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -27,6 +27,7 @@
import android.os.SystemClock;
import android.service.voice.IVoiceInteractionSession;
import android.util.SparseIntArray;
+import android.view.RemoteAnimationAdapter;
import com.android.internal.app.IVoiceInteractor;
@@ -264,6 +265,17 @@
public abstract void setHasOverlayUi(int pid, boolean hasOverlayUi);
/**
+ * Sets if the given pid is currently running a remote animation, which is taken a signal for
+ * determining oom adjustment and scheduling behavior.
+ *
+ * @param pid The pid we are setting overlay UI for.
+ * @param runningRemoteAnimation True if the process is running a remote animation, false
+ * otherwise.
+ * @see RemoteAnimationAdapter
+ */
+ public abstract void setRunningRemoteAnimation(int pid, boolean runningRemoteAnimation);
+
+ /**
* Called after the network policy rules are updated by
* {@link com.android.server.net.NetworkPolicyManagerService} for a specific {@param uid} and
* {@param procStateSeq}.
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 379944e..afcd515 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3722,16 +3722,27 @@
//Slog.i(TAG, "Running services: " + mServices);
}
- ActivityClientRecord performResumeActivity(IBinder token, boolean clearHide, String reason) {
+ ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest,
+ String reason) {
ActivityClientRecord r = mActivities.get(token);
if (localLOGV) Slog.v(TAG, "Performing resume of " + r
+ " finished=" + r.activity.mFinished);
if (r != null && !r.activity.mFinished) {
if (r.getLifecycleState() == ON_RESUME) {
- throw new IllegalStateException(
- "Trying to resume activity which is already resumed");
+ if (!finalStateRequest) {
+ final RuntimeException e = new IllegalStateException(
+ "Trying to resume activity which is already resumed");
+ Slog.e(TAG, e.getMessage(), e);
+ Slog.e(TAG, r.getStateString());
+ // TODO(lifecycler): A double resume request is possible when an activity
+ // receives two consequent transactions with relaunch requests and "resumed"
+ // final state requests and the second relaunch is omitted. We still try to
+ // handle two resume requests for the final state. For cases other than this
+ // one, we don't expect it to happen.
+ }
+ return null;
}
- if (clearHide) {
+ if (finalStateRequest) {
r.hideForNow = false;
r.activity.mStartedActivity = false;
}
@@ -3782,7 +3793,7 @@
}
@Override
- public void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
+ public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
String reason) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
@@ -3790,7 +3801,7 @@
mSomeActivitiesChanged = true;
// TODO Push resumeArgs into the activity for consideration
- final ActivityClientRecord r = performResumeActivity(token, clearHide, reason);
+ final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
if (r != null) {
final Activity a = r.activity;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 05a9861..14edd31 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1609,6 +1609,7 @@
* @param mode The app op mode to set.
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setUidMode(int code, int uid, int mode) {
try {
mService.setUidMode(code, uid, mode);
@@ -1628,7 +1629,7 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS)
+ @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setUidMode(String appOp, int uid, int mode) {
try {
mService.setUidMode(AppOpsManager.strOpToOp(appOp), uid, mode);
@@ -1660,6 +1661,7 @@
/** @hide */
@TestApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setMode(int code, int uid, String packageName, int mode) {
try {
mService.setMode(code, uid, packageName, mode);
@@ -1669,6 +1671,27 @@
}
/**
+ * Change the operating mode for the given op in the given app package. You must pass
+ * in both the uid and name of the application whose mode is being modified; if these
+ * do not match, the modification will not be applied.
+ *
+ * @param op The operation to modify. One of the OPSTR_* constants.
+ * @param uid The user id of the application whose mode will be changed.
+ * @param packageName The name of the application package name whose mode will
+ * be changed.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
+ public void setMode(String op, int uid, String packageName, int mode) {
+ try {
+ mService.setMode(strOpToOp(op), uid, packageName, mode);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Set a non-persisted restriction on an audio operation at a stream-level.
* Restrictions are temporary additional constraints imposed on top of the persisted rules
* defined by {@link #setMode}.
@@ -1679,6 +1702,7 @@
* @param exceptionPackages Optional list of packages to exclude from the restriction.
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setRestriction(int code, @AttributeUsage int usage, int mode,
String[] exceptionPackages) {
try {
@@ -1690,6 +1714,7 @@
}
/** @hide */
+ @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void resetAllModes() {
try {
mService.resetAllModes(mContext.getUserId(), null);
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
index 81cbbca..41eeb9a 100644
--- a/core/java/android/app/Application.java
+++ b/core/java/android/app/Application.java
@@ -191,6 +191,16 @@
}
}
+ /**
+ * Returns the name of the current process. A package's default process name
+ * is the same as its package name. Non-default processes will look like
+ * "$PACKAGE_NAME:$NAME", where $NAME corresponds to an android:process
+ * attribute within AndroidManifest.xml.
+ */
+ public static String getProcessName() {
+ return ActivityThread.currentProcessName();
+ }
+
// ------------------ Internal API ------------------
/**
@@ -333,4 +343,4 @@
}
return null;
}
-}
\ No newline at end of file
+}
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index 6bc66ec..206495d 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -67,9 +67,16 @@
public abstract void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
int configChanges, PendingTransactionActions pendingActions, String reason);
- /** Resume the activity. */
- public abstract void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
- String reason);
+ /**
+ * Resume the activity.
+ * @param token Target activity token.
+ * @param finalStateRequest Flag indicating if this call is handling final lifecycle state
+ * request for a transaction.
+ * @param isForward Flag indicating if next transition is forward.
+ * @param reason Reason for performing this operation.
+ */
+ public abstract void handleResumeActivity(IBinder token, boolean finalStateRequest,
+ boolean isForward, String reason);
/** Stop the activity. */
public abstract void handleStopActivity(IBinder token, boolean show, int configChanges,
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index b207d57..46d1264 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1072,20 +1072,77 @@
* @hide
*/
public static final int SUPPRESSED_EFFECTS_UNSET = -1;
+
/**
* Whether notifications suppressed by DND should not interrupt visually (e.g. with
* notification lights or by turning the screen on) when the screen is off.
+ *
+ * @deprecated use {@link #SUPPRESSED_EFFECT_FULL_SCREEN_INTENT} and
+ * {@link #SUPPRESSED_EFFECT_AMBIENT} and {@link #SUPPRESSED_EFFECT_LIGHTS} individually.
*/
+ @Deprecated
public static final int SUPPRESSED_EFFECT_SCREEN_OFF = 1 << 0;
/**
* Whether notifications suppressed by DND should not interrupt visually when the screen
* is on (e.g. by peeking onto the screen).
+ *
+ * @deprecated use {@link #SUPPRESSED_EFFECT_PEEK}.
*/
+ @Deprecated
public static final int SUPPRESSED_EFFECT_SCREEN_ON = 1 << 1;
+ /**
+ * Whether {@link Notification#fullScreenIntent full screen intents} from
+ * notifications intercepted by DND are blocked.
+ */
+ public static final int SUPPRESSED_EFFECT_FULL_SCREEN_INTENT = 1 << 2;
+
+ /**
+ * Whether {@link NotificationChannel#shouldShowLights() notification lights} from
+ * notifications intercepted by DND are blocked.
+ */
+ public static final int SUPPRESSED_EFFECT_LIGHTS = 1 << 3;
+
+ /**
+ * Whether notifications intercepted by DND are prevented from peeking.
+ */
+ public static final int SUPPRESSED_EFFECT_PEEK = 1 << 4;
+
+ /**
+ * Whether notifications intercepted by DND are prevented from appearing in the status bar,
+ * on devices that support status bars.
+ */
+ public static final int SUPPRESSED_EFFECT_STATUS_BAR = 1 << 5;
+
+ /**
+ * Whether {@link NotificationChannel#canShowBadge() badges} from
+ * notifications intercepted by DND are blocked on devices that support badging.
+ */
+ public static final int SUPPRESSED_EFFECT_BADGE = 1 << 6;
+
+ /**
+ * Whether notification intercepted by DND are prevented from appearing on ambient displays
+ * on devices that support ambient display.
+ */
+ public static final int SUPPRESSED_EFFECT_AMBIENT = 1 << 7;
+
+ /**
+ * Whether notification intercepted by DND are prevented from appearing in notification
+ * list views like the notification shade or lockscreen on devices that support those
+ * views.
+ */
+ public static final int SUPPRESSED_EFFECT_NOTIFICATION_LIST = 1 << 8;
+
private static final int[] ALL_SUPPRESSED_EFFECTS = {
SUPPRESSED_EFFECT_SCREEN_OFF,
SUPPRESSED_EFFECT_SCREEN_ON,
+ SUPPRESSED_EFFECT_FULL_SCREEN_INTENT,
+ SUPPRESSED_EFFECT_LIGHTS,
+ SUPPRESSED_EFFECT_PEEK,
+ SUPPRESSED_EFFECT_STATUS_BAR,
+ SUPPRESSED_EFFECT_BADGE,
+ SUPPRESSED_EFFECT_AMBIENT,
+ SUPPRESSED_EFFECT_NOTIFICATION_LIST
};
/**
@@ -1097,6 +1154,12 @@
/**
* Constructs a policy for Do Not Disturb priority mode behavior.
*
+ * <p>
+ * Apps that target API levels below {@link Build.VERSION_CODES#P} cannot
+ * change user-designated values to allow or disallow
+ * {@link Policy#PRIORITY_CATEGORY_ALARMS}, {@link Policy#PRIORITY_CATEGORY_SYSTEM}, and
+ * {@link Policy#PRIORITY_CATEGORY_MEDIA} from bypassing dnd.
+ *
* @param priorityCategories bitmask of categories of notifications that can bypass DND.
* @param priorityCallSenders which callers can bypass DND.
* @param priorityMessageSenders which message senders can bypass DND.
@@ -1109,6 +1172,26 @@
/**
* Constructs a policy for Do Not Disturb priority mode behavior.
*
+ * <p>
+ * Apps that target API levels below {@link Build.VERSION_CODES#P} cannot
+ * change user-designated values to allow or disallow
+ * {@link Policy#PRIORITY_CATEGORY_ALARMS}, {@link Policy#PRIORITY_CATEGORY_SYSTEM}, and
+ * {@link Policy#PRIORITY_CATEGORY_MEDIA} from bypassing dnd.
+ * <p>
+ * Additionally, apps that target API levels below {@link Build.VERSION_CODES#P} can
+ * only modify the {@link #SUPPRESSED_EFFECT_SCREEN_ON} and
+ * {@link #SUPPRESSED_EFFECT_SCREEN_OFF} bits of the suppressed visual effects field.
+ * All other suppressed effects will be ignored and reconstituted from the screen on
+ * and screen off values.
+ * <p>
+ * Apps that target {@link Build.VERSION_CODES#P} or above can set any
+ * suppressed visual effects. However, if any suppressed effects >
+ * {@link #SUPPRESSED_EFFECT_SCREEN_ON} are set, {@link #SUPPRESSED_EFFECT_SCREEN_ON}
+ * and {@link #SUPPRESSED_EFFECT_SCREEN_OFF} will be ignored and reconstituted from
+ * the more specific suppressed visual effect bits. Apps should migrate to targeting
+ * specific effects instead of the deprecated {@link #SUPPRESSED_EFFECT_SCREEN_ON} and
+ * {@link #SUPPRESSED_EFFECT_SCREEN_OFF} effects.
+ *
* @param priorityCategories bitmask of categories of notifications that can bypass DND.
* @param priorityCallSenders which callers can bypass DND.
* @param priorityMessageSenders which message senders can bypass DND.
@@ -1190,6 +1273,30 @@
}
}
+ /**
+ * @hide
+ */
+ public static int getAllSuppressedVisualEffects() {
+ int effects = 0;
+ for (int i = 0; i < ALL_SUPPRESSED_EFFECTS.length; i++) {
+ effects |= ALL_SUPPRESSED_EFFECTS[i];
+ }
+ return effects;
+ }
+
+ /**
+ * @hide
+ */
+ public static boolean areAllVisualEffectsSuppressed(int effects) {
+ for (int i = 0; i < ALL_SUPPRESSED_EFFECTS.length; i++) {
+ final int effect = ALL_SUPPRESSED_EFFECTS[i];
+ if ((effects & effect) == 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
public static String suppressedEffectsToString(int effects) {
if (effects <= 0) return "";
final StringBuilder sb = new StringBuilder();
@@ -1228,9 +1335,26 @@
private static String effectToString(int effect) {
switch (effect) {
- case SUPPRESSED_EFFECT_SCREEN_OFF: return "SUPPRESSED_EFFECT_SCREEN_OFF";
- case SUPPRESSED_EFFECT_SCREEN_ON: return "SUPPRESSED_EFFECT_SCREEN_ON";
- case SUPPRESSED_EFFECTS_UNSET: return "SUPPRESSED_EFFECTS_UNSET";
+ case SUPPRESSED_EFFECT_FULL_SCREEN_INTENT:
+ return "SUPPRESSED_EFFECT_FULL_SCREEN_INTENT";
+ case SUPPRESSED_EFFECT_LIGHTS:
+ return "SUPPRESSED_EFFECT_LIGHTS";
+ case SUPPRESSED_EFFECT_PEEK:
+ return "SUPPRESSED_EFFECT_PEEK";
+ case SUPPRESSED_EFFECT_STATUS_BAR:
+ return "SUPPRESSED_EFFECT_STATUS_BAR";
+ case SUPPRESSED_EFFECT_BADGE:
+ return "SUPPRESSED_EFFECT_BADGE";
+ case SUPPRESSED_EFFECT_AMBIENT:
+ return "SUPPRESSED_EFFECT_AMBIENT";
+ case SUPPRESSED_EFFECT_NOTIFICATION_LIST:
+ return "SUPPRESSED_EFFECT_NOTIFICATION_LIST";
+ case SUPPRESSED_EFFECT_SCREEN_OFF:
+ return "SUPPRESSED_EFFECT_SCREEN_OFF";
+ case SUPPRESSED_EFFECT_SCREEN_ON:
+ return "SUPPRESSED_EFFECT_SCREEN_ON";
+ case SUPPRESSED_EFFECTS_UNSET:
+ return "SUPPRESSED_EFFECTS_UNSET";
default: return "UNKNOWN_" + effect;
}
}
diff --git a/core/java/android/app/StatsManager.java b/core/java/android/app/StatsManager.java
index c2c91c2..b12e3bc 100644
--- a/core/java/android/app/StatsManager.java
+++ b/core/java/android/app/StatsManager.java
@@ -54,6 +54,12 @@
public static final String EXTRA_STATS_SUBSCRIPTION_RULE_ID =
"android.app.extra.STATS_SUBSCRIPTION_RULE_ID";
/**
+ * List<String> of the relevant statsd_config.proto's BroadcastSubscriberDetails.cookie.
+ * Obtain using {@link android.content.Intent#getStringArrayListExtra(String)}.
+ */
+ public static final String EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES =
+ "android.app.extra.STATS_BROADCAST_SUBSCRIBER_COOKIES";
+ /**
* Extra of a {@link android.os.StatsDimensionsValue} representing sliced dimension value
* information.
*/
@@ -146,7 +152,8 @@
* {@link #EXTRA_STATS_CONFIG_UID},
* {@link #EXTRA_STATS_CONFIG_KEY},
* {@link #EXTRA_STATS_SUBSCRIPTION_ID},
- * {@link #EXTRA_STATS_SUBSCRIPTION_RULE_ID}, and
+ * {@link #EXTRA_STATS_SUBSCRIPTION_RULE_ID},
+ * {@link #EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES}, and
* {@link #EXTRA_STATS_DIMENSIONS_VALUE}.
* <p>
* This function can only be called by the owner (uid) of the config. It must be called each
diff --git a/core/java/android/app/servertransaction/ResumeActivityItem.java b/core/java/android/app/servertransaction/ResumeActivityItem.java
index af2fb71..d16bc97 100644
--- a/core/java/android/app/servertransaction/ResumeActivityItem.java
+++ b/core/java/android/app/servertransaction/ResumeActivityItem.java
@@ -48,7 +48,8 @@
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
- client.handleResumeActivity(token, true /* clearHide */, mIsForward, "RESUME_ACTIVITY");
+ client.handleResumeActivity(token, true /* finalStateRequest */, mIsForward,
+ "RESUME_ACTIVITY");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java
index 0e52b34..0d995e8 100644
--- a/core/java/android/app/servertransaction/TransactionExecutor.java
+++ b/core/java/android/app/servertransaction/TransactionExecutor.java
@@ -147,7 +147,10 @@
pw.println("Executor:");
dump(pw, prefix);
- Slog.wtf(TAG, stringWriter.toString());
+ Slog.w(TAG, stringWriter.toString());
+
+ // Ignore requests for non-existent client records for now.
+ return;
}
// Cycle to the state right before the final requested state.
@@ -191,7 +194,7 @@
mTransactionHandler.handleStartActivity(r, mPendingActions);
break;
case ON_RESUME:
- mTransactionHandler.handleResumeActivity(r.token, false /* clearHide */,
+ mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */,
r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
break;
case ON_PAUSE:
diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java
index 9f9ce8d..4f3cd63 100644
--- a/core/java/android/app/slice/SliceManager.java
+++ b/core/java/android/app/slice/SliceManager.java
@@ -18,6 +18,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
@@ -60,6 +62,18 @@
"android.intent.action.REQUEST_SLICE_PERMISSION";
/**
+ * Category used to resolve intents that can be rendered as slices.
+ * <p>
+ * This category should be included on intent filters on providers that extend
+ * {@link SliceProvider}.
+ * @see SliceProvider
+ * @see SliceProvider#onMapIntentToUri(Intent)
+ * @see #mapIntentToUri(Intent)
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_SLICE = "android.app.slice.category.SLICE";
+
+ /**
* The meta-data key that allows an activity to easily be linked directly to a slice.
* <p>
* An activity can be statically linked to a slice uri by including a meta-data item
@@ -226,6 +240,18 @@
/**
* Turns a slice intent into a slice uri. Expects an explicit intent.
+ * <p>
+ * This goes through a several stage resolution process to determine if any slice
+ * can represent this intent.
+ * - If the intent contains data that {@link ContentResolver#getType} is
+ * {@link SliceProvider#SLICE_TYPE} then the data will be returned.
+ * - If the intent with {@link #CATEGORY_SLICE} added resolves to a provider, then
+ * the provider will be asked to {@link SliceProvider#onMapIntentToUri} and that result
+ * will be returned.
+ * - Lastly, if the intent explicitly points at an activity, and that activity has
+ * meta-data for key {@link #SLICE_METADATA_KEY}, then the Uri specified there will be
+ * returned.
+ * - If no slice is found, then {@code null} is returned.
*
* @param intent The intent associated with a slice.
* @return The Slice Uri provided by the app or null if none exists.
@@ -245,8 +271,12 @@
return intentData;
}
// Otherwise ask the app
+ Intent queryIntent = new Intent(intent);
+ if (!queryIntent.hasCategory(CATEGORY_SLICE)) {
+ queryIntent.addCategory(CATEGORY_SLICE);
+ }
List<ResolveInfo> providers =
- mContext.getPackageManager().queryIntentContentProviders(intent, 0);
+ mContext.getPackageManager().queryIntentContentProviders(queryIntent, 0);
if (providers == null || providers.isEmpty()) {
// There are no providers, see if this activity has a direct link.
ResolveInfo resolve = mContext.getPackageManager().resolveActivity(intent,
diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
index 64a5181..aa2cf46 100644
--- a/core/java/android/app/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -16,7 +16,6 @@
package android.app.slice;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.ContentProvider;
@@ -35,7 +34,6 @@
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Handler;
-import android.os.Looper;
import android.os.Process;
import android.os.StrictMode;
import android.os.StrictMode.ThreadPolicy;
@@ -46,7 +44,6 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import java.util.concurrent.CountDownLatch;
/**
* A SliceProvider allows an app to provide content to be displayed in system spaces. This content
@@ -81,6 +78,7 @@
* android:authorities="com.example.mypkg">
* <intent-filter>
* <action android:name="com.example.mypkg.intent.action.MY_SLICE_INTENT" />
+ * <category android:name="android.app.slice.category.SLICE" />
* </intent-filter>
* </provider>}
* </pre>
@@ -162,18 +160,10 @@
private static final boolean DEBUG = false;
- private String mBindingPkg;
- private SliceManager mSliceManager;
+ private static final long SLICE_BIND_ANR = 2000;
- /**
- * Return the package name of the caller that initiated the binding request
- * currently happening. The returned package will have been
- * verified to belong to the calling UID. Returns {@code null} if not
- * currently performing an {@link #onBindSlice(Uri, List)}.
- */
- public final @Nullable String getBindingPackage() {
- return mBindingPkg;
- }
+ private String mCallback;
+ private SliceManager mSliceManager;
@Override
public void attachInfo(Context context, ProviderInfo info) {
@@ -182,12 +172,12 @@
}
/**
- * Implemented to create a slice. Will be called on the main thread.
+ * Implemented to create a slice.
* <p>
* onBindSlice should return as quickly as possible so that the UI tied
* to this slice can be responsive. No network or other IO will be allowed
* during onBindSlice. Any loading that needs to be done should happen
- * off the main thread with a call to {@link ContentResolver#notifyChange(Uri, ContentObserver)}
+ * in the background with a call to {@link ContentResolver#notifyChange(Uri, ContentObserver)}
* when the app is ready to provide the complete data in onBindSlice.
* <p>
* The slice returned should have a spec that is compatible with one of
@@ -253,8 +243,13 @@
* In that case, this method can be called and is expected to return a non-null Uri representing
* a slice. Otherwise this will throw {@link UnsupportedOperationException}.
*
+ * Any intent filter added to a slice provider should also contain
+ * {@link SliceManager#CATEGORY_SLICE}, because otherwise it will not be detected by
+ * {@link SliceManager#mapIntentToUri(Intent)}.
+ *
* @return Uri representing the slice associated with the provided intent.
- * @see {@link Slice}
+ * @see Slice
+ * @see SliceManager#mapIntentToUri(Intent)
*/
public @NonNull Uri onMapIntentToUri(Intent intent) {
throw new UnsupportedOperationException(
@@ -375,55 +370,32 @@
}
private Collection<Uri> handleGetDescendants(Uri uri) {
- if (Looper.myLooper() == Looper.getMainLooper()) {
+ mCallback = "onGetSliceDescendants";
+ Handler.getMain().postDelayed(mAnr, SLICE_BIND_ANR);
+ try {
return onGetSliceDescendants(uri);
- } else {
- CountDownLatch latch = new CountDownLatch(1);
- Collection<Uri>[] output = new Collection[1];
- Handler.getMain().post(() -> {
- output[0] = onGetSliceDescendants(uri);
- latch.countDown();
- });
- try {
- latch.await();
- return output[0];
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
+ } finally {
+ Handler.getMain().removeCallbacks(mAnr);
}
}
private void handlePinSlice(Uri sliceUri) {
- if (Looper.myLooper() == Looper.getMainLooper()) {
+ mCallback = "onSlicePinned";
+ Handler.getMain().postDelayed(mAnr, SLICE_BIND_ANR);
+ try {
onSlicePinned(sliceUri);
- } else {
- CountDownLatch latch = new CountDownLatch(1);
- Handler.getMain().post(() -> {
- onSlicePinned(sliceUri);
- latch.countDown();
- });
- try {
- latch.await();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
+ } finally {
+ Handler.getMain().removeCallbacks(mAnr);
}
}
private void handleUnpinSlice(Uri sliceUri) {
- if (Looper.myLooper() == Looper.getMainLooper()) {
+ mCallback = "onSliceUnpinned";
+ Handler.getMain().postDelayed(mAnr, SLICE_BIND_ANR);
+ try {
onSliceUnpinned(sliceUri);
- } else {
- CountDownLatch latch = new CountDownLatch(1);
- Handler.getMain().post(() -> {
- onSliceUnpinned(sliceUri);
- latch.countDown();
- });
- try {
- latch.await();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
+ } finally {
+ Handler.getMain().removeCallbacks(mAnr);
}
}
@@ -441,21 +413,12 @@
return createPermissionSlice(getContext(), sliceUri, pkg);
}
}
- if (Looper.myLooper() == Looper.getMainLooper()) {
- return onBindSliceStrict(sliceUri, supportedSpecs, pkg);
- } else {
- CountDownLatch latch = new CountDownLatch(1);
- Slice[] output = new Slice[1];
- Handler.getMain().post(() -> {
- output[0] = onBindSliceStrict(sliceUri, supportedSpecs, pkg);
- latch.countDown();
- });
- try {
- latch.await();
- return output[0];
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
+ mCallback = "onBindSlice";
+ Handler.getMain().postDelayed(mAnr, SLICE_BIND_ANR);
+ try {
+ return onBindSliceStrict(sliceUri, supportedSpecs);
+ } finally {
+ Handler.getMain().removeCallbacks(mAnr);
}
}
@@ -507,19 +470,21 @@
}
}
- private Slice onBindSliceStrict(Uri sliceUri, List<SliceSpec> supportedSpecs,
- String callingPackage) {
+ private Slice onBindSliceStrict(Uri sliceUri, List<SliceSpec> supportedSpecs) {
ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
try {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyDeath()
.build());
- mBindingPkg = callingPackage;
return onBindSlice(sliceUri, supportedSpecs);
} finally {
- mBindingPkg = null;
StrictMode.setThreadPolicy(oldPolicy);
}
}
+
+ private final Runnable mAnr = () -> {
+ Process.sendSignal(Process.myPid(), Process.SIGNAL_QUIT);
+ Log.wtf(TAG, "Timed out while handling slice callback " + mCallback);
+ };
}
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 521ab4e..f7fb84b 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -116,6 +116,14 @@
@SystemApi
public static final int STANDBY_BUCKET_CHANGED = 11;
+ /**
+ * An event type denoting that an app posted an interruptive notification. Visual and
+ * audible interruptions are included.
+ * @hide
+ */
+ @SystemApi
+ public static final int NOTIFICATION_INTERRUPTION = 12;
+
/** @hide */
public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;
@@ -188,6 +196,14 @@
*/
public int mBucketAndReason;
+ /**
+ * The id of the {@link android.app.NotificationChannel} to which an interruptive
+ * notification was posted.
+ * Only present for {@link #NOTIFICATION_INTERRUPTION} event types.
+ * {@hide}
+ */
+ public String mNotificationChannelId;
+
/** @hide */
@EventFlags
public int mFlags;
@@ -208,6 +224,7 @@
mContentAnnotations = orig.mContentAnnotations;
mFlags = orig.mFlags;
mBucketAndReason = orig.mBucketAndReason;
+ mNotificationChannelId = orig.mNotificationChannelId;
}
/**
@@ -285,6 +302,16 @@
return mBucketAndReason & 0x0000FFFF;
}
+ /**
+ * Returns the ID of the {@link android.app.NotificationChannel} for this event if the
+ * event is of type {@link #NOTIFICATION_INTERRUPTION}, otherwise it returns null;
+ * @hide
+ */
+ @SystemApi
+ public String getNotificationChannelId() {
+ return mNotificationChannelId;
+ }
+
/** @hide */
public Event getObfuscatedIfInstantApp() {
if ((mFlags & FLAG_IS_PACKAGE_INSTANT_APP) == 0) {
@@ -444,6 +471,9 @@
case Event.STANDBY_BUCKET_CHANGED:
p.writeInt(event.mBucketAndReason);
break;
+ case Event.NOTIFICATION_INTERRUPTION:
+ p.writeString(event.mNotificationChannelId);
+ break;
}
}
@@ -473,6 +503,7 @@
eventOut.mAction = null;
eventOut.mContentType = null;
eventOut.mContentAnnotations = null;
+ eventOut.mNotificationChannelId = null;
switch (eventOut.mEventType) {
case Event.CONFIGURATION_CHANGE:
@@ -490,6 +521,9 @@
case Event.STANDBY_BUCKET_CHANGED:
eventOut.mBucketAndReason = p.readInt();
break;
+ case Event.NOTIFICATION_INTERRUPTION:
+ eventOut.mNotificationChannelId = p.readString();
+ break;
}
}
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index b62b1ee..09ced26 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -59,6 +59,16 @@
public abstract void reportConfigurationChange(Configuration config, @UserIdInt int userId);
/**
+ * Reports that an application has posted an interruptive notification.
+ *
+ * @param packageName The package name of the app that posted the notification
+ * @param channelId The ID of the NotificationChannel to which the notification was posted
+ * @param userId The user in which the notification was posted
+ */
+ public abstract void reportInterruptiveNotification(String packageName, String channelId,
+ @UserIdInt int userId);
+
+ /**
* Reports that an action equivalent to a ShortcutInfo is taken by the user.
*
* @param packageName The package name of the shortcut publisher
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 10331d4..ce7d3af 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -2143,21 +2143,6 @@
}
/**
- * @hide
- */
- public void releasePersistableUriPermission(@NonNull String toPackage, @NonNull Uri uri,
- @Intent.AccessUriMode int modeFlags) {
- Preconditions.checkNotNull(toPackage, "toPackage");
- Preconditions.checkNotNull(uri, "uri");
- try {
- ActivityManager.getService().releasePersistableUriPermission(
- ContentProvider.getUriWithoutUserId(uri), modeFlags, toPackage,
- resolveUserId(uri));
- } catch (RemoteException e) {
- }
- }
-
- /**
* Return list of all URI permission grants that have been persisted by the
* calling app. That is, the returned permissions have been granted
* <em>to</em> the calling app. Only persistable grants taken with
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index e7aead1..ce32278 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2448,6 +2448,23 @@
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";
+
+
+ /**
+ * Broadcast Action: Sent when the current battery level changes.
+ *
+ * It has {@link android.os.BatteryManager#EXTRA_EVENTS} that carries a list of {@link Bundle}
+ * instances representing individual battery level changes with associated
+ * extras from {@link #ACTION_BATTERY_CHANGED}.
+ *
+ * <p class="note">
+ * This broadcast requires {@link android.Manifest.permission#BATTERY_STATS} permission.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String ACTION_BATTERY_LEVEL_CHANGED =
+ "android.intent.action.BATTERY_LEVEL_CHANGED";
/**
* Broadcast Action: Indicates low battery condition on the device.
* This broadcast corresponds to the "Low battery warning" system dialog.
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 9e0c680..97868fa 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -26,8 +26,6 @@
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.PointerIcon;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodSubtype;
/** @hide */
interface IInputManager {
@@ -67,11 +65,6 @@
String keyboardLayoutDescriptor);
void removeKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor);
- KeyboardLayout getKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
- in InputMethodInfo imeInfo, in InputMethodSubtype imeSubtype);
- void setKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
- in InputMethodInfo imeInfo, in InputMethodSubtype imeSubtype,
- String keyboardLayoutDescriptor);
// Registers an input devices changed listener.
void registerInputDevicesChangedListener(IInputDevicesChangedListener listener);
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index fdea5a2..6ae7a14 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -17,7 +17,6 @@
package android.hardware.input;
import android.annotation.IntDef;
-import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
@@ -43,8 +42,6 @@
import android.view.InputEvent;
import android.view.MotionEvent;
import android.view.PointerIcon;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodSubtype;
import com.android.internal.os.SomeArgs;
@@ -703,52 +700,6 @@
}
}
-
- /**
- * Gets the keyboard layout for the specified input device and IME subtype.
- *
- * @param identifier The identifier for the input device.
- * @param inputMethodInfo The input method.
- * @param inputMethodSubtype The input method subtype. {@code null} if this input method does
- * not support any subtype.
- *
- * @return The associated {@link KeyboardLayout}, or null if one has not been set.
- *
- * @hide
- */
- @Nullable
- public KeyboardLayout getKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
- InputMethodInfo inputMethodInfo, @Nullable InputMethodSubtype inputMethodSubtype) {
- try {
- return mIm.getKeyboardLayoutForInputDevice(
- identifier, inputMethodInfo, inputMethodSubtype);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- }
-
- /**
- * Sets the keyboard layout for the specified input device and IME subtype pair.
- *
- * @param identifier The identifier for the input device.
- * @param inputMethodInfo The input method with which to associate the keyboard layout.
- * @param inputMethodSubtype The input method subtype which which to associate the keyboard
- * layout. {@code null} if this input method does not support any subtype.
- * @param keyboardLayoutDescriptor The descriptor of the keyboard layout to set
- *
- * @hide
- */
- public void setKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
- InputMethodInfo inputMethodInfo, @Nullable InputMethodSubtype inputMethodSubtype,
- String keyboardLayoutDescriptor) {
- try {
- mIm.setKeyboardLayoutForInputDevice(identifier, inputMethodInfo,
- inputMethodSubtype, keyboardLayoutDescriptor);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- }
-
/**
* Gets the TouchCalibration applied to the specified input device's coordinates.
*
diff --git a/core/java/android/hardware/input/InputManagerInternal.java b/core/java/android/hardware/input/InputManagerInternal.java
index 4ea0f55..eb7ea67 100644
--- a/core/java/android/hardware/input/InputManagerInternal.java
+++ b/core/java/android/hardware/input/InputManagerInternal.java
@@ -16,11 +16,8 @@
package android.hardware.input;
-import android.annotation.Nullable;
import android.hardware.display.DisplayViewport;
import android.view.InputEvent;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodSubtype;
import java.util.List;
@@ -46,16 +43,6 @@
public abstract void setInteractive(boolean interactive);
/**
- * Notifies that InputMethodManagerService switched the current input method subtype.
- *
- * @param userId user id that indicates who is using the specified input method and subtype.
- * @param inputMethodInfo {@code null} when no input method is selected.
- * @param subtype {@code null} when {@code inputMethodInfo} does has no subtype.
- */
- public abstract void onInputMethodSubtypeChanged(int userId,
- @Nullable InputMethodInfo inputMethodInfo, @Nullable InputMethodSubtype subtype);
-
- /**
* Toggles Caps Lock state for input device with specific id.
*
* @param deviceId The id of input device.
diff --git a/core/java/android/hardware/input/TouchCalibration.java b/core/java/android/hardware/input/TouchCalibration.java
index 15503ed..025fad0 100644
--- a/core/java/android/hardware/input/TouchCalibration.java
+++ b/core/java/android/hardware/input/TouchCalibration.java
@@ -123,10 +123,4 @@
Float.floatToIntBits(mYScale) ^
Float.floatToIntBits(mYOffset);
}
-
- @Override
- public String toString() {
- return String.format("[%f, %f, %f, %f, %f, %f]",
- mXScale, mXYMix, mXOffset, mYXMix, mYScale, mYOffset);
- }
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index f38c37a..b3bf092 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1081,7 +1081,7 @@
* @return true if the current input method and subtype was successfully switched to the last
* used input method and subtype.
*/
- public boolean switchToPreviousInputMethod() {
+ public final boolean switchToPreviousInputMethod() {
return mImm.switchToPreviousInputMethodInternal(mToken);
}
@@ -1093,7 +1093,7 @@
* @return true if the current input method and subtype was successfully switched to the next
* input method and subtype.
*/
- public boolean switchToNextInputMethod(boolean onlyCurrentIme) {
+ public final boolean switchToNextInputMethod(boolean onlyCurrentIme) {
return mImm.switchToNextInputMethodInternal(mToken, onlyCurrentIme);
}
@@ -1106,7 +1106,7 @@
* and subtype in order to provide the consistent user experience in switching
* between IMEs and subtypes.
*/
- public boolean shouldOfferSwitchingToNextInputMethod() {
+ public final boolean shouldOfferSwitchingToNextInputMethod() {
return mImm.shouldOfferSwitchingToNextInputMethodInternal(mToken);
}
@@ -1450,7 +1450,7 @@
* @param id Unique identifier of the new input method to start.
* @param subtype The new subtype of the new input method to be switched to.
*/
- public void switchInputMethod(String id, InputMethodSubtype subtype) {
+ public final void switchInputMethod(String id, InputMethodSubtype subtype) {
mImm.setInputMethodAndSubtypeInternal(mToken, id, subtype);
}
@@ -2059,7 +2059,7 @@
* @see InputMethodManager#SHOW_FORCED
* @param flags Provides additional operating flags.
*/
- public void requestShowSelf(int flags) {
+ public final void requestShowSelf(int flags) {
mImm.showSoftInputFromInputMethodInternal(mToken, flags);
}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 71266a0..36f359b 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -453,133 +453,177 @@
public static final int TYPE_NONE = -1;
/**
- * The Mobile data connection. When active, all data traffic
- * will use this network type's interface by default
- * (it has a default route)
+ * A Mobile data connection. Devices may support more than one.
+ *
+ * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or
+ * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an
+ * appropriate network. {@see NetworkCapabilities} for supported transports.
*/
+ @Deprecated
public static final int TYPE_MOBILE = 0;
+
/**
- * The WIFI data connection. When active, all data traffic
- * will use this network type's interface by default
- * (it has a default route).
+ * A WIFI data connection. Devices may support more than one.
+ *
+ * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or
+ * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an
+ * appropriate network. {@see NetworkCapabilities} for supported transports.
*/
+ @Deprecated
public static final int TYPE_WIFI = 1;
+
/**
* An MMS-specific Mobile data connection. This network type may use the
* same network interface as {@link #TYPE_MOBILE} or it may use a different
* one. This is used by applications needing to talk to the carrier's
* Multimedia Messaging Service servers.
*
- * @deprecated Applications should instead use
+ * @deprecated Applications should instead use {@link NetworkCapabilities#hasCapability} or
* {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that
* provides the {@link NetworkCapabilities#NET_CAPABILITY_MMS} capability.
*/
@Deprecated
public static final int TYPE_MOBILE_MMS = 2;
+
/**
* A SUPL-specific Mobile data connection. This network type may use the
* same network interface as {@link #TYPE_MOBILE} or it may use a different
* one. This is used by applications needing to talk to the carrier's
* Secure User Plane Location servers for help locating the device.
*
- * @deprecated Applications should instead use
+ * @deprecated Applications should instead use {@link NetworkCapabilities#hasCapability} or
* {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that
* provides the {@link NetworkCapabilities#NET_CAPABILITY_SUPL} capability.
*/
@Deprecated
public static final int TYPE_MOBILE_SUPL = 3;
+
/**
* A DUN-specific Mobile data connection. This network type may use the
* same network interface as {@link #TYPE_MOBILE} or it may use a different
* one. This is sometimes by the system when setting up an upstream connection
* for tethering so that the carrier is aware of DUN traffic.
+ *
+ * @deprecated Applications should instead use {@link NetworkCapabilities#hasCapability} or
+ * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that
+ * provides the {@link NetworkCapabilities#NET_CAPABILITY_DUN} capability.
*/
+ @Deprecated
public static final int TYPE_MOBILE_DUN = 4;
+
/**
* A High Priority Mobile data connection. This network type uses the
* same network interface as {@link #TYPE_MOBILE} but the routing setup
* is different.
*
- * @deprecated Applications should instead use
- * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that
- * uses the {@link NetworkCapabilities#TRANSPORT_CELLULAR} transport.
+ * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or
+ * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an
+ * appropriate network. {@see NetworkCapabilities} for supported transports.
*/
@Deprecated
public static final int TYPE_MOBILE_HIPRI = 5;
+
/**
- * The WiMAX data connection. When active, all data traffic
- * will use this network type's interface by default
- * (it has a default route).
+ * A WiMAX data connection.
+ *
+ * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or
+ * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an
+ * appropriate network. {@see NetworkCapabilities} for supported transports.
*/
+ @Deprecated
public static final int TYPE_WIMAX = 6;
/**
- * The Bluetooth data connection. When active, all data traffic
- * will use this network type's interface by default
- * (it has a default route).
+ * A Bluetooth data connection.
+ *
+ * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or
+ * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an
+ * appropriate network. {@see NetworkCapabilities} for supported transports.
*/
+ @Deprecated
public static final int TYPE_BLUETOOTH = 7;
/**
* Dummy data connection. This should not be used on shipping devices.
+ * @deprecated This is not used any more.
*/
+ @Deprecated
public static final int TYPE_DUMMY = 8;
/**
- * The Ethernet data connection. When active, all data traffic
- * will use this network type's interface by default
- * (it has a default route).
+ * An Ethernet data connection.
+ *
+ * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or
+ * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an
+ * appropriate network. {@see NetworkCapabilities} for supported transports.
*/
+ @Deprecated
public static final int TYPE_ETHERNET = 9;
/**
* Over the air Administration.
+ * @deprecated Use {@link NetworkCapabilities} instead.
* {@hide}
*/
+ @Deprecated
public static final int TYPE_MOBILE_FOTA = 10;
/**
* IP Multimedia Subsystem.
+ * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_IMS} instead.
* {@hide}
*/
+ @Deprecated
public static final int TYPE_MOBILE_IMS = 11;
/**
* Carrier Branded Services.
+ * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_CBS} instead.
* {@hide}
*/
+ @Deprecated
public static final int TYPE_MOBILE_CBS = 12;
/**
* A Wi-Fi p2p connection. Only requesting processes will have access to
* the peers connected.
+ * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_WIFI_P2P} instead.
* {@hide}
*/
+ @Deprecated
public static final int TYPE_WIFI_P2P = 13;
/**
* The network to use for initially attaching to the network
+ * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_IA} instead.
* {@hide}
*/
+ @Deprecated
public static final int TYPE_MOBILE_IA = 14;
/**
* Emergency PDN connection for emergency services. This
* may include IMS and MMS in emergency situations.
+ * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_EIMS} instead.
* {@hide}
*/
+ @Deprecated
public static final int TYPE_MOBILE_EMERGENCY = 15;
/**
* The network that uses proxy to achieve connectivity.
+ * @deprecated Use {@link NetworkCapabilities} instead.
* {@hide}
*/
+ @Deprecated
public static final int TYPE_PROXY = 16;
/**
* A virtual network using one or more native bearers.
* It may or may not be providing security services.
+ * @deprecated Applications should use {@link NetworkCapabilities#TRANSPORT_VPN} instead.
*/
+ @Deprecated
public static final int TYPE_VPN = 17;
/** {@hide} */
@@ -686,8 +730,10 @@
* @param type the type needing naming
* @return a String for the given type, or a string version of the type ("87")
* if no name is known.
+ * @deprecated Types are deprecated. Use {@link NetworkCapabilities} instead.
* {@hide}
*/
+ @Deprecated
public static String getNetworkTypeName(int type) {
switch (type) {
case TYPE_NONE:
@@ -738,8 +784,10 @@
* This should be replaced in the future by a network property.
* @param networkType the type to check
* @return a boolean - {@code true} if uses cellular network, else {@code false}
+ * @deprecated Types are deprecated. Use {@link NetworkCapabilities} instead.
* {@hide}
*/
+ @Deprecated
public static boolean isNetworkTypeMobile(int networkType) {
switch (networkType) {
case TYPE_MOBILE:
@@ -761,8 +809,10 @@
/**
* Checks if the given network type is backed by a Wi-Fi radio.
*
+ * @deprecated Types are deprecated. Use {@link NetworkCapabilities} instead.
* @hide
*/
+ @Deprecated
public static boolean isNetworkTypeWifi(int networkType) {
switch (networkType) {
case TYPE_WIFI:
@@ -1529,6 +1579,8 @@
* IllegalArgumentException if no mapping from the legacy type to
* NetworkCapabilities is known.
*
+ * @deprecated Types are deprecated. Use {@link NetworkCallback} or {@link NetworkRequest}
+ * to find the network instead.
* @hide
*/
public static NetworkCapabilities networkCapabilitiesForType(int type) {
@@ -2380,6 +2432,7 @@
*
* @param networkType The type of network you want to report on
* @param percentage The quality of the connection 0 is bad, 100 is good
+ * @deprecated Types are deprecated. Use {@link #reportNetworkConnectivity} instead.
* {@hide}
*/
public void reportInetCondition(int networkType, int percentage) {
@@ -2511,9 +2564,10 @@
*
* @param networkType The network type we'd like to check
* @return {@code true} if supported, else {@code false}
- *
+ * @deprecated Types are deprecated. Use {@link NetworkCapabilities} instead.
* @hide
*/
+ @Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
public boolean isNetworkSupported(int networkType) {
try {
diff --git a/core/java/android/net/INetdEventCallback.aidl b/core/java/android/net/INetdEventCallback.aidl
index 1fd9423..1e75bf4 100644
--- a/core/java/android/net/INetdEventCallback.aidl
+++ b/core/java/android/net/INetdEventCallback.aidl
@@ -20,8 +20,9 @@
oneway interface INetdEventCallback {
// Possible addNetdEventCallback callers.
- const int CALLBACK_CALLER_DEVICE_POLICY = 0;
- const int CALLBACK_CALLER_NETWORK_WATCHLIST = 1;
+ const int CALLBACK_CALLER_CONNECTIVITY_SERVICE = 0;
+ const int CALLBACK_CALLER_DEVICE_POLICY = 1;
+ const int CALLBACK_CALLER_NETWORK_WATCHLIST = 2;
/**
* Reports a single DNS lookup function call.
@@ -39,6 +40,18 @@
int uid);
/**
+ * Represents a private DNS validation success or failure.
+ * This method must not block or perform long-running operations.
+ *
+ * @param netId the ID of the network the validation was performed on.
+ * @param ipAddress the IP address for which validation was performed.
+ * @param hostname the hostname for which validation was performed.
+ * @param validated whether or not validation was successful.
+ */
+ void onPrivateDnsValidationEvent(int netId, String ipAddress, String hostname,
+ boolean validated);
+
+ /**
* Reports a single connect library call.
* This method must not block or perform long-running operations.
*
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index e6ad89a..999771a 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -38,14 +38,18 @@
* <table>
* <tr><td><b>Detailed state</b></td><td><b>Coarse-grained state</b></td></tr>
* <tr><td><code>IDLE</code></td><td><code>DISCONNECTED</code></td></tr>
- * <tr><td><code>SCANNING</code></td><td><code>CONNECTING</code></td></tr>
+ * <tr><td><code>SCANNING</code></td><td><code>DISCONNECTED</code></td></tr>
* <tr><td><code>CONNECTING</code></td><td><code>CONNECTING</code></td></tr>
* <tr><td><code>AUTHENTICATING</code></td><td><code>CONNECTING</code></td></tr>
+ * <tr><td><code>OBTAINING_IPADDR</code></td><td><code>CONNECTING</code></td></tr>
+ * <tr><td><code>VERIFYING_POOR_LINK</code></td><td><code>CONNECTING</code></td></tr>
+ * <tr><td><code>CAPTIVE_PORTAL_CHECK</code></td><td><code>CONNECTING</code></td></tr>
* <tr><td><code>CONNECTED</code></td><td><code>CONNECTED</code></td></tr>
+ * <tr><td><code>SUSPENDED</code></td><td><code>SUSPENDED</code></td></tr>
* <tr><td><code>DISCONNECTING</code></td><td><code>DISCONNECTING</code></td></tr>
* <tr><td><code>DISCONNECTED</code></td><td><code>DISCONNECTED</code></td></tr>
- * <tr><td><code>UNAVAILABLE</code></td><td><code>DISCONNECTED</code></td></tr>
* <tr><td><code>FAILED</code></td><td><code>DISCONNECTED</code></td></tr>
+ * <tr><td><code>BLOCKED</code></td><td><code>DISCONNECTED</code></td></tr>
* </table>
*/
public enum State {
@@ -163,8 +167,17 @@
* @return one of {@link ConnectivityManager#TYPE_MOBILE}, {@link
* ConnectivityManager#TYPE_WIFI}, {@link ConnectivityManager#TYPE_WIMAX}, {@link
* ConnectivityManager#TYPE_ETHERNET}, {@link ConnectivityManager#TYPE_BLUETOOTH}, or other
- * types defined by {@link ConnectivityManager}
+ * types defined by {@link ConnectivityManager}.
+ * @deprecated Callers should switch to checking {@link NetworkCapabilities#hasTransport}
+ * instead with one of the NetworkCapabilities#TRANSPORT_* constants :
+ * {@link #getType} and {@link #getTypeName} cannot account for networks using
+ * multiple transports. Note that generally apps should not care about transport;
+ * {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED} and
+ * {@link NetworkCapabilities#getLinkDownstreamBandwidthKbps} are calls that
+ * apps concerned with meteredness or bandwidth should be looking at, as they
+ * offer this information with much better accuracy.
*/
+ @Deprecated
public int getType() {
synchronized (this) {
return mNetworkType;
@@ -172,8 +185,10 @@
}
/**
+ * @deprecated Use {@link NetworkCapabilities} instead
* @hide
*/
+ @Deprecated
public void setType(int type) {
synchronized (this) {
mNetworkType = type;
@@ -205,7 +220,16 @@
* Return a human-readable name describe the type of the network,
* for example "WIFI" or "MOBILE".
* @return the name of the network type
+ * @deprecated Callers should switch to checking {@link NetworkCapabilities#hasTransport}
+ * instead with one of the NetworkCapabilities#TRANSPORT_* constants :
+ * {@link #getType} and {@link #getTypeName} cannot account for networks using
+ * multiple transports. Note that generally apps should not care about transport;
+ * {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED} and
+ * {@link NetworkCapabilities#getLinkDownstreamBandwidthKbps} are calls that
+ * apps concerned with meteredness or bandwidth should be looking at, as they
+ * offer this information with much better accuracy.
*/
+ @Deprecated
public String getTypeName() {
synchronized (this) {
return mTypeName;
@@ -230,7 +254,15 @@
* that the network is fully usable.
* @return {@code true} if network connectivity exists or is in the process
* of being established, {@code false} otherwise.
+ * @deprecated Apps should instead use the
+ * {@link android.net.ConnectivityManager.NetworkCallback} API to
+ * learn about connectivity changes.
+ * {@link ConnectivityManager#registerDefaultNetworkCallback} and
+ * {@link ConnectivityManager#registerNetworkCallback}. These will
+ * give a more accurate picture of the connectivity state of
+ * the device and let apps react more easily and quickly to changes.
*/
+ @Deprecated
public boolean isConnectedOrConnecting() {
synchronized (this) {
return mState == State.CONNECTED || mState == State.CONNECTING;
@@ -259,8 +291,18 @@
* data roaming has been disabled.</li>
* <li>The device's radio is turned off, e.g., because airplane mode is enabled.</li>
* </ul>
+ * Since Android L, this always returns {@code true}, because the system only
+ * returns info for available networks.
* @return {@code true} if the network is available, {@code false} otherwise
+ * @deprecated Apps should instead use the
+ * {@link android.net.ConnectivityManager.NetworkCallback} API to
+ * learn about connectivity changes.
+ * {@link ConnectivityManager#registerDefaultNetworkCallback} and
+ * {@link ConnectivityManager#registerNetworkCallback}. These will
+ * give a more accurate picture of the connectivity state of
+ * the device and let apps react more easily and quickly to changes.
*/
+ @Deprecated
public boolean isAvailable() {
synchronized (this) {
return mIsAvailable;
@@ -270,9 +312,11 @@
/**
* Sets if the network is available, ie, if the connectivity is possible.
* @param isAvailable the new availability value.
+ * @deprecated Use {@link NetworkCapabilities} instead
*
* @hide
*/
+ @Deprecated
public void setIsAvailable(boolean isAvailable) {
synchronized (this) {
mIsAvailable = isAvailable;
@@ -285,7 +329,10 @@
* network following a disconnect from another network.
* @return {@code true} if this is a failover attempt, {@code false}
* otherwise.
+ * @deprecated This field is not populated in recent Android releases,
+ * and does not make a lot of sense in a multi-network world.
*/
+ @Deprecated
public boolean isFailover() {
synchronized (this) {
return mIsFailover;
@@ -296,8 +343,10 @@
* Set the failover boolean.
* @param isFailover {@code true} to mark the current connection attempt
* as a failover.
+ * @deprecated This hasn't been set in any recent Android release.
* @hide
*/
+ @Deprecated
public void setFailover(boolean isFailover) {
synchronized (this) {
mIsFailover = isFailover;
@@ -322,7 +371,10 @@
}
}
- /** {@hide} */
+ /**
+ * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_NOT_ROAMING} instead.
+ * {@hide}
+ */
@VisibleForTesting
@Deprecated
public void setRoaming(boolean isRoaming) {
@@ -334,7 +386,15 @@
/**
* Reports the current coarse-grained state of the network.
* @return the coarse-grained state
+ * @deprecated Apps should instead use the
+ * {@link android.net.ConnectivityManager.NetworkCallback} API to
+ * learn about connectivity changes.
+ * {@link ConnectivityManager#registerDefaultNetworkCallback} and
+ * {@link ConnectivityManager#registerNetworkCallback}. These will
+ * give a more accurate picture of the connectivity state of
+ * the device and let apps react more easily and quickly to changes.
*/
+ @Deprecated
public State getState() {
synchronized (this) {
return mState;
@@ -358,8 +418,10 @@
* if one was supplied. May be {@code null}.
* @param extraInfo an optional {@code String} providing addditional network state
* information passed up from the lower networking layers.
+ * @deprecated Use {@link NetworkCapabilities} instead.
* @hide
*/
+ @Deprecated
public void setDetailedState(DetailedState detailedState, String reason, String extraInfo) {
synchronized (this) {
this.mDetailedState = detailedState;
@@ -385,6 +447,8 @@
* Report the reason an attempt to establish connectivity failed,
* if one is available.
* @return the reason for failure, or null if not available
+ * @deprecated This method does not have a consistent contract that could make it useful
+ * to callers.
*/
public String getReason() {
synchronized (this) {
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 8b4f02e..6363161 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -16,6 +16,7 @@
package android.os;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.content.Intent;
@@ -138,6 +139,23 @@
*/
public static final String EXTRA_SEQUENCE = "seq";
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_LEVEL_CHANGED}:
+ * Contains list of Bundles representing battery events
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_EVENTS = "android.os.extra.EVENTS";
+
+ /**
+ * Extra for event in {@link android.content.Intent#ACTION_BATTERY_LEVEL_CHANGED}:
+ * Long value representing time when event occurred as returned by
+ * {@link android.os.SystemClock#elapsedRealtime()}
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_EVENT_TIMESTAMP = "android.os.extra.EVENT_TIMESTAMP";
+
// values for "status" field in the ACTION_BATTERY_CHANGED Intent
public static final int BATTERY_STATUS_UNKNOWN = Constants.BATTERY_STATUS_UNKNOWN;
public static final int BATTERY_STATUS_CHARGING = Constants.BATTERY_STATUS_CHARGING;
diff --git a/core/java/android/os/IStatsCompanionService.aidl b/core/java/android/os/IStatsCompanionService.aidl
index 29c298e..402c995 100644
--- a/core/java/android/os/IStatsCompanionService.aidl
+++ b/core/java/android/os/IStatsCompanionService.aidl
@@ -74,6 +74,7 @@
*/
oneway void sendSubscriberBroadcast(in IBinder intentSender, long configUid, long configId,
long subscriptionId, long subscriptionRuleId,
+ in String[] cookies,
in StatsDimensionsValue dimensionsValue);
/** Tells StatsCompaionService to grab the uid map snapshot and send it to statsd. */
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index c7d89b0..2cb5aee 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -141,6 +141,14 @@
public abstract void setDozeOverrideFromDreamManager(
int screenState, int screenBrightness);
+ /**
+ * Used by sidekick manager to tell the power manager if it shouldn't change the display state
+ * when a draw wake lock is acquired. Some processes may grab such a wake lock to do some work
+ * in a powered-up state, but we shouldn't give up sidekick control over the display until this
+ * override is lifted.
+ */
+ public abstract void setDrawWakeLockOverrideFromSidekick(boolean keepState);
+
public abstract PowerSaveState getLowPowerState(int serviceType);
public abstract void registerLowPowerModeObserver(LowPowerModeListener listener);
diff --git a/core/java/android/provider/BlockedNumberContract.java b/core/java/android/provider/BlockedNumberContract.java
index fb11d00..8aef012 100644
--- a/core/java/android/provider/BlockedNumberContract.java
+++ b/core/java/android/provider/BlockedNumberContract.java
@@ -228,6 +228,25 @@
/** @hide */
public static final String RES_CAN_BLOCK_NUMBERS = "can_block";
+ /** @hide */
+ public static final String RES_ENHANCED_SETTING_IS_ENABLED = "enhanced_setting_enabled";
+
+ /** @hide */
+ public static final String RES_SHOW_EMERGENCY_CALL_NOTIFICATION =
+ "show_emergency_call_notification";
+
+ /** @hide */
+ public static final String EXTRA_ENHANCED_SETTING_KEY = "extra_enhanced_setting_key";
+
+ /** @hide */
+ public static final String EXTRA_ENHANCED_SETTING_VALUE = "extra_enhanced_setting_value";
+
+ /** @hide */
+ public static final String EXTRA_CONTACT_EXIST = "extra_contact_exist";
+
+ /** @hide */
+ public static final String EXTRA_CALL_PRESENTATION = "extra_call_presentation";
+
/**
* Returns whether a given number is in the blocked list.
*
@@ -314,11 +333,33 @@
public static final String METHOD_GET_BLOCK_SUPPRESSION_STATUS =
"get_block_suppression_status";
+ public static final String METHOD_SHOULD_SHOW_EMERGENCY_CALL_NOTIFICATION =
+ "should_show_emergency_call_notification";
+
public static final String RES_IS_BLOCKING_SUPPRESSED = "blocking_suppressed";
public static final String RES_BLOCKING_SUPPRESSED_UNTIL_TIMESTAMP =
"blocking_suppressed_until_timestamp";
+ public static final String METHOD_GET_ENHANCED_BLOCK_SETTING = "get_enhanced_block_setting";
+ public static final String METHOD_SET_ENHANCED_BLOCK_SETTING = "set_enhanced_block_setting";
+
+ /* Preference key of block numbers not in contacts setting. */
+ public static final String ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED =
+ "block_numbers_not_in_contacts_setting";
+ /* Preference key of block private number calls setting. */
+ public static final String ENHANCED_SETTING_KEY_BLOCK_PRIVATE =
+ "block_private_number_calls_setting";
+ /* Preference key of block payphone calls setting. */
+ public static final String ENHANCED_SETTING_KEY_BLOCK_PAYPHONE =
+ "block_payphone_calls_setting";
+ /* Preference key of block unknown calls setting. */
+ public static final String ENHANCED_SETTING_KEY_BLOCK_UNKNOWN =
+ "block_unknown_calls_setting";
+ /* Preference key for whether should show an emergency call notification. */
+ public static final String ENHANCED_SETTING_KEY_SHOW_EMERGENCY_CALL_NOTIFICATION =
+ "show_emergency_call_notification";
+
/**
* Notifies the provider that emergency services were contacted by the user.
* <p> This results in {@link #shouldSystemBlockNumber} returning {@code false} independent
@@ -342,13 +383,19 @@
/**
* Returns {@code true} if {@code phoneNumber} is blocked taking
- * {@link #notifyEmergencyContact(Context)} into consideration. If emergency services have
- * not been contacted recently, this method is equivalent to
- * {@link #isBlocked(Context, String)}.
+ * {@link #notifyEmergencyContact(Context)} into consideration. If emergency services
+ * have not been contacted recently and enhanced call blocking not been enabled, this
+ * method is equivalent to {@link #isBlocked(Context, String)}.
+ *
+ * @param context the context of the caller.
+ * @param phoneNumber the number to check.
+ * @param extras the extra attribute of the number.
+ * @return {@code true} if should block the number. {@code false} otherwise.
*/
- public static boolean shouldSystemBlockNumber(Context context, String phoneNumber) {
+ public static boolean shouldSystemBlockNumber(Context context, String phoneNumber,
+ Bundle extras) {
final Bundle res = context.getContentResolver().call(
- AUTHORITY_URI, METHOD_SHOULD_SYSTEM_BLOCK_NUMBER, phoneNumber, null);
+ AUTHORITY_URI, METHOD_SHOULD_SYSTEM_BLOCK_NUMBER, phoneNumber, extras);
return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false);
}
@@ -363,9 +410,62 @@
}
/**
- * Represents the current status of {@link #shouldSystemBlockNumber(Context, String)}. If
- * emergency services have been contacted recently, {@link #isSuppressed} is {@code true},
- * and blocking is disabled until the timestamp {@link #untilTimestampMillis}.
+ * Check whether should show the emergency call notification.
+ *
+ * @param context the context of the caller.
+ * @return {@code true} if should show emergency call notification. {@code false} otherwise.
+ */
+ public static boolean shouldShowEmergencyCallNotification(Context context) {
+ final Bundle res = context.getContentResolver().call(
+ AUTHORITY_URI, METHOD_SHOULD_SHOW_EMERGENCY_CALL_NOTIFICATION, null, null);
+ return res != null && res.getBoolean(RES_SHOW_EMERGENCY_CALL_NOTIFICATION, false);
+ }
+
+ /**
+ * Check whether the enhanced block setting is enabled.
+ *
+ * @param context the context of the caller.
+ * @param key the key of the setting to check, can be
+ * {@link #ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED}
+ * {@link #ENHANCED_SETTING_KEY_BLOCK_PRIVATE}
+ * {@link #ENHANCED_SETTING_KEY_BLOCK_PAYPHONE}
+ * {@link #ENHANCED_SETTING_KEY_BLOCK_UNKNOWN}
+ * {@link #ENHANCED_SETTING_KEY_EMERGENCY_CALL_NOTIFICATION_SHOWING}
+ * @return {@code true} if the setting is enabled. {@code false} otherwise.
+ */
+ public static boolean getEnhancedBlockSetting(Context context, String key) {
+ Bundle extras = new Bundle();
+ extras.putString(EXTRA_ENHANCED_SETTING_KEY, key);
+ final Bundle res = context.getContentResolver().call(
+ AUTHORITY_URI, METHOD_GET_ENHANCED_BLOCK_SETTING, null, extras);
+ return res != null && res.getBoolean(RES_ENHANCED_SETTING_IS_ENABLED, false);
+ }
+
+ /**
+ * Set the enhanced block setting enabled status.
+ *
+ * @param context the context of the caller.
+ * @param key the key of the setting to set, can be
+ * {@link #ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED}
+ * {@link #ENHANCED_SETTING_KEY_BLOCK_PRIVATE}
+ * {@link #ENHANCED_SETTING_KEY_BLOCK_PAYPHONE}
+ * {@link #ENHANCED_SETTING_KEY_BLOCK_UNKNOWN}
+ * {@link #ENHANCED_SETTING_KEY_EMERGENCY_CALL_NOTIFICATION_SHOWING}
+ * @param value the enabled statue of the setting to set.
+ */
+ public static void setEnhancedBlockSetting(Context context, String key, boolean value) {
+ Bundle extras = new Bundle();
+ extras.putString(EXTRA_ENHANCED_SETTING_KEY, key);
+ extras.putBoolean(EXTRA_ENHANCED_SETTING_VALUE, value);
+ context.getContentResolver().call(AUTHORITY_URI, METHOD_SET_ENHANCED_BLOCK_SETTING,
+ null, extras);
+ }
+
+ /**
+ * Represents the current status of
+ * {@link #shouldSystemBlockNumber(Context, String, Bundle)}. If emergency services
+ * have been contacted recently, {@link #isSuppressed} is {@code true}, and blocking
+ * is disabled until the timestamp {@link #untilTimestampMillis}.
*/
public static class BlockSuppressionStatus {
public final boolean isSuppressed;
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index d9808a3..1da6602 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -692,8 +692,8 @@
// Log.v(TAG, "getThumbnail: origId="+origId+", kind="+kind+", isVideo="+isVideo);
// If the magic is non-zero, we simply return thumbnail if it does exist.
// querying MediaProvider and simply return thumbnail.
- MiniThumbFile thumbFile = new MiniThumbFile(isVideo ? Video.Media.EXTERNAL_CONTENT_URI
- : Images.Media.EXTERNAL_CONTENT_URI);
+ MiniThumbFile thumbFile = MiniThumbFile.instance(
+ isVideo ? Video.Media.EXTERNAL_CONTENT_URI : Images.Media.EXTERNAL_CONTENT_URI);
Cursor c = null;
try {
long magic = thumbFile.getMagic(origId);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index bd29d2d..ef1dce3 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -430,6 +430,20 @@
"android.settings.WIFI_IP_SETTINGS";
/**
+ * Activity Action: Show settings to allow configuration of data and view data usage.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_DATA_USAGE_SETTINGS =
+ "android.settings.DATA_USAGE_SETTINGS";
+
+ /**
* Activity Action: Show settings to allow configuration of Bluetooth.
* <p>
* In some cases, a matching Activity may not exist, so ensure you
@@ -3713,7 +3727,7 @@
public static final Validator SOUND_EFFECTS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
/**
- * Whether the haptic feedback (long presses, ...) are enabled. The value is
+ * Whether haptic feedback (Vibrate on tap) is enabled. The value is
* boolean (1 or 0).
*/
public static final String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled";
@@ -6170,10 +6184,13 @@
/**
* Integer property that specifies the type of color space adjustment to
- * perform. Valid values are defined in AccessibilityManager:
+ * perform. Valid values are defined in AccessibilityManager and Settings arrays.xml:
* - AccessibilityManager.DALTONIZER_DISABLED = -1
* - AccessibilityManager.DALTONIZER_SIMULATE_MONOCHROMACY = 0
- * - AccessibilityManager.DALTONIZER_CORRECT_DEUTERANOMALY = 12
+ * - <item>@string/daltonizer_mode_protanomaly</item> = 11
+ * - AccessibilityManager.DALTONIZER_CORRECT_DEUTERANOMALY and
+ * <item>@string/daltonizer_mode_deuteranomaly</item> = 12
+ * - <item>@string/daltonizer_mode_tritanomaly</item> = 13
*
* @hide
*/
@@ -6181,7 +6198,8 @@
"accessibility_display_daltonizer";
private static final Validator ACCESSIBILITY_DISPLAY_DALTONIZER_VALIDATOR =
- new SettingsValidators.DiscreteValueValidator(new String[] {"-1", "0", "12"});
+ new SettingsValidators.DiscreteValueValidator(
+ new String[] {"-1", "0", "11", "12", "13"});
/**
* Setting that specifies whether automatic click when the mouse pointer stops moving is
@@ -10897,6 +10915,15 @@
private static final Validator LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR =
new SettingsValidators.InclusiveIntegerRangeValidator(0, 100);
+
+ /**
+ * The max value for {@link #LOW_POWER_MODE_TRIGGER_LEVEL}. If this setting is not set
+ * or the value is 0, the default max will be used.
+ *
+ * @hide
+ */
+ public static final String LOW_POWER_MODE_TRIGGER_LEVEL_MAX = "low_power_trigger_level_max";
+
/**
* If not 0, the activity manager will aggressively finish activities and
* processes as soon as they are no longer needed. If 0, the normal
@@ -11168,6 +11195,20 @@
public static final String ZEN_MODE_CONFIG_ETAG = "zen_mode_config_etag";
/**
+ * If 0, turning on dnd manually will last indefinitely.
+ * Else if non-negative, turning on dnd manually will last for this many minutes.
+ * Else (if negative), turning on dnd manually will surface a dialog that prompts
+ * user to specify a duration.
+ * @hide
+ */
+ public static final String ZEN_DURATION = "zen_duration";
+
+ private static final Validator ZEN_DURATION_VALIDATOR = ANY_INTEGER_VALIDATOR;
+
+ /** @hide */ public static final int ZEN_DURATION_PROMPT = -1;
+ /** @hide */ public static final int ZEN_DURATION_FOREVER = 0;
+
+ /**
* Defines global heads up toggle. One of HEADS_UP_OFF, HEADS_UP_ON.
*
* @hide
@@ -11483,7 +11524,14 @@
/**
* The packages whitelisted to be run in autofill compatibility mode. The list
- * of packages is ":" colon delimited.
+ * of packages is {@code ":"} colon delimited, and each entry has the name of the
+ * package and an optional list of url bar resource ids (the list is delimited by
+ * brackets&mdash{@code [} and {@code ]}&mdash and is also comma delimited).
+ *
+ * <p>For example, a list with 3 packages {@code p1}, {@code p2}, and {@code p3}, where
+ * package {@code p1} have one id ({@code url_bar}, {@code p2} has none, and {@code p3 }
+ * have 2 ids {@code url_foo} and {@code url_bas}) would be
+ * {@code p1[url_bar]:p2:p3[url_foo,url_bas]}
*
* @hide
*/
@@ -11541,7 +11589,8 @@
BLUETOOTH_ON,
PRIVATE_DNS_MODE,
PRIVATE_DNS_SPECIFIER,
- SOFT_AP_TIMEOUT_ENABLED
+ SOFT_AP_TIMEOUT_ENABLED,
+ ZEN_DURATION,
};
/**
@@ -11573,6 +11622,8 @@
VALIDATORS.put(DOCK_AUDIO_MEDIA_ENABLED, DOCK_AUDIO_MEDIA_ENABLED_VALIDATOR);
VALIDATORS.put(ENCODED_SURROUND_OUTPUT, ENCODED_SURROUND_OUTPUT_VALIDATOR);
VALIDATORS.put(LOW_POWER_MODE_TRIGGER_LEVEL, LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR);
+ VALIDATORS.put(LOW_POWER_MODE_TRIGGER_LEVEL_MAX,
+ LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR);
VALIDATORS.put(BLUETOOTH_ON, BLUETOOTH_ON_VALIDATOR);
VALIDATORS.put(PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_VALIDATOR);
VALIDATORS.put(PRIVATE_DNS_SPECIFIER, PRIVATE_DNS_SPECIFIER_VALIDATOR);
@@ -11580,6 +11631,7 @@
VALIDATORS.put(WIFI_CARRIER_NETWORKS_AVAILABLE_NOTIFICATION_ON,
WIFI_CARRIER_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR);
VALIDATORS.put(APP_AUTO_RESTRICTION_ENABLED, APP_AUTO_RESTRICTION_ENABLED_VALIDATOR);
+ VALIDATORS.put(ZEN_DURATION, ZEN_DURATION_VALIDATOR);
}
/**
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index c568b6f..140336e 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -49,7 +49,8 @@
* </ul>
*
* <P> The minimum permission needed to access this content provider is
- * {@link android.Manifest.permission#ADD_VOICEMAIL}
+ * {@link android.Manifest.permission#ADD_VOICEMAIL} or carrier privileges (see
+ * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}).
*
* <P>Voicemails are inserted by what is called as a "voicemail source"
* application, which is responsible for syncing voicemail data between a remote
diff --git a/core/java/android/se/omapi/Session.java b/core/java/android/se/omapi/Session.java
index 19a018e..3d8b74b 100644
--- a/core/java/android/se/omapi/Session.java
+++ b/core/java/android/se/omapi/Session.java
@@ -301,12 +301,6 @@
* provide a new logical channel.
*/
public @Nullable Channel openLogicalChannel(byte[] aid, byte p2) throws IOException {
-
- if ((mReader.getName().startsWith("SIM")) && (aid == null)) {
- Log.e(TAG, "NULL AID not supported on " + mReader.getName());
- return null;
- }
-
if (!mService.isConnected()) {
throw new IllegalStateException("service not connected to system");
}
diff --git a/core/java/android/service/autofill/AutofillServiceInfo.java b/core/java/android/service/autofill/AutofillServiceInfo.java
index 70c4ec0..de23455 100644
--- a/core/java/android/service/autofill/AutofillServiceInfo.java
+++ b/core/java/android/service/autofill/AutofillServiceInfo.java
@@ -32,7 +32,6 @@
import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.Log;
-import android.util.Pair;
import android.util.Xml;
import com.android.internal.R;
@@ -79,7 +78,7 @@
private final String mSettingsActivity;
@Nullable
- private final ArrayMap<String, Pair<Long, String>> mCompatibilityPackages;
+ private final ArrayMap<String, Long> mCompatibilityPackages;
public AutofillServiceInfo(Context context, ComponentName comp, int userHandle)
throws PackageManager.NameNotFoundException {
@@ -117,7 +116,7 @@
}
String settingsActivity = null;
- ArrayMap<String, Pair<Long, String>> compatibilityPackages = null;
+ ArrayMap<String, Long> compatibilityPackages = null;
try {
final Resources resources = context.getPackageManager().getResourcesForApplication(
@@ -153,10 +152,9 @@
mCompatibilityPackages = compatibilityPackages;
}
- private ArrayMap<String, Pair<Long, String>> parseCompatibilityPackages(XmlPullParser parser,
- Resources resources)
- throws IOException, XmlPullParserException {
- ArrayMap<String, Pair<Long, String>> compatibilityPackages = null;
+ private ArrayMap<String, Long> parseCompatibilityPackages(XmlPullParser parser,
+ Resources resources) throws IOException, XmlPullParserException {
+ ArrayMap<String, Long> compatibilityPackages = null;
final int outerDepth = parser.getDepth();
int type;
@@ -200,13 +198,18 @@
} else {
maxVersionCode = Long.MAX_VALUE;
}
- final String urlBarResourceId = cpAttributes.getString(
- R.styleable.AutofillService_CompatibilityPackage_urlBarResourceId);
+ if (true) { // TODO(b/74445943): remove block after P DP2 is branched
+ final String urlBarResourceId = cpAttributes.getString(
+ R.styleable.AutofillService_CompatibilityPackage_urlBarResourceId);
+ if (urlBarResourceId != null) {
+ Log.e(TAG, "Service is using deprecated attribute 'urlBarResourceId'");
+ }
+ }
if (compatibilityPackages == null) {
compatibilityPackages = new ArrayMap<>();
}
- compatibilityPackages.put(name, new Pair<>(maxVersionCode, urlBarResourceId));
+ compatibilityPackages.put(name, maxVersionCode);
} finally {
XmlUtils.skipCurrentTag(parser);
if (cpAttributes != null) {
@@ -228,23 +231,10 @@
return mSettingsActivity;
}
- public ArrayMap<String, Pair<Long, String>> getCompatibilityPackages() {
+ public ArrayMap<String, Long> getCompatibilityPackages() {
return mCompatibilityPackages;
}
- /**
- * Gets the resource id of the URL bar for a package. Used in compat mode
- */
- // TODO: return a list of strings instead
- @Nullable
- public String getUrlBarResourceId(String packageName) {
- if (mCompatibilityPackages == null) {
- return null;
- }
- final Pair<Long, String> pair = mCompatibilityPackages.get(packageName);
- return pair == null ? null : pair.second;
- }
-
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index eebd22a..ea10ae7 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -149,13 +149,19 @@
/**
* Whether notification suppressed by DND should not interruption visually when the screen is
* off.
+ *
+ * @deprecated Use the more specific visual effects in {@link NotificationManager.Policy}.
*/
+ @Deprecated
public static final int SUPPRESSED_EFFECT_SCREEN_OFF =
NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
/**
* Whether notification suppressed by DND should not interruption visually when the screen is
* on.
+ *
+ * @deprecated Use the more specific visual effects in {@link NotificationManager.Policy}.
*/
+ @Deprecated
public static final int SUPPRESSED_EFFECT_SCREEN_ON =
NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
@@ -1453,7 +1459,8 @@
/**
* Returns the type(s) of visual effects that should be suppressed for this notification.
- * See {@link #SUPPRESSED_EFFECT_SCREEN_OFF}, {@link #SUPPRESSED_EFFECT_SCREEN_ON}.
+ * See {@link NotificationManager.Policy}, e.g.
+ * {@link NotificationManager.Policy#SUPPRESSED_EFFECT_LIGHTS}.
*/
public int getSuppressedVisualEffects() {
return mSuppressedVisualEffects;
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index b61919e..740a387 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -92,10 +92,12 @@
private static final boolean DEFAULT_ALLOW_REMINDERS = false;
private static final boolean DEFAULT_ALLOW_EVENTS = false;
private static final boolean DEFAULT_ALLOW_REPEAT_CALLERS = false;
- private static final boolean DEFAULT_ALLOW_SCREEN_OFF = true;
- private static final boolean DEFAULT_ALLOW_SCREEN_ON = true;
+ private static final boolean DEFAULT_ALLOW_SCREEN_OFF = false;
+ private static final boolean DEFAULT_ALLOW_SCREEN_ON = false;
+ private static final int DEFAULT_SUPPRESSED_VISUAL_EFFECTS =
+ Policy.getAllSuppressedVisualEffects();
- public static final int XML_VERSION = 4;
+ public static final int XML_VERSION = 5;
public static final String ZEN_TAG = "zen";
private static final String ZEN_ATT_VERSION = "version";
private static final String ZEN_ATT_USER = "user";
@@ -113,6 +115,8 @@
private static final String ALLOW_ATT_EVENTS = "events";
private static final String ALLOW_ATT_SCREEN_OFF = "visualScreenOff";
private static final String ALLOW_ATT_SCREEN_ON = "visualScreenOn";
+ private static final String DISALLOW_TAG = "disallow";
+ private static final String DISALLOW_ATT_VISUAL_EFFECTS = "visualEffects";
private static final String CONDITION_ATT_ID = "id";
private static final String CONDITION_ATT_SUMMARY = "summary";
@@ -146,6 +150,7 @@
public int allowCallsFrom = DEFAULT_SOURCE;
public int allowMessagesFrom = DEFAULT_SOURCE;
public int user = UserHandle.USER_SYSTEM;
+ public int suppressedVisualEffects = DEFAULT_SUPPRESSED_VISUAL_EFFECTS;
public boolean allowWhenScreenOff = DEFAULT_ALLOW_SCREEN_OFF;
public boolean allowWhenScreenOn = DEFAULT_ALLOW_SCREEN_ON;
public int version;
@@ -180,6 +185,7 @@
allowAlarms = source.readInt() == 1;
allowMedia = source.readInt() == 1;
allowSystem = source.readInt() == 1;
+ suppressedVisualEffects = source.readInt();
}
@Override
@@ -212,6 +218,7 @@
dest.writeInt(allowAlarms ? 1 : 0);
dest.writeInt(allowMedia ? 1 : 0);
dest.writeInt(allowSystem ? 1 : 0);
+ dest.writeInt(suppressedVisualEffects);
}
@Override
@@ -230,6 +237,7 @@
.append(",allowMessagesFrom=").append(sourceToString(allowMessagesFrom))
.append(",allowWhenScreenOff=").append(allowWhenScreenOff)
.append(",allowWhenScreenOn=").append(allowWhenScreenOn)
+ .append(",suppressedVisualEffects=").append(suppressedVisualEffects)
.append(",automaticRules=").append(automaticRules)
.append(",manualRule=").append(manualRule)
.append(']').toString();
@@ -279,6 +287,10 @@
if (allowWhenScreenOn != to.allowWhenScreenOn) {
d.addLine("allowWhenScreenOn", allowWhenScreenOn, to.allowWhenScreenOn);
}
+ if (suppressedVisualEffects != to.suppressedVisualEffects) {
+ d.addLine("suppressedVisualEffects", suppressedVisualEffects,
+ to.suppressedVisualEffects);
+ }
final ArraySet<String> allRules = new ArraySet<>();
addKeys(allRules, automaticRules);
addKeys(allRules, to.automaticRules);
@@ -383,7 +395,8 @@
&& other.allowWhenScreenOn == allowWhenScreenOn
&& other.user == user
&& Objects.equals(other.automaticRules, automaticRules)
- && Objects.equals(other.manualRule, manualRule);
+ && Objects.equals(other.manualRule, manualRule)
+ && other.suppressedVisualEffects == suppressedVisualEffects;
}
@Override
@@ -391,7 +404,8 @@
return Objects.hash(allowAlarms, allowMedia, allowSystem, allowCalls,
allowRepeatCallers, allowMessages,
allowCallsFrom, allowMessagesFrom, allowReminders, allowEvents,
- allowWhenScreenOff, allowWhenScreenOn, user, automaticRules, manualRule);
+ allowWhenScreenOff, allowWhenScreenOn, user, automaticRules, manualRule,
+ suppressedVisualEffects);
}
private static String toDayList(int[] days) {
@@ -474,6 +488,8 @@
rt.allowCallsFrom = DEFAULT_SOURCE;
rt.allowMessagesFrom = DEFAULT_SOURCE;
}
+ // continue to read even though we now have suppressedVisualEffects, in case
+ // we need to revert to users' previous settings
rt.allowWhenScreenOff =
safeBoolean(parser, ALLOW_ATT_SCREEN_OFF, DEFAULT_ALLOW_SCREEN_OFF);
rt.allowWhenScreenOn =
@@ -482,6 +498,9 @@
rt.allowMedia = safeBoolean(parser, ALLOW_ATT_MEDIA,
DEFAULT_ALLOW_MEDIA);
rt.allowSystem = safeBoolean(parser, ALLOW_ATT_SYSTEM, DEFAULT_ALLOW_SYSTEM);
+ } else if (DISALLOW_TAG.equals(tag)) {
+ rt.suppressedVisualEffects = safeInt(parser, DISALLOW_ATT_VISUAL_EFFECTS,
+ DEFAULT_SUPPRESSED_VISUAL_EFFECTS);
} else if (MANUAL_TAG.equals(tag)) {
rt.manualRule = readRuleXml(parser);
} else if (AUTOMATIC_TAG.equals(tag)) {
@@ -517,6 +536,10 @@
out.attribute(null, ALLOW_ATT_SYSTEM, Boolean.toString(allowSystem));
out.endTag(null, ALLOW_TAG);
+ out.startTag(null, DISALLOW_TAG);
+ out.attribute(null, DISALLOW_ATT_VISUAL_EFFECTS, Integer.toString(suppressedVisualEffects));
+ out.endTag(null, DISALLOW_TAG);
+
if (manualRule != null) {
out.startTag(null, MANUAL_TAG);
writeRuleXml(manualRule, out);
@@ -701,13 +724,6 @@
if (allowRepeatCallers) {
priorityCategories |= Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
}
- int suppressedVisualEffects = 0;
- if (!allowWhenScreenOff) {
- suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
- }
- if (!allowWhenScreenOn) {
- suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_SCREEN_ON;
- }
if (allowAlarms) {
priorityCategories |= Policy.PRIORITY_CATEGORY_ALARMS;
}
@@ -770,10 +786,7 @@
allowMessagesFrom = prioritySendersToSource(policy.priorityMessageSenders,
allowMessagesFrom);
if (policy.suppressedVisualEffects != Policy.SUPPRESSED_EFFECTS_UNSET) {
- allowWhenScreenOff =
- (policy.suppressedVisualEffects & Policy.SUPPRESSED_EFFECT_SCREEN_OFF) == 0;
- allowWhenScreenOn =
- (policy.suppressedVisualEffects & Policy.SUPPRESSED_EFFECT_SCREEN_ON) == 0;
+ suppressedVisualEffects = policy.suppressedVisualEffects;
}
}
diff --git a/core/java/android/service/textclassifier/ITextClassifierService.aidl b/core/java/android/service/textclassifier/ITextClassifierService.aidl
index d2ffe34..25e9d45 100644
--- a/core/java/android/service/textclassifier/ITextClassifierService.aidl
+++ b/core/java/android/service/textclassifier/ITextClassifierService.aidl
@@ -19,13 +19,14 @@
import android.service.textclassifier.ITextClassificationCallback;
import android.service.textclassifier.ITextLinksCallback;
import android.service.textclassifier.ITextSelectionCallback;
+import android.view.textclassifier.SelectionEvent;
import android.view.textclassifier.TextClassification;
import android.view.textclassifier.TextLinks;
import android.view.textclassifier.TextSelection;
/**
* TextClassifierService binder interface.
- * See TextClassifier for interface documentation.
+ * See TextClassifier (and TextClassifier.Logger) for interface documentation.
* {@hide}
*/
oneway interface ITextClassifierService {
@@ -44,4 +45,6 @@
in CharSequence text,
in TextLinks.Options options,
in ITextLinksCallback c);
+
+ void onSelectionEvent(in SelectionEvent event);
}
diff --git a/core/java/android/service/textclassifier/TextClassifierService.java b/core/java/android/service/textclassifier/TextClassifierService.java
index 2c8c4ec..88e29b0 100644
--- a/core/java/android/service/textclassifier/TextClassifierService.java
+++ b/core/java/android/service/textclassifier/TextClassifierService.java
@@ -33,7 +33,9 @@
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Slog;
+import android.view.textclassifier.SelectionEvent;
import android.view.textclassifier.TextClassification;
+import android.view.textclassifier.TextClassificationManager;
import android.view.textclassifier.TextClassifier;
import android.view.textclassifier.TextLinks;
import android.view.textclassifier.TextSelection;
@@ -47,7 +49,7 @@
* {@link android.view.textclassifier.TextClassifierImpl} is loaded in the calling app's process.
*
* <p>See: {@link TextClassifier}.
- * See: {@link android.view.textclassifier.TextClassificationManager}.
+ * See: {@link TextClassificationManager}.
*
* <p>Include the following in the manifest:
*
@@ -170,6 +172,12 @@
}
});
}
+
+ /** {@inheritDoc} */
+ @Override
+ public void onSelectionEvent(SelectionEvent event) throws RemoteException {
+ TextClassifierService.this.onSelectionEvent(event);
+ }
};
@Nullable
@@ -237,6 +245,27 @@
@NonNull Callback<TextLinks> callback);
/**
+ * Writes the selection event.
+ * This is called when a selection event occurs. e.g. user changed selection; or smart selection
+ * happened.
+ *
+ * <p>The default implementation ignores the event.
+ */
+ public void onSelectionEvent(@NonNull SelectionEvent event) {}
+
+ /**
+ * Returns a TextClassifier that runs in this service's process.
+ * If the local TextClassifier is disabled, this returns {@link TextClassifier#NO_OP}.
+ */
+ public final TextClassifier getLocalTextClassifier() {
+ final TextClassificationManager tcm = getSystemService(TextClassificationManager.class);
+ if (tcm != null) {
+ return tcm.getTextClassifier(TextClassifier.LOCAL);
+ }
+ return TextClassifier.NO_OP;
+ }
+
+ /**
* Callbacks for TextClassifierService results.
*
* @param <T> the type of the result
diff --git a/core/java/android/util/KeyValueSettingObserver.java b/core/java/android/util/KeyValueSettingObserver.java
new file mode 100644
index 0000000..9fca8b2
--- /dev/null
+++ b/core/java/android/util/KeyValueSettingObserver.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2018 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.util;
+
+import android.content.ContentResolver;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+
+/**
+ * Abstract class for observing changes to a specified setting stored as a comma-separated key value
+ * list of parameters. Registers and unregisters a {@link ContentObserver} and handles updates when
+ * the setting changes.
+ *
+ * <p>Subclasses should pass in the relevant setting's {@link Uri} in the constructor and implement
+ * {@link #update(KeyValueListParser)} to receive updates when the value changes.
+ * Calls to {@link #update(KeyValueListParser)} only trigger after calling {@link
+ * #start()}.
+ *
+ * <p>To get the most up-to-date parameter values, first call {@link #start()} before accessing the
+ * values to start observing changes, and then call {@link #stop()} once finished.
+ *
+ * @hide
+ */
+public abstract class KeyValueSettingObserver {
+ private static final String TAG = "KeyValueSettingObserver";
+
+ private final KeyValueListParser mParser = new KeyValueListParser(',');
+
+ private final ContentObserver mObserver;
+ private final ContentResolver mResolver;
+ private final Uri mSettingUri;
+
+ public KeyValueSettingObserver(Handler handler, ContentResolver resolver,
+ Uri uri) {
+ mObserver = new SettingObserver(handler);
+ mResolver = resolver;
+ mSettingUri = uri;
+ }
+
+ /** Starts observing changes for the setting. Pair with {@link #stop()}. */
+ public void start() {
+ mResolver.registerContentObserver(mSettingUri, false, mObserver);
+ setParserValue();
+ update(mParser);
+ }
+
+ /** Stops observing changes for the setting. */
+ public void stop() {
+ mResolver.unregisterContentObserver(mObserver);
+ }
+
+ /**
+ * Returns the {@link String} representation of the setting. Subclasses should implement this
+ * for their setting.
+ */
+ public abstract String getSettingValue(ContentResolver resolver);
+
+ /** Updates the parser with the current setting value. */
+ private void setParserValue() {
+ String setting = getSettingValue(mResolver);
+ try {
+ mParser.setString(setting);
+ } catch (IllegalArgumentException e) {
+ Slog.e(TAG, "Malformed setting: " + setting);
+ }
+ }
+
+ /** Subclasses should implement this to update references to their parameters. */
+ public abstract void update(KeyValueListParser parser);
+
+ private class SettingObserver extends ContentObserver {
+ private SettingObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ setParserValue();
+ update(mParser);
+ }
+ }
+}
diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java
index bb16afd..b6adee9 100644
--- a/core/java/android/view/DisplayCutout.java
+++ b/core/java/android/view/DisplayCutout.java
@@ -18,10 +18,6 @@
import static android.view.DisplayCutoutProto.BOUNDS;
import static android.view.DisplayCutoutProto.INSETS;
-import static android.view.Surface.ROTATION_0;
-import static android.view.Surface.ROTATION_180;
-import static android.view.Surface.ROTATION_270;
-import static android.view.Surface.ROTATION_90;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
@@ -36,23 +32,24 @@
import android.text.TextUtils;
import android.util.Log;
import android.util.PathParser;
-import android.util.Size;
import android.util.proto.ProtoOutputStream;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import java.util.Objects;
+import java.util.ArrayList;
+import java.util.List;
/**
- * Represents a part of the display that is not functional for displaying content.
+ * Represents the area of the display that is not functional for displaying content.
*
* <p>{@code DisplayCutout} is immutable.
*/
public final class DisplayCutout {
private static final String TAG = "DisplayCutout";
+ private static final String BOTTOM_MARKER = "@bottom";
private static final String DP_MARKER = "@dp";
/**
@@ -74,7 +71,7 @@
* @hide
*/
public static final DisplayCutout NO_CUTOUT = new DisplayCutout(ZERO_RECT, EMPTY_REGION,
- new Size(0, 0));
+ false /* copyArguments */);
private static final Object CACHE_LOCK = new Object();
@@ -89,38 +86,38 @@
private final Rect mSafeInsets;
private final Region mBounds;
- private final Size mFrameSize; // TODO: move frameSize, calculateRelativeTo, etc. into WM.
/**
* Creates a DisplayCutout instance.
*
* @param safeInsets the insets from each edge which avoid the display cutout as returned by
* {@link #getSafeInsetTop()} etc.
- * @param bounds the bounds of the display cutout as returned by {@link #getBounds()}.
+ * @param boundingRects the bounding rects of the display cutouts as returned by
+ * {@link #getBoundingRects()} ()}.
*/
// TODO(b/73953958): @VisibleForTesting(visibility = PRIVATE)
- public DisplayCutout(Rect safeInsets, Region bounds) {
+ public DisplayCutout(Rect safeInsets, List<Rect> boundingRects) {
this(safeInsets != null ? new Rect(safeInsets) : ZERO_RECT,
- bounds != null ? Region.obtain(bounds) : Region.obtain(),
- null /* frameSize */);
+ boundingRectsToRegion(boundingRects),
+ true /* copyArguments */);
}
/**
* Creates a DisplayCutout instance.
*
- * NOTE: the Rects passed into this instance are not copied and MUST remain unchanged.
- *
- * @hide
+ * @param copyArguments if true, create a copy of the arguments. If false, the passed arguments
+ * are not copied and MUST remain unchanged forever.
*/
- @VisibleForTesting
- public DisplayCutout(Rect safeInsets, Region bounds, Size frameSize) {
- mSafeInsets = safeInsets != null ? safeInsets : ZERO_RECT;
- mBounds = bounds != null ? bounds : Region.obtain();
- mFrameSize = frameSize;
+ private DisplayCutout(Rect safeInsets, Region bounds, boolean copyArguments) {
+ mSafeInsets = safeInsets == null ? ZERO_RECT :
+ (copyArguments ? new Rect(safeInsets) : safeInsets);
+ mBounds = bounds == null ? Region.obtain() :
+ (copyArguments ? Region.obtain(bounds) : bounds);
}
/**
- * Returns true if there is no cutout or it is outside of the content view.
+ * Returns true if the safe insets are empty (and therefore the current view does not
+ * overlap with the cutout or cutout area).
*
* @hide
*/
@@ -128,6 +125,15 @@
return mSafeInsets.equals(ZERO_RECT);
}
+ /**
+ * Returns true if there is no cutout, i.e. the bounds are empty.
+ *
+ * @hide
+ */
+ public boolean isBoundsEmpty() {
+ return mBounds.isEmpty();
+ }
+
/** Returns the inset from the top which avoids the display cutout in pixels. */
public int getSafeInsetTop() {
return mSafeInsets.top;
@@ -161,23 +167,60 @@
/**
* Returns the bounding region of the cutout.
*
+ * <p>
+ * <strong>Note:</strong> There may be more than one cutout, in which case the returned
+ * {@code Region} will be non-contiguous and its bounding rect will be meaningless without
+ * intersecting it first.
+ *
+ * Example:
+ * <pre>
+ * // Getting the bounding rectangle of the top display cutout
+ * Region bounds = displayCutout.getBounds();
+ * bounds.op(0, 0, Integer.MAX_VALUE, displayCutout.getSafeInsetTop(), Region.Op.INTERSECT);
+ * Rect topDisplayCutout = bounds.getBoundingRect();
+ * </pre>
+ *
* @return the bounding region of the cutout. Coordinates are relative
* to the top-left corner of the content view and in pixel units.
+ * @hide
*/
public Region getBounds() {
return Region.obtain(mBounds);
}
/**
- * Returns the bounding rect of the cutout.
+ * Returns a list of {@code Rect}s, each of which is the bounding rectangle for a non-functional
+ * area on the display.
*
- * @return the bounding rect of the cutout. Coordinates are relative
- * to the top-left corner of the content view.
- * @hide
+ * There will be at most one non-functional area per short edge of the device, and none on
+ * the long edges.
+ *
+ * @return a list of bounding {@code Rect}s, one for each display cutout area.
*/
- public Rect getBoundingRect() {
- // TODO(roosa): Inline.
- return mBounds.getBounds();
+ public List<Rect> getBoundingRects() {
+ List<Rect> result = new ArrayList<>();
+ Region bounds = Region.obtain();
+ // top
+ bounds.set(mBounds);
+ bounds.op(0, 0, Integer.MAX_VALUE, getSafeInsetTop(), Region.Op.INTERSECT);
+ if (!bounds.isEmpty()) {
+ result.add(bounds.getBounds());
+ }
+ // left
+ bounds.set(mBounds);
+ bounds.op(0, 0, getSafeInsetLeft(), Integer.MAX_VALUE, Region.Op.INTERSECT);
+ if (!bounds.isEmpty()) {
+ result.add(bounds.getBounds());
+ }
+ // right & bottom
+ bounds.set(mBounds);
+ bounds.op(getSafeInsetLeft() + 1, getSafeInsetTop() + 1,
+ Integer.MAX_VALUE, Integer.MAX_VALUE, Region.Op.INTERSECT);
+ if (!bounds.isEmpty()) {
+ result.add(bounds.getBounds());
+ }
+ bounds.recycle();
+ return result;
}
@Override
@@ -195,8 +238,7 @@
if (o instanceof DisplayCutout) {
DisplayCutout c = (DisplayCutout) o;
return mSafeInsets.equals(c.mSafeInsets)
- && mBounds.equals(c.mBounds)
- && Objects.equals(mFrameSize, c.mFrameSize);
+ && mBounds.equals(c.mBounds);
}
return false;
}
@@ -204,7 +246,7 @@
@Override
public String toString() {
return "DisplayCutout{insets=" + mSafeInsets
- + " boundingRect=" + getBoundingRect()
+ + " boundingRect=" + mBounds.getBounds()
+ "}";
}
@@ -249,88 +291,19 @@
}
bounds.translate(-insetLeft, -insetTop);
- Size frame = mFrameSize == null ? null : new Size(
- mFrameSize.getWidth() - insetLeft - insetRight,
- mFrameSize.getHeight() - insetTop - insetBottom);
-
- return new DisplayCutout(safeInsets, bounds, frame);
+ return new DisplayCutout(safeInsets, bounds, false /* copyArguments */);
}
/**
- * Recalculates the cutout relative to the given reference frame.
+ * Returns a copy of this instance with the safe insets replaced with the parameter.
*
- * The safe insets must already have been computed, e.g. with {@link #computeSafeInsets}.
+ * @param safeInsets the new safe insets in pixels
+ * @return a copy of this instance with the safe insets replaced with the argument.
*
- * @return a copy of this instance with the safe insets recalculated
* @hide
*/
- public DisplayCutout calculateRelativeTo(Rect frame) {
- return inset(frame.left, frame.top,
- mFrameSize.getWidth() - frame.right, mFrameSize.getHeight() - frame.bottom);
- }
-
- /**
- * Calculates the safe insets relative to the given display size.
- *
- * @return a copy of this instance with the safe insets calculated
- * @hide
- */
- public DisplayCutout computeSafeInsets(int width, int height) {
- if (this == NO_CUTOUT || mBounds.isEmpty()) {
- return NO_CUTOUT;
- }
-
- return computeSafeInsets(new Size(width, height), mBounds);
- }
-
- private static DisplayCutout computeSafeInsets(Size displaySize, Region bounds) {
- Rect boundingRect = bounds.getBounds();
- Rect safeRect = new Rect();
-
- int bestArea = 0;
- int bestVariant = 0;
- for (int variant = ROTATION_0; variant <= ROTATION_270; variant++) {
- int area = calculateInsetVariantArea(displaySize, boundingRect, variant, safeRect);
- if (bestArea < area) {
- bestArea = area;
- bestVariant = variant;
- }
- }
- calculateInsetVariantArea(displaySize, boundingRect, bestVariant, safeRect);
- if (safeRect.isEmpty()) {
- // The entire displaySize overlaps with the cutout.
- safeRect.set(0, displaySize.getHeight(), 0, 0);
- } else {
- // Convert safeRect to insets relative to displaySize. We're reusing the rect here to
- // avoid an allocation.
- safeRect.set(
- Math.max(0, safeRect.left),
- Math.max(0, safeRect.top),
- Math.max(0, displaySize.getWidth() - safeRect.right),
- Math.max(0, displaySize.getHeight() - safeRect.bottom));
- }
-
- return new DisplayCutout(safeRect, bounds, displaySize);
- }
-
- private static int calculateInsetVariantArea(Size display, Rect boundingRect, int variant,
- Rect outSafeRect) {
- switch (variant) {
- case ROTATION_0:
- outSafeRect.set(0, 0, display.getWidth(), boundingRect.top);
- break;
- case ROTATION_90:
- outSafeRect.set(0, 0, boundingRect.left, display.getHeight());
- break;
- case ROTATION_180:
- outSafeRect.set(0, boundingRect.bottom, display.getWidth(), display.getHeight());
- break;
- case ROTATION_270:
- outSafeRect.set(boundingRect.right, 0, display.getWidth(), display.getHeight());
- break;
- }
-
- return outSafeRect.isEmpty() ? 0 : outSafeRect.width() * outSafeRect.height();
+ public DisplayCutout replaceSafeInsets(Rect safeInsets) {
+ return new DisplayCutout(new Rect(safeInsets), mBounds, false /* copyArguments */);
}
private static int atLeastZero(int value) {
@@ -369,7 +342,7 @@
Region bounds = new Region();
bounds.setPath(path, clipRegion);
clipRegion.recycle();
- return new DisplayCutout(ZERO_RECT, bounds, null /* frameSize */);
+ return new DisplayCutout(ZERO_RECT, bounds, false /* copyArguments */);
}
/**
@@ -377,9 +350,9 @@
*
* @hide
*/
- public static DisplayCutout fromResources(Resources res, int displayWidth) {
+ public static DisplayCutout fromResources(Resources res, int displayWidth, int displayHeight) {
return fromSpec(res.getString(R.string.config_mainBuiltInDisplayCutout),
- displayWidth, res.getDisplayMetrics().density);
+ displayWidth, displayHeight, res.getDisplayMetrics().density);
}
/**
@@ -388,7 +361,8 @@
* @hide
*/
@VisibleForTesting(visibility = PRIVATE)
- public static DisplayCutout fromSpec(String spec, int displayWidth, float density) {
+ public static DisplayCutout fromSpec(String spec, int displayWidth, int displayHeight,
+ float density) {
if (TextUtils.isEmpty(spec)) {
return null;
}
@@ -404,7 +378,14 @@
spec = spec.substring(0, spec.length() - DP_MARKER.length());
}
- Path p;
+ String bottomSpec = null;
+ if (spec.contains(BOTTOM_MARKER)) {
+ String[] splits = spec.split(BOTTOM_MARKER, 2);
+ spec = splits[0].trim();
+ bottomSpec = splits[1].trim();
+ }
+
+ final Path p;
try {
p = PathParser.createPathFromPathData(spec);
} catch (Throwable e) {
@@ -419,6 +400,20 @@
m.postTranslate(displayWidth / 2f, 0);
p.transform(m);
+ if (bottomSpec != null) {
+ final Path bottomPath;
+ try {
+ bottomPath = PathParser.createPathFromPathData(bottomSpec);
+ } catch (Throwable e) {
+ Log.wtf(TAG, "Could not inflate bottom cutout: ", e);
+ return null;
+ }
+ // Keep top transform
+ m.postTranslate(0, displayHeight);
+ bottomPath.transform(m);
+ p.addPath(bottomPath);
+ }
+
final DisplayCutout result = fromBounds(p);
synchronized (CACHE_LOCK) {
sCachedSpec = spec;
@@ -429,6 +424,16 @@
return result;
}
+ private static Region boundingRectsToRegion(List<Rect> rects) {
+ Region result = Region.obtain();
+ if (rects != null) {
+ for (Rect r : rects) {
+ result.op(r, Region.Op.UNION);
+ }
+ }
+ return result;
+ }
+
/**
* Helper class for passing {@link DisplayCutout} through binder.
*
@@ -472,12 +477,6 @@
out.writeInt(1);
out.writeTypedObject(cutout.mSafeInsets, flags);
out.writeTypedObject(cutout.mBounds, flags);
- if (cutout.mFrameSize != null) {
- out.writeInt(cutout.mFrameSize.getWidth());
- out.writeInt(cutout.mFrameSize.getHeight());
- } else {
- out.writeInt(-1);
- }
}
}
@@ -520,10 +519,7 @@
Rect safeInsets = in.readTypedObject(Rect.CREATOR);
Region bounds = in.readTypedObject(Region.CREATOR);
- int width = in.readInt();
- Size frameSize = width >= 0 ? new Size(width, in.readInt()) : null;
-
- return new DisplayCutout(safeInsets, bounds, frameSize);
+ return new DisplayCutout(safeInsets, bounds, false /* copyArguments */);
}
public DisplayCutout get() {
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index 5607b11..89684ca 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -51,4 +51,12 @@
* and then enable it mid-animation to start receiving touch events.
*/
void setInputConsumerEnabled(boolean enabled);
+
+ /**
+ * Informs the system whether the animation targets passed into
+ * IRecentsAnimationRunner.onAnimationStart are currently behind the system bars. If they are,
+ * they can control the SystemUI flags, otherwise the SystemUI flags from home activity will be
+ * taken.
+ */
+ void setAnimationTargetsBehindSystemBars(boolean behindSystemBars);
}
diff --git a/core/java/android/view/RemoteAnimationAdapter.java b/core/java/android/view/RemoteAnimationAdapter.java
index d597e59..a864e55 100644
--- a/core/java/android/view/RemoteAnimationAdapter.java
+++ b/core/java/android/view/RemoteAnimationAdapter.java
@@ -52,6 +52,9 @@
private final long mDuration;
private final long mStatusBarTransitionDelay;
+ /** @see #getCallingPid */
+ private int mCallingPid;
+
/**
* @param runner The interface that gets notified when we actually need to start the animation.
* @param duration The duration of the animation.
@@ -83,6 +86,20 @@
return mStatusBarTransitionDelay;
}
+ /**
+ * To be called by system_server to keep track which pid is running this animation.
+ */
+ public void setCallingPid(int pid) {
+ mCallingPid = pid;
+ }
+
+ /**
+ * @return The pid of the process running the animation.
+ */
+ public int getCallingPid() {
+ return mCallingPid;
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/core/java/android/view/RemoteAnimationDefinition.java b/core/java/android/view/RemoteAnimationDefinition.java
index 381f692..8def435 100644
--- a/core/java/android/view/RemoteAnimationDefinition.java
+++ b/core/java/android/view/RemoteAnimationDefinition.java
@@ -70,6 +70,16 @@
mTransitionAnimationMap = in.readSparseArray(null /* loader */);
}
+ /**
+ * To be called by system_server to keep track which pid is running the remote animations inside
+ * this definition.
+ */
+ public void setCallingPid(int pid) {
+ for (int i = mTransitionAnimationMap.size() - 1; i >= 0; i--) {
+ mTransitionAnimationMap.valueAt(i).setCallingPid(pid);
+ }
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/core/java/android/view/RemoteAnimationTarget.java b/core/java/android/view/RemoteAnimationTarget.java
index facf575..5b2cc81 100644
--- a/core/java/android/view/RemoteAnimationTarget.java
+++ b/core/java/android/view/RemoteAnimationTarget.java
@@ -16,13 +16,26 @@
package android.view;
+import static android.app.RemoteAnimationTargetProto.CLIP_RECT;
+import static android.app.RemoteAnimationTargetProto.CONTENT_INSETS;
+import static android.app.RemoteAnimationTargetProto.IS_TRANSLUCENT;
+import static android.app.RemoteAnimationTargetProto.LEASH;
+import static android.app.RemoteAnimationTargetProto.MODE;
+import static android.app.RemoteAnimationTargetProto.POSITION;
+import static android.app.RemoteAnimationTargetProto.PREFIX_ORDER_INDEX;
+import static android.app.RemoteAnimationTargetProto.SOURCE_CONTAINER_BOUNDS;
+import static android.app.RemoteAnimationTargetProto.TASK_ID;
+import static android.app.RemoteAnimationTargetProto.WINDOW_CONFIGURATION;
+
import android.annotation.IntDef;
import android.app.WindowConfiguration;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.proto.ProtoOutputStream;
+import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -109,9 +122,14 @@
*/
public final WindowConfiguration windowConfiguration;
+ /**
+ * Whether the task is not presented in Recents UI.
+ */
+ public boolean isNotInRecents;
+
public RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent,
Rect clipRect, Rect contentInsets, int prefixOrderIndex, Point position,
- Rect sourceContainerBounds, WindowConfiguration windowConfig) {
+ Rect sourceContainerBounds, WindowConfiguration windowConfig, boolean isNotInRecents) {
this.mode = mode;
this.taskId = taskId;
this.leash = leash;
@@ -122,6 +140,7 @@
this.position = new Point(position);
this.sourceContainerBounds = new Rect(sourceContainerBounds);
this.windowConfiguration = windowConfig;
+ this.isNotInRecents = isNotInRecents;
}
public RemoteAnimationTarget(Parcel in) {
@@ -135,6 +154,7 @@
position = in.readParcelable(null);
sourceContainerBounds = in.readParcelable(null);
windowConfiguration = in.readParcelable(null);
+ isNotInRecents = in.readBoolean();
}
@Override
@@ -154,6 +174,36 @@
dest.writeParcelable(position, 0 /* flags */);
dest.writeParcelable(sourceContainerBounds, 0 /* flags */);
dest.writeParcelable(windowConfiguration, 0 /* flags */);
+ dest.writeBoolean(isNotInRecents);
+ }
+
+ public void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.print("mode="); pw.print(mode);
+ pw.print(" taskId="); pw.print(taskId);
+ pw.print(" isTranslucent="); pw.print(isTranslucent);
+ pw.print(" clipRect="); clipRect.printShortString(pw);
+ pw.print(" contentInsets="); contentInsets.printShortString(pw);
+ pw.print(" prefixOrderIndex="); pw.print(prefixOrderIndex);
+ pw.print(" position="); position.printShortString(pw);
+ pw.print(" sourceContainerBounds="); sourceContainerBounds.printShortString(pw);
+ pw.println();
+ pw.print(prefix); pw.print("windowConfiguration="); pw.println(windowConfiguration);
+ pw.print(prefix); pw.print("leash="); pw.println(leash);
+ }
+
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+ proto.write(TASK_ID, taskId);
+ proto.write(MODE, mode);
+ leash.writeToProto(proto, LEASH);
+ proto.write(IS_TRANSLUCENT, isTranslucent);
+ clipRect.writeToProto(proto, CLIP_RECT);
+ contentInsets.writeToProto(proto, CONTENT_INSETS);
+ proto.write(PREFIX_ORDER_INDEX, prefixOrderIndex);
+ position.writeToProto(proto, POSITION);
+ sourceContainerBounds.writeToProto(proto, SOURCE_CONTAINER_BOUNDS);
+ windowConfiguration.writeToProto(proto, WINDOW_CONFIGURATION);
+ proto.end(token);
}
public static final Creator<RemoteAnimationTarget> CREATOR
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 8830c90..d3b1e5c 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -396,7 +396,44 @@
synchronized (mLock) {
checkNotReleasedLocked();
if (mHwuiContext == null) {
- mHwuiContext = new HwuiContext();
+ mHwuiContext = new HwuiContext(false);
+ }
+ return mHwuiContext.lockCanvas(
+ nativeGetWidth(mNativeObject),
+ nativeGetHeight(mNativeObject));
+ }
+ }
+
+ /**
+ * Gets a {@link Canvas} for drawing into this surface that supports wide color gamut.
+ *
+ * After drawing into the provided {@link Canvas}, the caller must
+ * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
+ *
+ * Unlike {@link #lockCanvas(Rect)} and {@link #lockHardwareCanvas()},
+ * this will return a hardware-accelerated canvas that supports wide color gamut.
+ * See the <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#unsupported">
+ * unsupported drawing operations</a> for a list of what is and isn't
+ * supported in a hardware-accelerated canvas. It is also required to
+ * fully cover the surface every time {@link #lockHardwareCanvas()} is
+ * called as the buffer is not preserved between frames. Partial updates
+ * are not supported.
+ *
+ * @return A canvas for drawing into the surface.
+ *
+ * @throws IllegalStateException If the canvas cannot be locked.
+ *
+ * @hide
+ */
+ public Canvas lockHardwareWideColorGamutCanvas() {
+ synchronized (mLock) {
+ checkNotReleasedLocked();
+ if (mHwuiContext != null && !mHwuiContext.isWideColorGamut()) {
+ mHwuiContext.destroy();
+ mHwuiContext = null;
+ }
+ if (mHwuiContext == null) {
+ mHwuiContext = new HwuiContext(true);
}
return mHwuiContext.lockCanvas(
nativeGetWidth(mNativeObject),
@@ -829,11 +866,14 @@
private final RenderNode mRenderNode;
private long mHwuiRenderer;
private DisplayListCanvas mCanvas;
+ private final boolean mIsWideColorGamut;
- HwuiContext() {
+ HwuiContext(boolean isWideColorGamut) {
mRenderNode = RenderNode.create("HwuiCanvas", null);
mRenderNode.setClipToBounds(false);
- mHwuiRenderer = nHwuiCreate(mRenderNode.mNativeRenderNode, mNativeObject);
+ mIsWideColorGamut = isWideColorGamut;
+ mHwuiRenderer = nHwuiCreate(mRenderNode.mNativeRenderNode, mNativeObject,
+ isWideColorGamut);
}
Canvas lockCanvas(int width, int height) {
@@ -864,9 +904,13 @@
mHwuiRenderer = 0;
}
}
+
+ boolean isWideColorGamut() {
+ return mIsWideColorGamut;
+ }
}
- private static native long nHwuiCreate(long rootNode, long surface);
+ private static native long nHwuiCreate(long rootNode, long surface, boolean isWideColorGamut);
private static native void nHwuiSetSurface(long renderer, long surface);
private static native void nHwuiDraw(long renderer);
private static native void nHwuiDestroy(long renderer);
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 4a9da4a..7213923 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -16,7 +16,6 @@
package android.view;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
import static android.view.WindowManagerPolicyConstants.APPLICATION_MEDIA_OVERLAY_SUBLAYER;
import static android.view.WindowManagerPolicyConstants.APPLICATION_MEDIA_SUBLAYER;
import static android.view.WindowManagerPolicyConstants.APPLICATION_PANEL_SUBLAYER;
@@ -877,31 +876,6 @@
return callbacks;
}
- /**
- * This method still exists only for compatibility reasons because some applications have relied
- * on this method via reflection. See Issue 36345857 for details.
- *
- * @deprecated No platform code is using this method anymore.
- * @hide
- */
- @Deprecated
- public void setWindowType(int type) {
- if (getContext().getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.O) {
- throw new UnsupportedOperationException(
- "SurfaceView#setWindowType() has never been a public API.");
- }
-
- if (type == TYPE_APPLICATION_PANEL) {
- Log.e(TAG, "If you are calling SurfaceView#setWindowType(TYPE_APPLICATION_PANEL) "
- + "just to make the SurfaceView to be placed on top of its window, you must "
- + "call setZOrderOnTop(true) instead.", new Throwable());
- setZOrderOnTop(true);
- return;
- }
- Log.e(TAG, "SurfaceView#setWindowType(int) is deprecated and now does nothing. "
- + "type=" + type, new Throwable());
- }
-
private void runOnUiThread(Runnable runnable) {
Handler handler = getHandler();
if (handler != null && handler.getLooper() != Looper.myLooper()) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index bf0e2eb..b624870 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6546,7 +6546,7 @@
} finally {
// Set it to already called so it's not called twice when called by
// performClickInternal()
- mPrivateFlags |= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
+ mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
}
}
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 2354f25..69938cb 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -2241,18 +2241,20 @@
/**
* The window is allowed to extend into the {@link DisplayCutout} area, only if the
- * {@link DisplayCutout} is fully contained within the status bar. Otherwise, the window is
+ * {@link DisplayCutout} is fully contained within a system bar. Otherwise, the window is
* laid out such that it does not overlap with the {@link DisplayCutout} area.
*
* <p>
* In practice, this means that if the window did not set FLAG_FULLSCREEN or
- * SYSTEM_UI_FLAG_FULLSCREEN, it can extend into the cutout area in portrait.
- * Otherwise (i.e. fullscreen or landscape) it is laid out such that it does overlap the
+ * SYSTEM_UI_FLAG_FULLSCREEN, it can extend into the cutout area in portrait if the cutout
+ * is at the top edge. Similarly for SYSTEM_UI_FLAG_HIDE_NAVIGATION and a cutout at the
+ * bottom of the screen.
+ * Otherwise (i.e. fullscreen or landscape) it is laid out such that it does not overlap the
* cutout area.
*
* <p>
- * The usual precautions for not overlapping with the status bar are sufficient for ensuring
- * that no important content overlaps with the DisplayCutout.
+ * The usual precautions for not overlapping with the status and navigation bar are
+ * sufficient for ensuring that no important content overlaps with the DisplayCutout.
*
* @see DisplayCutout
* @see WindowInsets
@@ -2260,8 +2262,18 @@
public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT = 0;
/**
- * The window is always allowed to extend into the {@link DisplayCutout} area,
- * even if fullscreen or in landscape.
+ * @deprecated use {@link #LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES}
+ * @hide
+ */
+ @Deprecated
+ public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS = 1;
+
+ /**
+ * The window is always allowed to extend into the {@link DisplayCutout} areas on the short
+ * edges of the screen.
+ *
+ * The window will never extend into a {@link DisplayCutout} area on the long edges of the
+ * screen.
*
* <p>
* The window must make sure that no important content overlaps with the
@@ -2270,7 +2282,7 @@
* @see DisplayCutout
* @see WindowInsets#getDisplayCutout()
*/
- public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS = 1;
+ public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES = 1;
/**
* The window is never allowed to overlap with the DisplayCutout area.
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index c69543f..f0f30a0 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -261,8 +261,7 @@
mIsDefaultResId = isDefaultResId;
mIsAuxIme = isAuxIme;
mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod;
- // TODO(b/68948291): remove this meta-data before release.
- mIsVrOnly = isVrOnly || service.serviceInfo.metaData.getBoolean("isVrOnly", false);
+ mIsVrOnly = isVrOnly;
}
InputMethodInfo(Parcel source) {
diff --git a/core/java/android/view/textclassifier/logging/DefaultLogger.java b/core/java/android/view/textclassifier/DefaultLogger.java
similarity index 99%
rename from core/java/android/view/textclassifier/logging/DefaultLogger.java
rename to core/java/android/view/textclassifier/DefaultLogger.java
index f510879..b2f4e39 100644
--- a/core/java/android/view/textclassifier/logging/DefaultLogger.java
+++ b/core/java/android/view/textclassifier/DefaultLogger.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.view.textclassifier.logging;
+package android.view.textclassifier;
import android.annotation.NonNull;
import android.content.Context;
diff --git a/core/java/android/view/textclassifier/logging/GenerateLinksLogger.java b/core/java/android/view/textclassifier/GenerateLinksLogger.java
similarity index 97%
rename from core/java/android/view/textclassifier/logging/GenerateLinksLogger.java
rename to core/java/android/view/textclassifier/GenerateLinksLogger.java
index fb6f205..73cf43b 100644
--- a/core/java/android/view/textclassifier/logging/GenerateLinksLogger.java
+++ b/core/java/android/view/textclassifier/GenerateLinksLogger.java
@@ -14,14 +14,12 @@
* limitations under the License.
*/
-package android.view.textclassifier.logging;
+package android.view.textclassifier;
import android.annotation.Nullable;
import android.metrics.LogMaker;
import android.util.ArrayMap;
import android.util.Log;
-import android.view.textclassifier.TextClassifier;
-import android.view.textclassifier.TextLinks;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
diff --git a/core/java/android/view/textclassifier/logging/Logger.java b/core/java/android/view/textclassifier/Logger.java
similarity index 97%
rename from core/java/android/view/textclassifier/logging/Logger.java
rename to core/java/android/view/textclassifier/Logger.java
index 4448b2b..9c92fd4 100644
--- a/core/java/android/view/textclassifier/logging/Logger.java
+++ b/core/java/android/view/textclassifier/Logger.java
@@ -14,16 +14,13 @@
* limitations under the License.
*/
-package android.view.textclassifier.logging;
+package android.view.textclassifier;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringDef;
import android.content.Context;
import android.util.Log;
-import android.view.textclassifier.TextClassification;
-import android.view.textclassifier.TextClassifier;
-import android.view.textclassifier.TextSelection;
import com.android.internal.util.Preconditions;
@@ -97,10 +94,7 @@
}
/**
- * Writes the selection event.
- *
- * <p><strong>NOTE: </strong>This method is designed for subclasses.
- * Apps should not call it directly.
+ * Writes the selection event to a log.
*/
public abstract void writeEvent(@NonNull SelectionEvent event);
diff --git a/core/java/android/view/textclassifier/SelectionEvent.aidl b/core/java/android/view/textclassifier/SelectionEvent.aidl
new file mode 100644
index 0000000..10ed16e
--- /dev/null
+++ b/core/java/android/view/textclassifier/SelectionEvent.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2018 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.view.textclassifier;
+
+parcelable SelectionEvent;
diff --git a/core/java/android/view/textclassifier/logging/SelectionEvent.java b/core/java/android/view/textclassifier/SelectionEvent.java
similarity index 70%
rename from core/java/android/view/textclassifier/logging/SelectionEvent.java
rename to core/java/android/view/textclassifier/SelectionEvent.java
index a8de308..7ac094e 100644
--- a/core/java/android/view/textclassifier/logging/SelectionEvent.java
+++ b/core/java/android/view/textclassifier/SelectionEvent.java
@@ -14,10 +14,12 @@
* limitations under the License.
*/
-package android.view.textclassifier.logging;
+package android.view.textclassifier;
import android.annotation.IntDef;
import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.view.textclassifier.TextClassifier.EntityType;
import com.android.internal.util.Preconditions;
@@ -25,12 +27,13 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Locale;
+import java.util.Objects;
/**
* A selection event.
* Specify index parameters as word token indices.
*/
-public final class SelectionEvent {
+public final class SelectionEvent implements Parcelable {
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -121,9 +124,9 @@
private String mSignature;
private long mEventTime;
private long mDurationSinceSessionStart;
- private long mDurationSinceLastEvent;
+ private long mDurationSincePreviousEvent;
private int mEventIndex;
- private String mSessionId;
+ @Nullable private String mSessionId;
private int mStart;
private int mEnd;
private int mSmartStart;
@@ -146,6 +149,60 @@
mInvocationMethod = invocationMethod;
}
+ private SelectionEvent(Parcel in) {
+ mAbsoluteStart = in.readInt();
+ mAbsoluteEnd = in.readInt();
+ mEventType = in.readInt();
+ mEntityType = in.readString();
+ mWidgetVersion = in.readInt() > 0 ? in.readString() : null;
+ mPackageName = in.readString();
+ mWidgetType = in.readString();
+ mInvocationMethod = in.readInt();
+ mSignature = in.readString();
+ mEventTime = in.readLong();
+ mDurationSinceSessionStart = in.readLong();
+ mDurationSincePreviousEvent = in.readLong();
+ mEventIndex = in.readInt();
+ mSessionId = in.readInt() > 0 ? in.readString() : null;
+ mStart = in.readInt();
+ mEnd = in.readInt();
+ mSmartStart = in.readInt();
+ mSmartEnd = in.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mAbsoluteStart);
+ dest.writeInt(mAbsoluteEnd);
+ dest.writeInt(mEventType);
+ dest.writeString(mEntityType);
+ dest.writeInt(mWidgetVersion != null ? 1 : 0);
+ if (mWidgetVersion != null) {
+ dest.writeString(mWidgetVersion);
+ }
+ dest.writeString(mPackageName);
+ dest.writeString(mWidgetType);
+ dest.writeInt(mInvocationMethod);
+ dest.writeString(mSignature);
+ dest.writeLong(mEventTime);
+ dest.writeLong(mDurationSinceSessionStart);
+ dest.writeLong(mDurationSincePreviousEvent);
+ dest.writeInt(mEventIndex);
+ dest.writeInt(mSessionId != null ? 1 : 0);
+ if (mSessionId != null) {
+ dest.writeString(mSessionId);
+ }
+ dest.writeInt(mStart);
+ dest.writeInt(mEnd);
+ dest.writeInt(mSmartStart);
+ dest.writeInt(mSmartEnd);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
int getAbsoluteStart() {
return mAbsoluteStart;
}
@@ -240,11 +297,11 @@
* in the selection session was triggered.
*/
public long getDurationSincePreviousEvent() {
- return mDurationSinceLastEvent;
+ return mDurationSincePreviousEvent;
}
SelectionEvent setDurationSincePreviousEvent(long durationMs) {
- this.mDurationSinceLastEvent = durationMs;
+ this.mDurationSincePreviousEvent = durationMs;
return this;
}
@@ -342,15 +399,66 @@
}
@Override
+ public int hashCode() {
+ return Objects.hash(mAbsoluteStart, mAbsoluteEnd, mEventType, mEntityType,
+ mWidgetVersion, mPackageName, mWidgetType, mInvocationMethod, mSignature,
+ mEventTime, mDurationSinceSessionStart, mDurationSincePreviousEvent,
+ mEventIndex, mSessionId, mStart, mEnd, mSmartStart, mSmartEnd);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof SelectionEvent)) {
+ return false;
+ }
+
+ final SelectionEvent other = (SelectionEvent) obj;
+ return mAbsoluteStart == other.mAbsoluteStart
+ && mAbsoluteEnd == other.mAbsoluteEnd
+ && mEventType == other.mEventType
+ && Objects.equals(mEntityType, other.mEntityType)
+ && Objects.equals(mWidgetVersion, other.mWidgetVersion)
+ && Objects.equals(mPackageName, other.mPackageName)
+ && Objects.equals(mWidgetType, other.mWidgetType)
+ && mInvocationMethod == other.mInvocationMethod
+ && Objects.equals(mSignature, other.mSignature)
+ && mEventTime == other.mEventTime
+ && mDurationSinceSessionStart == other.mDurationSinceSessionStart
+ && mDurationSincePreviousEvent == other.mDurationSincePreviousEvent
+ && mEventIndex == other.mEventIndex
+ && Objects.equals(mSessionId, other.mSessionId)
+ && mStart == other.mStart
+ && mEnd == other.mEnd
+ && mSmartStart == other.mSmartStart
+ && mSmartEnd == other.mSmartEnd;
+ }
+
+ @Override
public String toString() {
return String.format(Locale.US,
"SelectionEvent {absoluteStart=%d, absoluteEnd=%d, eventType=%d, entityType=%s, "
- + "widgetVersion=%s, packageName=%s, widgetType=%s, signature=%s, "
- + "eventTime=%d, durationSinceSessionStart=%d, durationSinceLastEvent=%d, "
- + "eventIndex=%d, sessionId=%s, start=%d, end=%d, smartStart=%d, smartEnd=%d}",
+ + "widgetVersion=%s, packageName=%s, widgetType=%s, invocationMethod=%s, "
+ + "signature=%s, eventTime=%d, durationSinceSessionStart=%d, "
+ + "durationSincePreviousEvent=%d, eventIndex=%d, sessionId=%s, start=%d, end=%d, "
+ + "smartStart=%d, smartEnd=%d}",
mAbsoluteStart, mAbsoluteEnd, mEventType, mEntityType,
- mWidgetVersion, mPackageName, mWidgetType, mSignature,
- mEventTime, mDurationSinceSessionStart, mDurationSinceLastEvent,
+ mWidgetVersion, mPackageName, mWidgetType, mInvocationMethod, mSignature,
+ mEventTime, mDurationSinceSessionStart, mDurationSincePreviousEvent,
mEventIndex, mSessionId, mStart, mEnd, mSmartStart, mSmartEnd);
}
+
+ public static final Creator<SelectionEvent> CREATOR = new Creator<SelectionEvent>() {
+ @Override
+ public SelectionEvent createFromParcel(Parcel in) {
+ return new SelectionEvent(in);
+ }
+
+ @Override
+ public SelectionEvent[] newArray(int size) {
+ return new SelectionEvent[size];
+ }
+ };
}
diff --git a/core/java/android/view/textclassifier/SystemTextClassifier.java b/core/java/android/view/textclassifier/SystemTextClassifier.java
index 2b335fb..c783cae 100644
--- a/core/java/android/view/textclassifier/SystemTextClassifier.java
+++ b/core/java/android/view/textclassifier/SystemTextClassifier.java
@@ -29,6 +29,7 @@
import android.service.textclassifier.ITextLinksCallback;
import android.service.textclassifier.ITextSelectionCallback;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import java.util.concurrent.CountDownLatch;
@@ -46,6 +47,12 @@
private final TextClassifier mFallback;
private final String mPackageName;
+ private final Object mLoggerLock = new Object();
+ @GuardedBy("mLoggerLock")
+ private Logger.Config mLoggerConfig;
+ @GuardedBy("mLoggerLock")
+ private Logger mLogger;
+
SystemTextClassifier(Context context, TextClassificationConstants settings)
throws ServiceManager.ServiceNotFoundException {
mManagerService = ITextClassifierService.Stub.asInterface(
@@ -58,6 +65,7 @@
/**
* @inheritDoc
*/
+ @Override
@WorkerThread
public TextSelection suggestSelection(
@NonNull CharSequence text,
@@ -84,6 +92,7 @@
/**
* @inheritDoc
*/
+ @Override
@WorkerThread
public TextClassification classifyText(
@NonNull CharSequence text,
@@ -109,6 +118,7 @@
/**
* @inheritDoc
*/
+ @Override
@WorkerThread
public TextLinks generateLinks(
@NonNull CharSequence text, @Nullable TextLinks.Options options) {
@@ -142,11 +152,33 @@
* @inheritDoc
*/
@Override
+ @WorkerThread
public int getMaxGenerateLinksTextLength() {
// TODO: retrieve this from the bound service.
return mFallback.getMaxGenerateLinksTextLength();
}
+ @Override
+ public Logger getLogger(@NonNull Logger.Config config) {
+ Preconditions.checkNotNull(config);
+ synchronized (mLoggerLock) {
+ if (mLogger == null || !config.equals(mLoggerConfig)) {
+ mLoggerConfig = config;
+ mLogger = new Logger(config) {
+ @Override
+ public void writeEvent(SelectionEvent event) {
+ try {
+ mManagerService.onSelectionEvent(event);
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+ };
+ }
+ }
+ return mLogger;
+ }
+
private static final class TextSelectionCallback extends ITextSelectionCallback.Stub {
final ResponseReceiver<TextSelection> mReceiver = new ResponseReceiver<>();
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index ec40fdd..887bebb 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -28,7 +28,6 @@
import android.os.Parcelable;
import android.util.ArraySet;
import android.util.Slog;
-import android.view.textclassifier.logging.Logger;
import com.android.internal.util.Preconditions;
@@ -324,6 +323,7 @@
* @see #generateLinks(CharSequence)
* @see #generateLinks(CharSequence, TextLinks.Options)
*/
+ @WorkerThread
default int getMaxGenerateLinksTextLength() {
return Integer.MAX_VALUE;
}
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 41f1c69..a099820 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.WorkerThread;
import android.app.SearchManager;
import android.content.ComponentName;
import android.content.ContentUris;
@@ -34,9 +35,6 @@
import android.provider.Browser;
import android.provider.CalendarContract;
import android.provider.ContactsContract;
-import android.view.textclassifier.logging.DefaultLogger;
-import android.view.textclassifier.logging.GenerateLinksLogger;
-import android.view.textclassifier.logging.Logger;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
@@ -45,7 +43,6 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
-import java.lang.ref.WeakReference;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
@@ -81,7 +78,6 @@
private final Context mContext;
private final TextClassifier mFallback;
-
private final GenerateLinksLogger mGenerateLinksLogger;
private final Object mLock = new Object();
@@ -94,9 +90,9 @@
private final Object mLoggerLock = new Object();
@GuardedBy("mLoggerLock") // Do not access outside this lock.
- private WeakReference<Logger.Config> mLoggerConfig = new WeakReference<>(null);
+ private Logger.Config mLoggerConfig;
@GuardedBy("mLoggerLock") // Do not access outside this lock.
- private Logger mLogger; // Should never be null if mLoggerConfig.get() is not null.
+ private Logger mLogger;
private final TextClassificationConstants mSettings;
@@ -109,6 +105,7 @@
/** @inheritDoc */
@Override
+ @WorkerThread
public TextSelection suggestSelection(
@NonNull CharSequence text, int selectionStartIndex, int selectionEndIndex,
@Nullable TextSelection.Options options) {
@@ -172,6 +169,7 @@
/** @inheritDoc */
@Override
+ @WorkerThread
public TextClassification classifyText(
@NonNull CharSequence text, int startIndex, int endIndex,
@Nullable TextClassification.Options options) {
@@ -207,6 +205,7 @@
/** @inheritDoc */
@Override
+ @WorkerThread
public TextLinks generateLinks(
@NonNull CharSequence text, @Nullable TextLinks.Options options) {
Utils.validate(text, getMaxGenerateLinksTextLength(), false /* allowInMainThread */);
@@ -285,16 +284,17 @@
}
}
+ /** @inheritDoc */
@Override
public Logger getLogger(@NonNull Logger.Config config) {
Preconditions.checkNotNull(config);
synchronized (mLoggerLock) {
- if (mLoggerConfig.get() == null || !mLoggerConfig.get().equals(config)) {
- mLoggerConfig = new WeakReference<>(config);
+ if (mLogger == null || !config.equals(mLoggerConfig)) {
+ mLoggerConfig = config;
mLogger = new DefaultLogger(config);
}
- return mLogger;
}
+ return mLogger;
}
private TextClassifierImplNative getNative(LocaleList localeList)
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index fadc3dc..f39b73e 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2906,6 +2906,11 @@
mProvider.getViewDelegate().autofill(values);
}
+ @Override
+ public boolean isVisibleToUserForAutofill(int virtualId) {
+ return mProvider.getViewDelegate().isVisibleToUserForAutofill(virtualId);
+ }
+
/** @hide */
@Override
public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
@@ -3121,6 +3126,11 @@
mProvider.getViewDelegate().onActivityResult(requestCode, resultCode, data);
}
+ @Override
+ public boolean onCheckIsTextEditor() {
+ return mProvider.getViewDelegate().onCheckIsTextEditor();
+ }
+
/** @hide */
@Override
protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index a896925..00e782b 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -329,13 +329,16 @@
public void onProvideVirtualStructure(android.view.ViewStructure structure);
- @SuppressWarnings("unused")
- public default void onProvideAutofillVirtualStructure(android.view.ViewStructure structure,
- int flags) {
+ default void onProvideAutofillVirtualStructure(
+ @SuppressWarnings("unused") android.view.ViewStructure structure,
+ @SuppressWarnings("unused") int flags) {
}
- @SuppressWarnings("unused")
- public default void autofill(SparseArray<AutofillValue>values) {
+ default void autofill(@SuppressWarnings("unused") SparseArray<AutofillValue> values) {
+ }
+
+ default boolean isVisibleToUserForAutofill(@SuppressWarnings("unused") int virtualId) {
+ return true; // true is the default value returned by View.isVisibleToUserForAutofill()
}
public AccessibilityNodeProvider getAccessibilityNodeProvider();
@@ -424,6 +427,11 @@
public Handler getHandler(Handler originalHandler);
public View findFocus(View originalFocusedView);
+
+ @SuppressWarnings("unused")
+ default boolean onCheckIsTextEditor() {
+ return false;
+ }
}
interface ScrollDelegate {
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 1d1fcc9..61a5873 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -863,7 +863,7 @@
}
final int range = getMax() - getMin();
- progress += scale * range;
+ progress += scale * range + getMin();
setHotspot(x, y);
setProgressInternal(Math.round(progress), true, false);
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index fe49c02..92285c7 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -17,6 +17,7 @@
package android.widget;
import android.R;
+import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -37,6 +38,7 @@
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
+import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
@@ -99,6 +101,7 @@
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.animation.LinearInterpolator;
import android.view.inputmethod.CorrectionInfo;
import android.view.inputmethod.CursorAnchorInfo;
import android.view.inputmethod.EditorInfo;
@@ -200,11 +203,11 @@
private final boolean mHapticTextHandleEnabled;
- private final Magnifier mMagnifier;
+ private final MagnifierMotionAnimator mMagnifierAnimator;
private final Runnable mUpdateMagnifierRunnable = new Runnable() {
@Override
public void run() {
- mMagnifier.update();
+ mMagnifierAnimator.update();
}
};
// Update the magnifier contents whenever anything in the view hierarchy is updated.
@@ -215,7 +218,7 @@
new ViewTreeObserver.OnDrawListener() {
@Override
public void onDraw() {
- if (mMagnifier != null) {
+ if (mMagnifierAnimator != null) {
// Posting the method will ensure that updating the magnifier contents will
// happen right after the rendering of the current frame.
mTextView.post(mUpdateMagnifierRunnable);
@@ -371,7 +374,9 @@
mHapticTextHandleEnabled = mTextView.getContext().getResources().getBoolean(
com.android.internal.R.bool.config_enableHapticTextHandle);
- mMagnifier = FLAG_USE_MAGNIFIER ? new Magnifier(mTextView) : null;
+ if (FLAG_USE_MAGNIFIER) {
+ mMagnifierAnimator = new MagnifierMotionAnimator(new Magnifier(mTextView));
+ }
}
ParcelableParcel saveInstanceState() {
@@ -4309,6 +4314,88 @@
}
}
+ private static class MagnifierMotionAnimator {
+ private static final long DURATION = 100 /* miliseconds */;
+
+ // The magnifier being animated.
+ private final Magnifier mMagnifier;
+ // A value animator used to animate the magnifier.
+ private final ValueAnimator mAnimator;
+
+ // Whether the magnifier is currently visible.
+ private boolean mMagnifierIsShowing;
+ // The coordinates of the magnifier when the currently running animation started.
+ private float mAnimationStartX;
+ private float mAnimationStartY;
+ // The coordinates of the magnifier in the latest animation frame.
+ private float mAnimationCurrentX;
+ private float mAnimationCurrentY;
+ // The latest coordinates the motion animator was asked to #show() the magnifier at.
+ private float mLastX;
+ private float mLastY;
+
+ private MagnifierMotionAnimator(final Magnifier magnifier) {
+ mMagnifier = magnifier;
+ // Prepare the animator used to run the motion animation.
+ mAnimator = ValueAnimator.ofFloat(0, 1);
+ mAnimator.setDuration(DURATION);
+ mAnimator.setInterpolator(new LinearInterpolator());
+ mAnimator.addUpdateListener((animation) -> {
+ // Interpolate to find the current position of the magnifier.
+ mAnimationCurrentX = mAnimationStartX
+ + (mLastX - mAnimationStartX) * animation.getAnimatedFraction();
+ mAnimationCurrentY = mAnimationStartY
+ + (mLastY - mAnimationStartY) * animation.getAnimatedFraction();
+ mMagnifier.show(mAnimationCurrentX, mAnimationCurrentY);
+ });
+ }
+
+ /**
+ * Shows the magnifier at a new position.
+ * If the y coordinate is different from the previous y coordinate
+ * (probably corresponding to a line jump in the text), a short
+ * animation is added to the jump.
+ */
+ private void show(final float x, final float y) {
+ final boolean startNewAnimation = mMagnifierIsShowing && y != mLastY;
+
+ if (startNewAnimation) {
+ if (mAnimator.isRunning()) {
+ mAnimator.cancel();
+ mAnimationStartX = mAnimationCurrentX;
+ mAnimationStartY = mAnimationCurrentY;
+ } else {
+ mAnimationStartX = mLastX;
+ mAnimationStartY = mLastY;
+ }
+ mAnimator.start();
+ } else {
+ if (!mAnimator.isRunning()) {
+ mMagnifier.show(x, y);
+ }
+ }
+ mLastX = x;
+ mLastY = y;
+ mMagnifierIsShowing = true;
+ }
+
+ /**
+ * Updates the content of the magnifier.
+ */
+ private void update() {
+ mMagnifier.update();
+ }
+
+ /**
+ * Dismisses the magnifier, or does nothing if it is already dismissed.
+ */
+ private void dismiss() {
+ mMagnifier.dismiss();
+ mAnimator.cancel();
+ mMagnifierIsShowing = false;
+ }
+ }
+
@VisibleForTesting
public abstract class HandleView extends View implements TextViewPositionListener {
protected Drawable mDrawable;
@@ -4648,52 +4735,106 @@
return 0;
}
- protected final void showMagnifier(@NonNull final MotionEvent event) {
- if (mMagnifier == null) {
- return;
- }
+ /**
+ * Computes the position where the magnifier should be shown, relative to
+ * {@code mTextView}, and writes them to {@code showPosInView}. Also decides
+ * whether the magnifier should be shown or dismissed after this touch event.
+ * @return Whether the magnifier should be shown at the computed coordinates or dismissed.
+ */
+ private boolean obtainMagnifierShowCoordinates(@NonNull final MotionEvent event,
+ final PointF showPosInView) {
final int trigger = getMagnifierHandleTrigger();
final int offset;
+ final int otherHandleOffset;
switch (trigger) {
- case MagnifierHandleTrigger.INSERTION: // Fall through.
+ case MagnifierHandleTrigger.INSERTION:
+ offset = mTextView.getSelectionStart();
+ otherHandleOffset = -1;
+ break;
case MagnifierHandleTrigger.SELECTION_START:
offset = mTextView.getSelectionStart();
+ otherHandleOffset = mTextView.getSelectionEnd();
break;
case MagnifierHandleTrigger.SELECTION_END:
offset = mTextView.getSelectionEnd();
+ otherHandleOffset = mTextView.getSelectionStart();
break;
default:
offset = -1;
+ otherHandleOffset = -1;
break;
}
if (offset == -1) {
- dismissMagnifier();
+ return false;
}
final Layout layout = mTextView.getLayout();
final int lineNumber = layout.getLineForOffset(offset);
- // Horizontally move the magnifier smoothly.
+ // Compute whether the selection handles are currently on the same line, and,
+ // in this particular case, whether the selected text is right to left.
+ final boolean sameLineSelection = otherHandleOffset != -1
+ && lineNumber == layout.getLineForOffset(otherHandleOffset);
+ final boolean rtl = sameLineSelection
+ && (offset < otherHandleOffset)
+ != (getHorizontal(mTextView.getLayout(), offset)
+ < getHorizontal(mTextView.getLayout(), otherHandleOffset));
+
+ // Horizontally move the magnifier smoothly, clamp inside the current line / selection.
final int[] textViewLocationOnScreen = new int[2];
mTextView.getLocationOnScreen(textViewLocationOnScreen);
- final float xPosInView = event.getRawX() - textViewLocationOnScreen[0];
+ final float touchXInView = event.getRawX() - textViewLocationOnScreen[0];
+ float leftBound = mTextView.getTotalPaddingLeft() - mTextView.getScrollX();
+ float rightBound = mTextView.getTotalPaddingLeft() - mTextView.getScrollX();
+ if (sameLineSelection && ((trigger == MagnifierHandleTrigger.SELECTION_END) ^ rtl)) {
+ leftBound += getHorizontal(mTextView.getLayout(), otherHandleOffset);
+ } else {
+ leftBound += mTextView.getLayout().getLineLeft(lineNumber);
+ }
+ if (sameLineSelection && ((trigger == MagnifierHandleTrigger.SELECTION_START) ^ rtl)) {
+ rightBound += getHorizontal(mTextView.getLayout(), otherHandleOffset);
+ } else {
+ rightBound += mTextView.getLayout().getLineRight(lineNumber);
+ }
+ final float contentWidth = Math.round(mMagnifierAnimator.mMagnifier.getWidth()
+ / mMagnifierAnimator.mMagnifier.getZoom());
+ if (touchXInView < leftBound - contentWidth / 2
+ || touchXInView > rightBound + contentWidth / 2) {
+ // The touch is too far from the current line / selection, so hide the magnifier.
+ return false;
+ }
+ showPosInView.x = Math.max(leftBound, Math.min(rightBound, touchXInView));
+
// Vertically snap to middle of current line.
- final float yPosInView = (mTextView.getLayout().getLineTop(lineNumber)
+ showPosInView.y = (mTextView.getLayout().getLineTop(lineNumber)
+ mTextView.getLayout().getLineBottom(lineNumber)) / 2.0f
+ mTextView.getTotalPaddingTop() - mTextView.getScrollY();
- // Make the cursor visible and stop blinking.
- mRenderCursorRegardlessTiming = true;
- mTextView.invalidateCursorPath();
- suspendBlink();
+ return true;
+ }
- mMagnifier.show(xPosInView, yPosInView);
+ protected final void updateMagnifier(@NonNull final MotionEvent event) {
+ if (mMagnifierAnimator == null) {
+ return;
+ }
+
+ final PointF showPosInView = new PointF();
+ final boolean shouldShow = obtainMagnifierShowCoordinates(event, showPosInView);
+ if (shouldShow) {
+ // Make the cursor visible and stop blinking.
+ mRenderCursorRegardlessTiming = true;
+ mTextView.invalidateCursorPath();
+ suspendBlink();
+ mMagnifierAnimator.show(showPosInView.x, showPosInView.y);
+ } else {
+ dismissMagnifier();
+ }
}
protected final void dismissMagnifier() {
- if (mMagnifier != null) {
- mMagnifier.dismiss();
+ if (mMagnifierAnimator != null) {
+ mMagnifierAnimator.dismiss();
mRenderCursorRegardlessTiming = false;
resumeBlink();
}
@@ -4877,11 +5018,11 @@
case MotionEvent.ACTION_DOWN:
mDownPositionX = ev.getRawX();
mDownPositionY = ev.getRawY();
- showMagnifier(ev);
+ updateMagnifier(ev);
break;
case MotionEvent.ACTION_MOVE:
- showMagnifier(ev);
+ updateMagnifier(ev);
break;
case MotionEvent.ACTION_UP:
@@ -5235,11 +5376,11 @@
// re-engages the handle.
mTouchWordDelta = 0.0f;
mPrevX = UNSET_X_VALUE;
- showMagnifier(event);
+ updateMagnifier(event);
break;
case MotionEvent.ACTION_MOVE:
- showMagnifier(event);
+ updateMagnifier(event);
break;
case MotionEvent.ACTION_UP:
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 85f68d7..e2601dc 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -23,6 +23,7 @@
import android.annotation.UiThread;
import android.content.Context;
import android.content.res.Resources;
+import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Outline;
@@ -34,6 +35,7 @@
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
+import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.DisplayListCanvas;
import android.view.LayoutInflater;
@@ -49,6 +51,7 @@
import android.view.ViewParent;
import android.view.ViewRootImpl;
+import com.android.internal.R;
import com.android.internal.util.Preconditions;
/**
@@ -75,12 +78,16 @@
private final int mWindowWidth;
// The height of the window containing the magnifier.
private final int mWindowHeight;
+ // The zoom applied to the view region copied to the magnifier window.
+ private final float mZoom;
// The width of the bitmaps where the magnifier content is copied.
private final int mBitmapWidth;
// The height of the bitmaps where the magnifier content is copied.
private final int mBitmapHeight;
// The elevation of the window containing the magnifier.
private final float mWindowElevation;
+ // The corner radius of the window containing the magnifier.
+ private final float mWindowCornerRadius;
// The center coordinates of the content that is to be magnified.
private final Point mCenterZoomCoords = new Point();
// Variables holding previous states, used for detecting redundant calls and invalidation.
@@ -102,19 +109,15 @@
public Magnifier(@NonNull View view) {
mView = Preconditions.checkNotNull(view);
final Context context = mView.getContext();
- final View content = LayoutInflater.from(context).inflate(
- com.android.internal.R.layout.magnifier, null);
- content.findViewById(com.android.internal.R.id.magnifier_inner).setClipToOutline(true);
- mWindowWidth = context.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.magnifier_width);
- mWindowHeight = context.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.magnifier_height);
- mWindowElevation = context.getResources().getDimension(
- com.android.internal.R.dimen.magnifier_elevation);
- final float zoomScale = context.getResources().getFloat(
- com.android.internal.R.dimen.magnifier_zoom_scale);
- mBitmapWidth = Math.round(mWindowWidth / zoomScale);
- mBitmapHeight = Math.round(mWindowHeight / zoomScale);
+ final View content = LayoutInflater.from(context).inflate(R.layout.magnifier, null);
+ content.findViewById(R.id.magnifier_inner).setClipToOutline(true);
+ mWindowWidth = context.getResources().getDimensionPixelSize(R.dimen.magnifier_width);
+ mWindowHeight = context.getResources().getDimensionPixelSize(R.dimen.magnifier_height);
+ mWindowElevation = context.getResources().getDimension(R.dimen.magnifier_elevation);
+ mWindowCornerRadius = getDeviceDefaultDialogCornerRadius();
+ mZoom = context.getResources().getFloat(R.dimen.magnifier_zoom_scale);
+ mBitmapWidth = Math.round(mWindowWidth / mZoom);
+ mBitmapHeight = Math.round(mWindowHeight / mZoom);
// The view's surface coordinates will not be updated until the magnifier is first shown.
mViewCoordinatesInSurface = new int[2];
}
@@ -124,6 +127,21 @@
}
/**
+ * Returns the device default theme dialog corner radius attribute.
+ * We retrieve this from the device default theme to avoid
+ * using the values set in the custom application themes.
+ */
+ private float getDeviceDefaultDialogCornerRadius() {
+ final Context deviceDefaultContext =
+ new ContextThemeWrapper(mView.getContext(), R.style.Theme_DeviceDefault);
+ final TypedArray ta = deviceDefaultContext.obtainStyledAttributes(
+ new int[]{android.R.attr.dialogCornerRadius});
+ final float dialogCornerRadius = ta.getDimension(0, 0);
+ ta.recycle();
+ return dialogCornerRadius;
+ }
+
+ /**
* Shows the magnifier on the screen.
*
* @param xPosInView horizontal coordinate of the center point of the magnifier source relative
@@ -176,7 +194,8 @@
if (mWindow == null) {
synchronized (mLock) {
mWindow = new InternalPopupWindow(mView.getContext(), mView.getDisplay(),
- getValidViewSurface(), mWindowWidth, mWindowHeight, mWindowElevation,
+ getValidViewSurface(),
+ mWindowWidth, mWindowHeight, mWindowElevation, mWindowCornerRadius,
Handler.getMain() /* draw the magnifier on the UI thread */, mLock,
mCallback);
}
@@ -187,21 +206,6 @@
}
}
- @Nullable
- private Surface getValidViewSurface() {
- // TODO: deduplicate this against the first part of #performPixelCopy
- final Surface surface;
- if (mView instanceof SurfaceView) {
- surface = ((SurfaceView) mView).getHolder().getSurface();
- } else if (mView.getViewRootImpl() != null) {
- surface = mView.getViewRootImpl().mSurface;
- } else {
- surface = null;
- }
-
- return (surface != null && surface.isValid()) ? surface : null;
- }
-
/**
* Dismisses the magnifier from the screen. Calling this on a dismissed magnifier is a no-op.
*/
@@ -226,6 +230,44 @@
}
}
+ /**
+ * @return The width of the magnifier window, in pixels.
+ */
+ public int getWidth() {
+ return mWindowWidth;
+ }
+
+ /**
+ * @return The height of the magnifier window, in pixels.
+ */
+ public int getHeight() {
+ return mWindowHeight;
+ }
+
+ /**
+ * @return The zoom applied to the magnified view region copied to the magnifier window.
+ * If the zoom is x and the magnifier window size is (width, height), the original size
+ * of the content copied in the magnifier will be (width / x, height / x).
+ */
+ public float getZoom() {
+ return mZoom;
+ }
+
+ @Nullable
+ private Surface getValidViewSurface() {
+ // TODO: deduplicate this against the first part of #performPixelCopy
+ final Surface surface;
+ if (mView instanceof SurfaceView) {
+ surface = ((SurfaceView) mView).getHolder().getSurface();
+ } else if (mView.getViewRootImpl() != null) {
+ surface = mView.getViewRootImpl().mSurface;
+ } else {
+ surface = null;
+ }
+
+ return (surface != null && surface.isValid()) ? surface : null;
+ }
+
private void configureCoordinates(final float xPosInView, final float yPosInView) {
// Compute the coordinates of the center of the content going to be displayed in the
// magnifier. These are relative to the surface the content is copied from.
@@ -246,7 +288,7 @@
// Compute the position of the magnifier window. Again, this has to be relative to the
// surface of the magnified view, as this surface is the parent of the magnifier surface.
final int verticalOffset = mView.getContext().getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.magnifier_offset);
+ R.dimen.magnifier_offset);
mWindowCoords.x = mCenterZoomCoords.x - mWindowWidth / 2;
mWindowCoords.y = mCenterZoomCoords.y - mWindowHeight / 2 - verticalOffset;
}
@@ -368,7 +410,7 @@
InternalPopupWindow(final Context context, final Display display,
final Surface parentSurface,
- final int width, final int height, final float elevation,
+ final int width, final int height, final float elevation, final float cornerRadius,
final Handler handler, final Object lock, final Callback callback) {
mDisplay = display;
mLock = lock;
@@ -399,7 +441,8 @@
);
mBitmapRenderNode = createRenderNodeForBitmap(
"magnifier content",
- elevation
+ elevation,
+ cornerRadius
);
final DisplayListCanvas canvas = mRenderer.getRootNode().start(width, height);
@@ -417,7 +460,8 @@
mFrameDrawScheduled = false;
}
- private RenderNode createRenderNodeForBitmap(final String name, final float elevation) {
+ private RenderNode createRenderNodeForBitmap(final String name,
+ final float elevation, final float cornerRadius) {
final RenderNode bitmapRenderNode = RenderNode.create(name, null);
// Define the position of the bitmap in the parent render node. The surface regions
@@ -427,7 +471,7 @@
bitmapRenderNode.setElevation(elevation);
final Outline outline = new Outline();
- outline.setRoundRect(0, 0, mContentWidth, mContentHeight, 3);
+ outline.setRoundRect(0, 0, mContentWidth, mContentHeight, cornerRadius);
outline.setAlpha(1.0f);
bitmapRenderNode.setOutline(outline);
bitmapRenderNode.setClipToOutline(true);
@@ -602,7 +646,7 @@
return null;
}
synchronized (mWindow.mLock) {
- return mWindow.mBitmap;
+ return Bitmap.createScaledBitmap(mWindow.mBitmap, mWindowWidth, mWindowHeight, true);
}
}
@@ -633,8 +677,8 @@
final Resources resources = Resources.getSystem();
final float density = resources.getDisplayMetrics().density;
final PointF size = new PointF();
- size.x = resources.getDimension(com.android.internal.R.dimen.magnifier_width) / density;
- size.y = resources.getDimension(com.android.internal.R.dimen.magnifier_height) / density;
+ size.x = resources.getDimension(R.dimen.magnifier_width) / density;
+ size.y = resources.getDimension(R.dimen.magnifier_height) / density;
return size;
}
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 8e93078..be8c34c 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -33,13 +33,13 @@
import android.text.TextUtils;
import android.util.Log;
import android.view.ActionMode;
+import android.view.textclassifier.Logger;
+import android.view.textclassifier.SelectionEvent;
import android.view.textclassifier.TextClassification;
import android.view.textclassifier.TextClassificationConstants;
import android.view.textclassifier.TextClassificationManager;
import android.view.textclassifier.TextClassifier;
import android.view.textclassifier.TextSelection;
-import android.view.textclassifier.logging.Logger;
-import android.view.textclassifier.logging.SelectionEvent;
import android.widget.Editor.SelectionModifierCursorController;
import com.android.internal.annotations.VisibleForTesting;
@@ -648,6 +648,9 @@
* Part selection of a word e.g. "or" is counted as selecting the
* entire word i.e. equivalent to "York", and each special character is counted as a word, e.g.
* "," is at [2, 3). Whitespaces are ignored.
+ *
+ * NOTE that the definition of a word is defined by the TextClassifier's Logger's token
+ * iterator.
*/
private static final class SelectionMetricsLogger {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 6fe64a0..f77a6b7 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -291,6 +291,7 @@
* @attr ref android.R.styleable#TextView_drawableTintMode
* @attr ref android.R.styleable#TextView_lineSpacingExtra
* @attr ref android.R.styleable#TextView_lineSpacingMultiplier
+ * @attr ref android.R.styleable#TextView_justificationMode
* @attr ref android.R.styleable#TextView_marqueeRepeatLimit
* @attr ref android.R.styleable#TextView_inputType
* @attr ref android.R.styleable#TextView_imeOptions
diff --git a/core/java/com/android/internal/backup/LocalTransportParameters.java b/core/java/com/android/internal/backup/LocalTransportParameters.java
index 390fae9..154e79d 100644
--- a/core/java/com/android/internal/backup/LocalTransportParameters.java
+++ b/core/java/com/android/internal/backup/LocalTransportParameters.java
@@ -16,62 +16,32 @@
package com.android.internal.backup;
+import android.util.KeyValueSettingObserver;
import android.content.ContentResolver;
-import android.database.ContentObserver;
import android.os.Handler;
import android.provider.Settings;
import android.util.KeyValueListParser;
-import android.util.Slog;
-class LocalTransportParameters {
+class LocalTransportParameters extends KeyValueSettingObserver {
private static final String TAG = "LocalTransportParams";
private static final String SETTING = Settings.Secure.BACKUP_LOCAL_TRANSPORT_PARAMETERS;
private static final String KEY_FAKE_ENCRYPTION_FLAG = "fake_encryption_flag";
- private final KeyValueListParser mParser = new KeyValueListParser(',');
- private final ContentObserver mObserver;
- private final ContentResolver mResolver;
private boolean mFakeEncryptionFlag;
LocalTransportParameters(Handler handler, ContentResolver resolver) {
- mObserver = new Observer(handler);
- mResolver = resolver;
- }
-
- /** Observes for changes in the setting. This method MUST be paired with {@link #stop()}. */
- void start() {
- mResolver.registerContentObserver(Settings.Secure.getUriFor(SETTING), false, mObserver);
- update();
- }
-
- /** Stop observing for changes in the setting. */
- void stop() {
- mResolver.unregisterContentObserver(mObserver);
+ super(handler, resolver, Settings.Secure.getUriFor(SETTING));
}
boolean isFakeEncryptionFlag() {
return mFakeEncryptionFlag;
}
- private void update() {
- String parameters = "";
- try {
- parameters = Settings.Secure.getString(mResolver, SETTING);
- } catch (IllegalArgumentException e) {
- Slog.e(TAG, "Malformed " + SETTING + " setting: " + e.getMessage());
- }
- mParser.setString(parameters);
- mFakeEncryptionFlag = mParser.getBoolean(KEY_FAKE_ENCRYPTION_FLAG, false);
+ public String getSettingValue(ContentResolver resolver) {
+ return Settings.Secure.getString(resolver, SETTING);
}
- private class Observer extends ContentObserver {
- private Observer(Handler handler) {
- super(handler);
- }
-
- @Override
- public void onChange(boolean selfChange) {
- update();
- }
+ public void update(KeyValueListParser parser) {
+ mFakeEncryptionFlag = parser.getBoolean(KEY_FAKE_ENCRYPTION_FLAG, false);
}
}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodSubtypeHandle.java b/core/java/com/android/internal/inputmethod/InputMethodSubtypeHandle.java
deleted file mode 100644
index 04d7f9b..0000000
--- a/core/java/com/android/internal/inputmethod/InputMethodSubtypeHandle.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.inputmethod;
-
-import android.annotation.Nullable;
-import android.text.TextUtils;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodSubtype;
-
-import java.util.Objects;
-
-public class InputMethodSubtypeHandle {
- private final String mInputMethodId;
- private final int mSubtypeId;
-
- public InputMethodSubtypeHandle(InputMethodInfo info, @Nullable InputMethodSubtype subtype) {
- mInputMethodId = info.getId();
- if (subtype != null) {
- mSubtypeId = subtype.hashCode();
- } else {
- mSubtypeId = InputMethodUtils.NOT_A_SUBTYPE_ID;
- }
- }
-
- public InputMethodSubtypeHandle(String inputMethodId, int subtypeId) {
- mInputMethodId = inputMethodId;
- mSubtypeId = subtypeId;
- }
-
- public String getInputMethodId() {
- return mInputMethodId;
- }
-
- public int getSubtypeId() {
- return mSubtypeId;
- }
-
- @Override
- public boolean equals(Object o) {
- if (o == null || !(o instanceof InputMethodSubtypeHandle)) {
- return false;
- }
- InputMethodSubtypeHandle other = (InputMethodSubtypeHandle) o;
- return TextUtils.equals(mInputMethodId, other.getInputMethodId())
- && mSubtypeId == other.getSubtypeId();
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(mInputMethodId) * 31 + mSubtypeId;
- }
-
- @Override
- public String toString() {
- return "InputMethodSubtypeHandle{mInputMethodId=" + mInputMethodId
- + ", mSubtypeId=" + mSubtypeId + "}";
- }
-}
diff --git a/core/java/com/android/internal/util/LatencyTracker.java b/core/java/com/android/internal/util/LatencyTracker.java
index 72cd248..6c3a58c 100644
--- a/core/java/com/android/internal/util/LatencyTracker.java
+++ b/core/java/com/android/internal/util/LatencyTracker.java
@@ -147,8 +147,17 @@
}
mStartRtc.delete(action);
Trace.asyncTraceEnd(Trace.TRACE_TAG_APP, NAMES[action], 0);
- long duration = endRtc - startRtc;
+ logAction(action, (int)(endRtc - startRtc));
+ }
+
+ /**
+ * Logs an action that has started and ended. This needs to be called from the main thread.
+ *
+ * @param action The action to end. One of the ACTION_* values.
+ * @param duration The duration of the action in ms.
+ */
+ public static void logAction(int action, int duration) {
Log.i(TAG, "action=" + action + " latency=" + duration);
- EventLog.writeEvent(EventLogTags.SYSUI_LATENCY, action, (int) duration);
+ EventLog.writeEvent(EventLogTags.SYSUI_LATENCY, action, duration);
}
}
diff --git a/core/java/com/android/internal/util/NotificationMessagingUtil.java b/core/java/com/android/internal/util/NotificationMessagingUtil.java
index 518cf41..b962d4f 100644
--- a/core/java/com/android/internal/util/NotificationMessagingUtil.java
+++ b/core/java/com/android/internal/util/NotificationMessagingUtil.java
@@ -78,6 +78,10 @@
return false;
}
+ return isMessaging(sbn);
+ }
+
+ public boolean isMessaging(StatusBarNotification sbn) {
Class<? extends Notification.Style> style = sbn.getNotification().getNotificationStyle();
if (Notification.MessagingStyle.class.equals(style)) {
return true;
diff --git a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
index 6dff8b4..bf3e8d5 100644
--- a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
@@ -47,6 +47,7 @@
*/
final class CascadingMenuPopup extends MenuPopup implements MenuPresenter, OnKeyListener,
PopupWindow.OnDismissListener {
+ private static final int ITEM_LAYOUT = com.android.internal.R.layout.cascading_menu_item_layout;
@Retention(RetentionPolicy.SOURCE)
@IntDef({HORIZ_POSITION_LEFT, HORIZ_POSITION_RIGHT})
@@ -348,7 +349,7 @@
*/
private void showMenu(@NonNull MenuBuilder menu) {
final LayoutInflater inflater = LayoutInflater.from(mContext);
- final MenuAdapter adapter = new MenuAdapter(menu, inflater, mOverflowOnly);
+ final MenuAdapter adapter = new MenuAdapter(menu, inflater, mOverflowOnly, ITEM_LAYOUT);
// Apply "force show icon" setting. There are 3 cases:
// (1) This is the top level menu and icon spacing is forced. Add spacing.
diff --git a/core/java/com/android/internal/view/menu/MenuAdapter.java b/core/java/com/android/internal/view/menu/MenuAdapter.java
index 2834d39..5bc981b 100644
--- a/core/java/com/android/internal/view/menu/MenuAdapter.java
+++ b/core/java/com/android/internal/view/menu/MenuAdapter.java
@@ -23,8 +23,6 @@
import java.util.ArrayList;
public class MenuAdapter extends BaseAdapter {
- static final int ITEM_LAYOUT = com.android.internal.R.layout.popup_menu_item_layout;
-
MenuBuilder mAdapterMenu;
private int mExpandedIndex = -1;
@@ -32,11 +30,14 @@
private boolean mForceShowIcon;
private final boolean mOverflowOnly;
private final LayoutInflater mInflater;
+ private final int mItemLayoutRes;
- public MenuAdapter(MenuBuilder menu, LayoutInflater inflater, boolean overflowOnly) {
+ public MenuAdapter(MenuBuilder menu, LayoutInflater inflater, boolean overflowOnly,
+ int itemLayoutRes) {
mOverflowOnly = overflowOnly;
mInflater = inflater;
mAdapterMenu = menu;
+ mItemLayoutRes = itemLayoutRes;
findExpandedIndex();
}
@@ -78,7 +79,7 @@
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
- convertView = mInflater.inflate(ITEM_LAYOUT, parent, false);
+ convertView = mInflater.inflate(mItemLayoutRes, parent, false);
}
final int currGroupId = getItem(position).getGroupId();
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index 9d012de..0c5ea63 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.ColorStateList;
+import android.content.res.Resources;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.util.Log;
@@ -33,6 +34,7 @@
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.ViewDebug;
import android.widget.LinearLayout;
@@ -108,13 +110,6 @@
private CharSequence mContentDescription;
private CharSequence mTooltipText;
- private static String sLanguage;
- private static String sPrependShortcutLabel;
- private static String sEnterShortcutLabel;
- private static String sDeleteShortcutLabel;
- private static String sSpaceShortcutLabel;
-
-
/**
* Instantiates this menu item.
*
@@ -130,20 +125,6 @@
MenuItemImpl(MenuBuilder menu, int group, int id, int categoryOrder, int ordering,
CharSequence title, int showAsAction) {
- String lang = menu.getContext().getResources().getConfiguration().locale.toString();
- if (sPrependShortcutLabel == null || !lang.equals(sLanguage)) {
- sLanguage = lang;
- // This is instantiated from the UI thread, so no chance of sync issues
- sPrependShortcutLabel = menu.getContext().getResources().getString(
- com.android.internal.R.string.prepend_shortcut_label);
- sEnterShortcutLabel = menu.getContext().getResources().getString(
- com.android.internal.R.string.menu_enter_shortcut_label);
- sDeleteShortcutLabel = menu.getContext().getResources().getString(
- com.android.internal.R.string.menu_delete_shortcut_label);
- sSpaceShortcutLabel = menu.getContext().getResources().getString(
- com.android.internal.R.string.menu_space_shortcut_label);
- }
-
mMenu = menu;
mId = id;
mGroup = group;
@@ -353,19 +334,45 @@
return "";
}
- StringBuilder sb = new StringBuilder(sPrependShortcutLabel);
+ final Resources res = mMenu.getContext().getResources();
+
+ StringBuilder sb = new StringBuilder();
+ if (ViewConfiguration.get(mMenu.getContext()).hasPermanentMenuKey()) {
+ // Only prepend "Menu+" if there is a hardware menu key.
+ sb.append(res.getString(
+ com.android.internal.R.string.prepend_shortcut_label));
+ }
+
+ final int modifiers =
+ mMenu.isQwertyMode() ? mShortcutAlphabeticModifiers : mShortcutNumericModifiers;
+ appendModifier(sb, modifiers, KeyEvent.META_META_ON, res.getString(
+ com.android.internal.R.string.menu_meta_shortcut_label));
+ appendModifier(sb, modifiers, KeyEvent.META_CTRL_ON, res.getString(
+ com.android.internal.R.string.menu_ctrl_shortcut_label));
+ appendModifier(sb, modifiers, KeyEvent.META_ALT_ON, res.getString(
+ com.android.internal.R.string.menu_alt_shortcut_label));
+ appendModifier(sb, modifiers, KeyEvent.META_SHIFT_ON, res.getString(
+ com.android.internal.R.string.menu_shift_shortcut_label));
+ appendModifier(sb, modifiers, KeyEvent.META_SYM_ON, res.getString(
+ com.android.internal.R.string.menu_sym_shortcut_label));
+ appendModifier(sb, modifiers, KeyEvent.META_FUNCTION_ON, res.getString(
+ com.android.internal.R.string.menu_function_shortcut_label));
+
switch (shortcut) {
case '\n':
- sb.append(sEnterShortcutLabel);
+ sb.append(res.getString(
+ com.android.internal.R.string.menu_enter_shortcut_label));
break;
case '\b':
- sb.append(sDeleteShortcutLabel);
+ sb.append(res.getString(
+ com.android.internal.R.string.menu_delete_shortcut_label));
break;
case ' ':
- sb.append(sSpaceShortcutLabel);
+ sb.append(res.getString(
+ com.android.internal.R.string.menu_space_shortcut_label));
break;
default:
@@ -376,6 +383,12 @@
return sb.toString();
}
+ private static void appendModifier(StringBuilder sb, int mask, int modifier, String label) {
+ if ((mask & modifier) == modifier) {
+ sb.append(label);
+ }
+ }
+
/**
* @return Whether this menu item should be showing shortcuts (depends on
* whether the menu should show shortcuts and whether this item has
diff --git a/core/java/com/android/internal/view/menu/StandardMenuPopup.java b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
index 445379b..d618f67 100644
--- a/core/java/com/android/internal/view/menu/StandardMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
@@ -43,6 +43,7 @@
*/
final class StandardMenuPopup extends MenuPopup implements OnDismissListener, OnItemClickListener,
MenuPresenter, OnKeyListener {
+ private static final int ITEM_LAYOUT = com.android.internal.R.layout.popup_menu_item_layout;
private final Context mContext;
@@ -116,7 +117,7 @@
mMenu = menu;
mOverflowOnly = overflowOnly;
final LayoutInflater inflater = LayoutInflater.from(context);
- mAdapter = new MenuAdapter(menu, inflater, mOverflowOnly);
+ mAdapter = new MenuAdapter(menu, inflater, mOverflowOnly, ITEM_LAYOUT);
mPopupStyleAttr = popupStyleAttr;
mPopupStyleRes = popupStyleRes;
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index e3b1c01..35aae15 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -1784,7 +1784,8 @@
private static Context applyDefaultTheme(Context originalContext) {
TypedArray a = originalContext.obtainStyledAttributes(new int[]{R.attr.isLightTheme});
boolean isLightTheme = a.getBoolean(0, true);
- int themeId = isLightTheme ? R.style.Theme_Material_Light : R.style.Theme_Material;
+ int themeId
+ = isLightTheme ? R.style.Theme_DeviceDefault_Light : R.style.Theme_DeviceDefault;
a.recycle();
return new ContextThemeWrapper(originalContext, themeId);
}
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 5a06f7f..25e1589 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -54,13 +54,6 @@
void userPresent(int userId);
int getStrongAuthForUser(int userId);
- long addEscrowToken(in byte[] token, int userId);
- boolean removeEscrowToken(long handle, int userId);
- boolean isEscrowTokenActive(long handle, int userId);
- boolean setLockCredentialWithToken(String credential, int type, long tokenHandle,
- in byte[] token, int requestedQuality, int userId);
- void unlockUserWithToken(long tokenHandle, in byte[] token, int userId);
-
// Keystore RecoveryController methods.
// {@code ServiceSpecificException} may be thrown to signal an error, which caller can
// convert to {@code RecoveryManagerException}.
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 7eb2f38..bf075bf 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -45,6 +45,7 @@
import android.util.SparseLongArray;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.LocalServices;
import com.google.android.collect.Lists;
import libcore.util.HexEncoding;
@@ -1473,6 +1474,13 @@
}
}
+ private LockSettingsInternal getLockSettingsInternal() {
+ LockSettingsInternal service = LocalServices.getService(LockSettingsInternal.class);
+ if (service == null) {
+ throw new SecurityException("Only available to system server itself");
+ }
+ return service;
+ }
/**
* Create an escrow token for the current user, which can later be used to unlock FBE
* or change user password.
@@ -1481,44 +1489,41 @@
* confirm credential operation in order to activate the token for future use. If the user
* has no secure lockscreen, then the token is activated immediately.
*
+ * <p>This method is only available to code running in the system server process itself.
+ *
* @return a unique 64-bit token handle which is needed to refer to this token later.
*/
public long addEscrowToken(byte[] token, int userId) {
- try {
- return getLockSettings().addEscrowToken(token, userId);
- } catch (RemoteException re) {
- return 0L;
- }
+ return getLockSettingsInternal().addEscrowToken(token, userId);
}
/**
* Remove an escrow token.
+ *
+ * <p>This method is only available to code running in the system server process itself.
+ *
* @return true if the given handle refers to a valid token previously returned from
* {@link #addEscrowToken}, whether it's active or not. return false otherwise.
*/
public boolean removeEscrowToken(long handle, int userId) {
- try {
- return getLockSettings().removeEscrowToken(handle, userId);
- } catch (RemoteException re) {
- return false;
- }
+ return getLockSettingsInternal().removeEscrowToken(handle, userId);
}
/**
* Check if the given escrow token is active or not. Only active token can be used to call
* {@link #setLockCredentialWithToken} and {@link #unlockUserWithToken}
+ *
+ * <p>This method is only available to code running in the system server process itself.
*/
public boolean isEscrowTokenActive(long handle, int userId) {
- try {
- return getLockSettings().isEscrowTokenActive(handle, userId);
- } catch (RemoteException re) {
- return false;
- }
+ return getLockSettingsInternal().isEscrowTokenActive(handle, userId);
}
/**
* Change a user's lock credential with a pre-configured escrow token.
*
+ * <p>This method is only available to code running in the system server process itself.
+ *
* @param credential The new credential to be set
* @param type Credential type: password / pattern / none.
* @param requestedQuality the requested password quality by DevicePolicyManager.
@@ -1530,55 +1535,55 @@
*/
public boolean setLockCredentialWithToken(String credential, int type, int requestedQuality,
long tokenHandle, byte[] token, int userId) {
- try {
- if (type != CREDENTIAL_TYPE_NONE) {
- if (TextUtils.isEmpty(credential) || credential.length() < MIN_LOCK_PASSWORD_SIZE) {
- throw new IllegalArgumentException("password must not be null and at least "
- + "of length " + MIN_LOCK_PASSWORD_SIZE);
- }
- final int quality = computePasswordQuality(type, credential, requestedQuality);
- if (!getLockSettings().setLockCredentialWithToken(credential, type, tokenHandle,
- token, quality, userId)) {
- return false;
- }
- setLong(PASSWORD_TYPE_KEY, quality, userId);
-
- updateEncryptionPasswordIfNeeded(credential, quality, userId);
- updatePasswordHistory(credential, userId);
- } else {
- if (!TextUtils.isEmpty(credential)) {
- throw new IllegalArgumentException("password must be emtpy for NONE type");
- }
- if (!getLockSettings().setLockCredentialWithToken(null, CREDENTIAL_TYPE_NONE,
- tokenHandle, token, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
- userId)) {
- return false;
- }
- setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
- userId);
-
- if (userId == UserHandle.USER_SYSTEM) {
- // Set the encryption password to default.
- updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
- setCredentialRequiredToDecrypt(false);
- }
+ LockSettingsInternal localService = getLockSettingsInternal();
+ if (type != CREDENTIAL_TYPE_NONE) {
+ if (TextUtils.isEmpty(credential) || credential.length() < MIN_LOCK_PASSWORD_SIZE) {
+ throw new IllegalArgumentException("password must not be null and at least "
+ + "of length " + MIN_LOCK_PASSWORD_SIZE);
}
- onAfterChangingPassword(userId);
- return true;
- } catch (RemoteException re) {
- Log.e(TAG, "Unable to save lock password ", re);
- re.rethrowFromSystemServer();
+ final int quality = computePasswordQuality(type, credential, requestedQuality);
+ if (!localService.setLockCredentialWithToken(credential, type, tokenHandle,
+ token, quality, userId)) {
+ return false;
+ }
+ setLong(PASSWORD_TYPE_KEY, quality, userId);
+
+ updateEncryptionPasswordIfNeeded(credential, quality, userId);
+ updatePasswordHistory(credential, userId);
+ } else {
+ if (!TextUtils.isEmpty(credential)) {
+ throw new IllegalArgumentException("password must be emtpy for NONE type");
+ }
+ if (!localService.setLockCredentialWithToken(null, CREDENTIAL_TYPE_NONE,
+ tokenHandle, token, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
+ userId)) {
+ return false;
+ }
+ setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
+ userId);
+
+ if (userId == UserHandle.USER_SYSTEM) {
+ // Set the encryption password to default.
+ updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
+ setCredentialRequiredToDecrypt(false);
+ }
}
- return false;
+ onAfterChangingPassword(userId);
+ return true;
}
- public void unlockUserWithToken(long tokenHandle, byte[] token, int userId) {
- try {
- getLockSettings().unlockUserWithToken(tokenHandle, token, userId);
- } catch (RemoteException re) {
- Log.e(TAG, "Unable to unlock user with token", re);
- re.rethrowFromSystemServer();
- }
+ /**
+ * Unlock the specified user by an pre-activated escrow token. This should have the same effect
+ * on device encryption as the user entering his lockscreen credentials for the first time after
+ * boot, this includes unlocking the user's credential-encrypted storage as well as the keystore
+ *
+ * <p>This method is only available to code running in the system server process itself.
+ *
+ * @return {@code true} if the supplied token is valid and unlock succeeds,
+ * {@code false} otherwise.
+ */
+ public boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId) {
+ return getLockSettingsInternal().unlockUserWithToken(tokenHandle, token, userId);
}
diff --git a/core/java/com/android/internal/widget/LockSettingsInternal.java b/core/java/com/android/internal/widget/LockSettingsInternal.java
new file mode 100644
index 0000000..9de9ef7
--- /dev/null
+++ b/core/java/com/android/internal/widget/LockSettingsInternal.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+
+/**
+ * LockSettingsService local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class LockSettingsInternal {
+
+ /**
+ * Create an escrow token for the current user, which can later be used to unlock FBE
+ * or change user password.
+ *
+ * After adding, if the user currently has lockscreen password, he will need to perform a
+ * confirm credential operation in order to activate the token for future use. If the user
+ * has no secure lockscreen, then the token is activated immediately.
+ *
+ * @return a unique 64-bit token handle which is needed to refer to this token later.
+ */
+ public abstract long addEscrowToken(byte[] token, int userId);
+
+ /**
+ * Remove an escrow token.
+ * @return true if the given handle refers to a valid token previously returned from
+ * {@link #addEscrowToken}, whether it's active or not. return false otherwise.
+ */
+ public abstract boolean removeEscrowToken(long handle, int userId);
+
+ /**
+ * Check if the given escrow token is active or not. Only active token can be used to call
+ * {@link #setLockCredentialWithToken} and {@link #unlockUserWithToken}
+ */
+ public abstract boolean isEscrowTokenActive(long handle, int userId);
+
+ public abstract boolean setLockCredentialWithToken(String credential, int type,
+ long tokenHandle, byte[] token, int requestedQuality, int userId);
+
+ public abstract boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId);
+}
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 8b1de2f..c71e505 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -22,6 +22,7 @@
import android.content.ComponentName;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager;
+import android.os.Build;
import android.os.Environment;
import android.os.Process;
import android.os.storage.StorageManager;
@@ -276,16 +277,20 @@
readPermissions(Environment.buildPath(
Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
- // Allow Vendor to customize system configs around libs, features, permissions and apps
- int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
- ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS;
+ // Vendors are only allowed to customze libs, features and privapp permissions
+ int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS;
+ if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) {
+ // For backward compatibility
+ vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
+ }
readPermissions(Environment.buildPath(
Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
- // Allow ODM to customize system configs around libs, features and apps
- int odmPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_APP_CONFIGS;
+ // Allow ODM to customize system configs as much as Vendor, because /odm is another
+ // vendor partition other than /vendor.
+ int odmPermissionFlag = vendorPermissionFlag;
readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
readPermissions(Environment.buildPath(
@@ -631,7 +636,9 @@
// granting permissions to priv apps in the system partition and vice
// versa.
boolean vendor = permFile.toPath().startsWith(
- Environment.getVendorDirectory().toPath());
+ Environment.getVendorDirectory().toPath())
+ || permFile.toPath().startsWith(
+ Environment.getOdmDirectory().toPath());
boolean product = permFile.toPath().startsWith(
Environment.getProductDirectory().toPath());
if (vendor) {
@@ -656,6 +663,8 @@
}
XmlUtils.skipCurrentTag(parser);
} else {
+ Slog.w(TAG, "Tag " + name + " is unknown or not allowed in "
+ + permFile.getParent());
XmlUtils.skipCurrentTag(parser);
continue;
}
diff --git a/core/java/com/android/server/net/BaseNetdEventCallback.java b/core/java/com/android/server/net/BaseNetdEventCallback.java
new file mode 100644
index 0000000..fdba2f3
--- /dev/null
+++ b/core/java/com/android/server/net/BaseNetdEventCallback.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.net;
+
+import android.net.INetdEventCallback;
+
+/**
+ * Base {@link INetdEventCallback} that provides no-op
+ * implementations which can be overridden.
+ *
+ * @hide
+ */
+public class BaseNetdEventCallback extends INetdEventCallback.Stub {
+ @Override
+ public void onDnsEvent(String hostname, String[] ipAddresses,
+ int ipAddressesCount, long timestamp, int uid) {
+ // default no-op
+ }
+
+ @Override
+ public void onPrivateDnsValidationEvent(int netId, String ipAddress,
+ String hostname, boolean validated) {
+ // default no-op
+ }
+
+ @Override
+ public void onConnectEvent(String ipAddr, int port, long timestamp, int uid) {
+ // default no-op
+ }
+}
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 5498a93..ce4e384 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -921,6 +921,28 @@
SkBitmap skbitmap;
bitmap->getSkBitmap(&skbitmap);
+ if (skbitmap.colorType() == kRGBA_F16_SkColorType) {
+ // Convert to P3 before encoding. This matches SkAndroidCodec::computeOutputColorSpace
+ // for wide gamuts.
+ auto cs = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kDCIP3_D65_Gamut);
+ auto info = skbitmap.info().makeColorType(kRGBA_8888_SkColorType)
+ .makeColorSpace(std::move(cs));
+ SkBitmap p3;
+ if (!p3.tryAllocPixels(info)) {
+ return JNI_FALSE;
+ }
+ auto xform = SkColorSpaceXform::New(skbitmap.colorSpace(), info.colorSpace());
+ if (!xform) {
+ return JNI_FALSE;
+ }
+ if (!xform->apply(SkColorSpaceXform::kRGBA_8888_ColorFormat, p3.getPixels(),
+ SkColorSpaceXform::kRGBA_F16_ColorFormat, skbitmap.getPixels(),
+ info.width() * info.height(), kUnpremul_SkAlphaType)) {
+ return JNI_FALSE;
+ }
+ skbitmap = p3;
+ }
return SkEncodeImage(strm.get(), skbitmap, fm, quality) ? JNI_TRUE : JNI_FALSE;
}
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index f5c09fd..f70cf07 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -546,12 +546,16 @@
}
};
-static jlong create(JNIEnv* env, jclass clazz, jlong rootNodePtr, jlong surfacePtr) {
+static jlong create(JNIEnv* env, jclass clazz, jlong rootNodePtr, jlong surfacePtr,
+ jboolean isWideColorGamut) {
RenderNode* rootNode = reinterpret_cast<RenderNode*>(rootNodePtr);
sp<Surface> surface(reinterpret_cast<Surface*>(surfacePtr));
ContextFactory factory;
RenderProxy* proxy = new RenderProxy(false, rootNode, &factory);
proxy->loadSystemProperties();
+ if (isWideColorGamut) {
+ proxy->setWideGamut(true);
+ }
proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
proxy->initialize(surface);
// Shadows can't be used via this interface, so just set the light source
@@ -620,7 +624,7 @@
{"nativeSetAutoRefreshEnabled", "(JZ)I", (void*)nativeSetAutoRefreshEnabled},
// HWUI context
- {"nHwuiCreate", "(JJ)J", (void*) hwui::create },
+ {"nHwuiCreate", "(JJZ)J", (void*) hwui::create },
{"nHwuiSetSurface", "(JJ)V", (void*) hwui::setSurface },
{"nHwuiDraw", "(J)V", (void*) hwui::draw },
{"nHwuiDestroy", "(J)V", (void*) hwui::destroy },
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index d6fe568..d05be2c 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -488,6 +488,8 @@
if (errno != 0) {
ALOGW("Unable to set the name of current thread to '%s': %s", buf, strerror(errno));
}
+ // Update base::logging default tag.
+ android::base::SetDefaultTag(buf);
}
// The list of open zygote file descriptors.
@@ -685,10 +687,10 @@
// Make it easier to debug audit logs by setting the main thread's name to the
// nice name rather than "app_process".
- if (se_info_c_str == NULL && is_system_server) {
+ if (se_name_c_str == NULL && is_system_server) {
se_name_c_str = "system_server";
}
- if (se_info_c_str != NULL) {
+ if (se_name_c_str != NULL) {
SetThreadName(se_name_c_str);
}
diff --git a/core/proto/README.md b/core/proto/README.md
new file mode 100644
index 0000000..d2b89a5
--- /dev/null
+++ b/core/proto/README.md
@@ -0,0 +1,41 @@
+Conventions for the protos in this directory:
+
+1. As in the rest of Android, use 4 spaces to indent instead of 2.
+
+1. For protos based on Java files, use the same package as the Java file. For
+ example, `com.android.server.thing` instead of `com.android.server.thing.proto`.
+
+1. If the proto describes the top level output of dumpsys, it should contain
+ `Dump`. This makes it easy to understand that the proto is the dumpsys output
+ of a certain service, not the data structure of that service, e.g.
+ `WindowManagerServiceDumpProto` vs `WindowManagerServiceDumpProto`.
+
+ * Inner messages whose containing messages have the `Proto` suffix do not
+ need to have a `Proto` suffix. E.g:
+
+```
+message FooProto {
+ message Bar {
+ ...
+ }
+}
+```
+
+ vs
+
+```
+message FooProto {
+ message BarProto {
+ ...
+ }
+}
+```
+
+1. If the proto represents the structure of an object, it should have `Proto` as
+ its suffix. Please also include the full package path of the original object
+ as a comment to the proto message.
+
+1. Include units in the field names. For example, `screen_time_ms` vs
+ `screen_time`, or `file_size_bytes` or `file_size_mebibytes` vs `file_size`.
+
+1. Leave field numbers 50,000 - 100,000 reserved for OEMs.
diff --git a/core/proto/android/bluetooth/enums.proto b/core/proto/android/bluetooth/enums.proto
index 06ae2d3..9e459e6 100644
--- a/core/proto/android/bluetooth/enums.proto
+++ b/core/proto/android/bluetooth/enums.proto
@@ -21,10 +21,23 @@
option java_multiple_files = true;
// Bluetooth connection states.
-// Primarily used by android/bluetooth/BluetoothAdapter.java
enum ConnectionStateEnum {
CONNECTION_STATE_DISCONNECTED = 0;
CONNECTION_STATE_CONNECTING = 1;
CONNECTION_STATE_CONNECTED = 2;
CONNECTION_STATE_DISCONNECTING = 3;
+}
+
+// Bluetooth Adapter Enable and Disable Reasons
+enum EnableDisableReasonEnum {
+ ENABLE_DISABLE_REASON_UNSPECIFIED = 0;
+ ENABLE_DISABLE_REASON_APPLICATION_REQUEST = 1;
+ ENABLE_DISABLE_REASON_AIRPLANE_MODE = 2;
+ ENABLE_DISABLE_REASON_DISALLOWED = 3;
+ ENABLE_DISABLE_REASON_RESTARTED = 4;
+ ENABLE_DISABLE_REASON_START_ERROR = 5;
+ ENABLE_DISABLE_REASON_SYSTEM_BOOT = 6;
+ ENABLE_DISABLE_REASON_CRASH = 7;
+ ENABLE_DISABLE_REASON_USER_SWITCH = 8;
+ ENABLE_DISABLE_REASON_RESTORE_USER_SETTING = 9;
}
\ No newline at end of file
diff --git a/core/proto/android/os/batterystats.proto b/core/proto/android/os/batterystats.proto
index 9915174..f468143 100644
--- a/core/proto/android/os/batterystats.proto
+++ b/core/proto/android/os/batterystats.proto
@@ -641,9 +641,7 @@
message Job {
option (android.msg_privacy).dest = DEST_AUTOMATIC;
- optional string name = 1 [
- (android.privacy).dest = DEST_EXPLICIT
- ];
+ optional string name = 1;
// Job times aren't apportioned.
optional TimerProto total = 2;
optional TimerProto background = 3;
@@ -654,9 +652,7 @@
option (android.msg_privacy).dest = DEST_AUTOMATIC;
// Job name.
- optional string name = 1 [
- (android.privacy).dest = DEST_EXPLICIT
- ];
+ optional string name = 1;
message ReasonCount {
option (android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -801,9 +797,7 @@
message Sync {
option (android.msg_privacy).dest = DEST_AUTOMATIC;
- optional string name = 1 [
- (android.privacy).dest = DEST_EXPLICIT
- ];
+ optional string name = 1;
// Sync times aren't apportioned.
optional TimerProto total = 2;
optional TimerProto background = 3;
@@ -842,9 +836,7 @@
message Wakelock {
option (android.msg_privacy).dest = DEST_AUTOMATIC;
- optional string name = 1 [
- (android.privacy).dest = DEST_EXPLICIT
- ];
+ optional string name = 1;
// Full wakelocks keep the screen on. Based on
// PowerManager.SCREEN_BRIGHT_WAKE_LOCK (deprecated in API 13) and
@@ -876,9 +868,7 @@
option (android.msg_privacy).dest = DEST_AUTOMATIC;
// Wakeup alarm name.
- optional string name = 1 [
- (android.privacy).dest = DEST_EXPLICIT
- ];
+ optional string name = 1;
// Only includes counts when screen-off (& on battery).
optional int32 count = 2;
}
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index bb9568b..4657dc4 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -280,4 +280,7 @@
(section).type = SECTION_DUMPSYS,
(section).args = "usb --proto"
];
+
+ // Reserved for OEMs.
+ extensions 50000 to 100000;
}
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index d7ba421..914a7db 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -433,9 +433,11 @@
optional SettingProto show_mute_in_crash_dialog = 352 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingsProto show_zen_upgrade_notification = 354 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingsProto app_auto_restriction_enabled = 359 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingsProto zen_duration = 360 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
// Please insert fields in the same order as in
// frameworks/base/core/java/android/provider/Settings.java.
- // Next tag = 360;
+ // Next tag = 361;
}
message SecureSettingsProto {
diff --git a/core/proto/android/server/animationadapter.proto b/core/proto/android/server/animationadapter.proto
new file mode 100644
index 0000000..c4ffe8c
--- /dev/null
+++ b/core/proto/android/server/animationadapter.proto
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+syntax = "proto2";
+
+import "frameworks/base/core/proto/android/graphics/point.proto";
+import "frameworks/base/core/proto/android/view/remote_animation_target.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
+package com.android.server.wm.proto;
+option java_multiple_files = true;
+
+message AnimationAdapterProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional LocalAnimationAdapterProto local = 1;
+ optional RemoteAnimationAdapterWrapperProto remote = 2;
+}
+
+/* represents RemoteAnimationAdapterWrapper */
+message RemoteAnimationAdapterWrapperProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional .android.view.RemoteAnimationTargetProto target = 1;
+}
+
+/* represents LocalAnimationAdapter */
+message LocalAnimationAdapterProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional AnimationSpecProto animation_spec = 1;
+}
+
+message AnimationSpecProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional WindowAnimationSpecProto window = 1;
+ optional MoveAnimationSpecProto move = 2;
+ optional AlphaAnimationSpecProto alpha = 3;
+}
+
+/* represents WindowAnimationSpec */
+message WindowAnimationSpecProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional string animation = 1;
+}
+
+/* represents MoveAnimationSpec*/
+message MoveAnimationSpecProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional .android.graphics.PointProto from = 1;
+ optional .android.graphics.PointProto to = 2;
+ optional int64 duration = 3;
+}
+
+/* represents AlphaAnimationSpec */
+message AlphaAnimationSpecProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional float from = 1;
+ optional float to = 2;
+ optional int64 duration = 3;
+}
\ No newline at end of file
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index 69abed3..9193129 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -614,7 +614,6 @@
CONSTRAINT_DEADLINE = 5;
CONSTRAINT_IDLE = 6;
CONSTRAINT_CONNECTIVITY = 7;
- CONSTRAINT_APP_NOT_IDLE = 8;
CONSTRAINT_CONTENT_TRIGGER = 9;
CONSTRAINT_DEVICE_NOT_DOZING = 10;
}
diff --git a/core/proto/android/server/powermanagerservice.proto b/core/proto/android/server/powermanagerservice.proto
index 5cb5319..64aa98b 100644
--- a/core/proto/android/server/powermanagerservice.proto
+++ b/core/proto/android/server/powermanagerservice.proto
@@ -315,4 +315,6 @@
optional bool is_double_tap_wake_enabled = 37;
// True if we are currently in VR Mode.
optional bool is_vr_mode_enabled = 38;
+ // True if Sidekick is controlling the display and we shouldn't change its power mode.
+ optional bool draw_wake_lock_override_from_sidekick = 39;
}
diff --git a/core/proto/android/server/surfaceanimator.proto b/core/proto/android/server/surfaceanimator.proto
index 7f7839e..dcc2b34 100644
--- a/core/proto/android/server/surfaceanimator.proto
+++ b/core/proto/android/server/surfaceanimator.proto
@@ -16,6 +16,7 @@
syntax = "proto2";
+import "frameworks/base/core/proto/android/server/animationadapter.proto";
import "frameworks/base/core/proto/android/view/surfacecontrol.proto";
import "frameworks/base/libs/incident/proto/android/privacy.proto";
@@ -28,7 +29,8 @@
message SurfaceAnimatorProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
- optional string animation_adapter = 1;
+ reserved 1; // Was string animation_adapter = 1
optional .android.view.SurfaceControlProto leash = 2;
optional bool animation_start_delayed = 3;
+ optional AnimationAdapterProto animation_adapter = 4;
}
\ No newline at end of file
diff --git a/core/proto/android/view/remote_animation_target.proto b/core/proto/android/view/remote_animation_target.proto
new file mode 100644
index 0000000..d5da0a9
--- /dev/null
+++ b/core/proto/android/view/remote_animation_target.proto
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+syntax = "proto2";
+option java_package = "android.app";
+option java_multiple_files = true;
+
+package android.view;
+
+import "frameworks/base/core/proto/android/app/window_configuration.proto";
+import "frameworks/base/core/proto/android/graphics/point.proto";
+import "frameworks/base/core/proto/android/graphics/rect.proto";
+import "frameworks/base/core/proto/android/view/surfacecontrol.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
+/** Proto representation for RemoteAnimationTarget.java class. */
+message RemoteAnimationTargetProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional int32 task_id = 1;
+ optional int32 mode = 2;
+ optional .android.view.SurfaceControlProto leash = 3;
+ optional bool is_translucent = 4;
+ optional .android.graphics.RectProto clip_rect = 5;
+ optional .android.graphics.RectProto contentInsets = 6;
+ optional int32 prefix_order_index = 7;
+ optional .android.graphics.PointProto position = 8;
+ optional .android.graphics.RectProto source_container_bounds = 9;
+ optional .android.app.WindowConfigurationProto window_configuration = 10;
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7aec812..9b11a33 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -56,6 +56,7 @@
<protected-broadcast android:name="android.intent.action.SPLIT_CONFIGURATION_CHANGED" />
<protected-broadcast android:name="android.intent.action.LOCALE_CHANGED" />
<protected-broadcast android:name="android.intent.action.BATTERY_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.BATTERY_LEVEL_CHANGED" />
<protected-broadcast android:name="android.intent.action.BATTERY_LOW" />
<protected-broadcast android:name="android.intent.action.BATTERY_OKAY" />
<protected-broadcast android:name="android.intent.action.ACTION_POWER_CONNECTED" />
@@ -2551,6 +2552,12 @@
<permission android:name="android.permission.MANAGE_APP_OPS_RESTRICTIONS"
android:protectionLevel="signature|installer" />
+ <!-- Allows an application to update the user app op modes.
+ Not for use by third party apps.
+ @hide -->
+ <permission android:name="android.permission.MANAGE_APP_OPS_MODES"
+ android:protectionLevel="signature|installer|verifier" />
+
<!-- @SystemApi Allows an application to open windows that are for use by parts
of the system user interface.
<p>Not for use by third-party applications.
@@ -3088,7 +3095,8 @@
<!-- Allows an application to collect usage infomation about brightness slider changes.
<p>Not for use by third-party applications.</p>
@hide
- @SystemApi -->
+ @SystemApi
+ @TestApi -->
<permission android:name="android.permission.BRIGHTNESS_SLIDER_USAGE"
android:protectionLevel="signature|privileged|development" />
@@ -3101,7 +3109,8 @@
<!-- Allows an application to modify the display brightness configuration
@hide
- @SystemApi -->
+ @SystemApi
+ @TestApi -->
<permission android:name="android.permission.CONFIGURE_DISPLAY_BRIGHTNESS"
android:protectionLevel="signature|privileged|development" />
diff --git a/core/res/res/drawable/floating_popup_background_dark.xml b/core/res/res/drawable/floating_popup_background_dark.xml
index ded1137..c4b4448 100644
--- a/core/res/res/drawable/floating_popup_background_dark.xml
+++ b/core/res/res/drawable/floating_popup_background_dark.xml
@@ -16,8 +16,8 @@
*/
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
+ android:shape="rectangle">
<solid android:color="@color/background_floating_material_dark" />
- <corners android:radius="2dp" />
+ <corners android:radius="?android:attr/dialogCornerRadius" />
</shape>
diff --git a/core/res/res/drawable/floating_popup_background_light.xml b/core/res/res/drawable/floating_popup_background_light.xml
index 9c7a886..767140d 100644
--- a/core/res/res/drawable/floating_popup_background_light.xml
+++ b/core/res/res/drawable/floating_popup_background_light.xml
@@ -18,6 +18,6 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/background_floating_material_light" />
- <corners android:radius="2dp" />
+ <corners android:radius="?android:attr/dialogCornerRadius" />
</shape>
diff --git a/core/res/res/drawable/ic_corp_user_badge.xml b/core/res/res/drawable/ic_corp_user_badge.xml
index 6a0d902..a08f2d4 100644
--- a/core/res/res/drawable/ic_corp_user_badge.xml
+++ b/core/res/res/drawable/ic_corp_user_badge.xml
@@ -2,7 +2,8 @@
android:width="36dp"
android:height="36dp"
android:viewportWidth="36.0"
- android:viewportHeight="36.0">
+ android:viewportHeight="36.0"
+ android:tint="?attr/colorControlNormal">
<path
android:pathData="M16.3,11.3h3.4v1.7h-3.4z"
android:fillColor="#FFFFFF"/>
diff --git a/core/res/res/layout/cascading_menu_item_layout.xml b/core/res/res/layout/cascading_menu_item_layout.xml
new file mode 100644
index 0000000..7d18635
--- /dev/null
+++ b/core/res/res/layout/cascading_menu_item_layout.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<!-- Keep in sync with popup_menu_item_layout.xml (which only differs in the title and shortcut
+ position). -->
+<com.android.internal.view.menu.ListMenuItemView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minWidth="196dip"
+ android:orientation="vertical" >
+
+ <ImageView
+ android:id="@+id/group_divider"
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:layout_marginTop="4dip"
+ android:layout_marginBottom="4dip"
+ android:background="@drawable/list_divider_material" />
+
+ <LinearLayout
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/dropdownListPreferredItemHeight"
+ android:paddingEnd="16dip"
+ android:duplicateParentState="true" >
+
+ <!-- Icon will be inserted here. -->
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="16dip"
+ android:textAppearance="?attr/textAppearanceLargePopupMenu"
+ android:singleLine="true"
+ android:duplicateParentState="true"
+ android:textAlignment="viewStart" />
+
+ <Space
+ android:layout_width="0dip"
+ android:layout_height="1dip"
+ android:layout_weight="1"/>
+
+ <TextView
+ android:id="@+id/shortcut"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="16dip"
+ android:textAppearance="?attr/textAppearanceSmallPopupMenu"
+ android:singleLine="true"
+ android:duplicateParentState="true"
+ android:textAlignment="viewEnd" />
+
+ <ImageView
+ android:id="@+id/submenuarrow"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginStart="8dp"
+ android:scaleType="center"
+ android:visibility="gone" />
+
+ <!-- Checkbox, and/or radio button will be inserted here. -->
+
+ </LinearLayout>
+
+</com.android.internal.view.menu.ListMenuItemView>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 021e88e..4a72bf9 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2125,29 +2125,32 @@
Defaults to {@code default}.
@see android.view.WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
- @see android.view.WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
+ @see android.view.WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
@see android.view.WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
@see android.view.DisplayCutout
@see android.R.attr#layoutInDisplayCutoutMode -->
<attr name="windowLayoutInDisplayCutoutMode">
<!-- The window is allowed to extend into the {@code DisplayCutout} area, only if the
- {@code DisplayCutout} is fully contained within the status bar. Otherwise, the window is
+ {@code DisplayCutout} is fully contained within a system bar. Otherwise, the window is
laid out such that it does not overlap with the {@code DisplayCutout} area.
@see android.view.DisplayCutout
@see android.view.WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
-->
<enum name="default" value="0" />
- <!-- The window is always allowed to extend into the {@code DisplayCutout} area,
- even if fullscreen or in landscape.
+ <!--
+ The window is always allowed to extend into the {@code DisplayCutout} areas on the short
+ edges of the screen even if fullscreen or in landscape.
+ The window will never extend into a {@link DisplayCutout} area on the long edges of the
+ screen.
<p>
The window must make sure that no important content overlaps with the
{@link DisplayCutout}.
@see android.view.DisplayCutout
- @see android.view.WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
+ @see android.view.WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
-->
- <enum name="always" value="1" />
+ <enum name="shortEdges" value="1" />
<!-- The window is never allowed to overlap with the DisplayCutout area.
<p>
This should be used with windows that transiently set {@code SYSTEM_UI_FLAG_FULLSCREEN}
@@ -7978,9 +7981,7 @@
android.content.pm.PackageInfo#getLongVersionCode()} for the target package.
-->
<attr name="maxLongVersionCode" format="string" />
- <!-- The resource id of view that contains the URL bar of the HTML page being loaded.
- Typically used when compatibility mode is used in a browser.
- -->
+ <!-- TODO(b/74445943): STOPSHIP (urlBarResourceId should be removed after P DP2 is branched)-->
<attr name="urlBarResourceId" format="string" />
</declare-styleable>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f1c9f67..cf13d1c 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2396,6 +2396,7 @@
<!-- depends on ImportanceExtractor-->
<item>com.android.server.notification.NotificationIntrusivenessExtractor</item>
<item>com.android.server.notification.VisibilityExtractor</item>
+ <!-- Depends on ZenModeExtractor -->
<item>com.android.server.notification.BadgeExtractor</item>
</string-array>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 7d5d1ba..2c0deed 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2869,6 +2869,7 @@
<public name="outlineSpotShadowColor" />
<public name="outlineAmbientShadowColor" />
<public name="maxLongVersionCode" />
+ <!-- TODO(b/74445943): STOPSHIP (urlBarResourceId should be removed after P DP2 is branched)-->
<public name="urlBarResourceId" />
<!-- @hide @SystemApi -->
<public name="userRestriction" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 15dffc0..93e765b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -148,16 +148,16 @@
<string name="CLIRPermanent">You can\'t change the caller ID setting.</string>
<!-- Notification title to tell the user that data service is blocked by access control. -->
- <string name="RestrictedOnDataTitle">No data service</string>
+ <string name="RestrictedOnDataTitle">No mobile data service</string>
<!-- Notification title to tell the user that emergency calling is blocked by access control. -->
- <string name="RestrictedOnEmergencyTitle">No emergency calling</string>
+ <string name="RestrictedOnEmergencyTitle">Emergency calling unavailable</string>
<!-- Notification title to tell the user that normal service is blocked by access control. -->
<string name="RestrictedOnNormalTitle">No voice service</string>
<!-- Notification title to tell the user that all emergency and normal voice services are blocked by access control. -->
- <string name="RestrictedOnAllVoiceTitle">No voice/emergency service</string>
+ <string name="RestrictedOnAllVoiceTitle">No voice service or emergency calling</string>
<!-- Notification content to tell the user that voice/data/emergency service is blocked by access control. -->
- <string name="RestrictedStateContent">Temporarily not offered by the mobile network at your location</string>
+ <string name="RestrictedStateContent">Temporarily turned off by your carrier</string>
<!-- Displayed to tell the user that they should switch their network preference. -->
<string name="NetworkPreferenceSwitchTitle">Can\u2019t reach network</string>
@@ -352,9 +352,6 @@
<!-- Work profile deleted notification--> <skip />
<!-- Shows up in the notification's title when the system deletes the work profile. [CHAR LIMIT=NONE] -->
<string name="work_profile_deleted">Work profile deleted</string>
- <!-- Content text for a notification. The Title of the notification is "Work profile deleted".
- This says that the profile is deleted by the system as a result of the current profile owner gone missing. [CHAR LIMIT=100]-->
- <string name="work_profile_deleted_description">Work profile deleted due to missing admin app</string>
<!-- Content text for an expanded notification. The Title of the notification is "Work profile deleted".
This further explains that the profile is deleted by the system as a result of the current profile admin gone missing. [CHAR LIMIT=NONE]-->
<string name="work_profile_deleted_details">The work profile admin app is either missing or corrupted.
@@ -2447,6 +2444,18 @@
<string name="more_item_label">More</string>
<!-- Prepended to the shortcut for a menu item to indicate that the user should hold the MENU button together with the shortcut to invoke the item. For example, if the shortcut to open a new tab in browser is MENU and B together, then this would be prepended to the letter "B" -->
<string name="prepend_shortcut_label">Menu+</string>
+ <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the META key together with the shortcut to invoke the item. -->
+ <string name="menu_meta_shortcut_label">Meta+</string>
+ <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the CTRL key together with the shortcut to invoke the item. -->
+ <string name="menu_ctrl_shortcut_label">Ctrl+</string>
+ <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the ALT key together with the shortcut to invoke the item. -->
+ <string name="menu_alt_shortcut_label">Alt+</string>
+ <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the SHIFT key together with the shortcut to invoke the item. -->
+ <string name="menu_shift_shortcut_label">Shift+</string>
+ <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the SYM key together with the shortcut to invoke the item. -->
+ <string name="menu_sym_shortcut_label">Sym+</string>
+ <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the FUNCTION key together with the shortcut to invoke the item. -->
+ <string name="menu_function_shortcut_label">Function+</string>
<!-- Displayed in place of the regular shortcut letter when a menu item has Menu+space for the shortcut. -->
<string name="menu_space_shortcut_label">space</string>
<!-- Displayed in place of the regular shortcut letter when a menu item has Menu+enter for the shortcut. -->
@@ -4490,7 +4499,7 @@
<!-- Zen mode condition - summary: time duration in hours. [CHAR LIMIT=NONE] -->
<plurals name="zen_mode_duration_hours_summary">
- <item quantity="one">For one hour (until <xliff:g id="formattedTime" example="10:00 PM">%2$s</xliff:g>)</item>
+ <item quantity="one">For 1 hour (until <xliff:g id="formattedTime" example="10:00 PM">%2$s</xliff:g>)</item>
<item quantity="other">For %1$d hours (until <xliff:g id="formattedTime" example="10:00 PM">%2$s</xliff:g>)</item>
</plurals>
@@ -4514,7 +4523,7 @@
<!-- Zen mode condition - line one: time duration in hours. [CHAR LIMIT=NONE] -->
<plurals name="zen_mode_duration_hours">
- <item quantity="one">For one hour</item>
+ <item quantity="one">For 1 hour</item>
<item quantity="other">For %d hours</item>
</plurals>
@@ -4883,7 +4892,7 @@
<!-- Title for the notification channel notifying user of settings system changes (i.e. Do Not Disturb has changed). [CHAR LIMIT=NONE] -->
<string name="notification_channel_system_changes">System changes</string>
<!-- Title of notification indicating do not disturb settings have changed when upgrading to P -->
- <string name="zen_upgrade_notification_title">Do Not Disturb has changed</string>
+ <string name="zen_upgrade_notification_title">Do Not Disturb is hiding notifications to help you focus</string>
<!-- Content of notification indicating users can tap on the notification to go to dnd behavior settings -->
- <string name="zen_upgrade_notification_content">Tap to check your behavior settings for interruptions</string>
+ <string name="zen_upgrade_notification_content">This is a new feature from the latest system update. Tap to change.</string>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index fa0fb94..30193a8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -528,9 +528,15 @@
<java-symbol type="string" name="delete" />
<java-symbol type="string" name="deleteText" />
<java-symbol type="string" name="grant_permissions_header_text" />
+ <java-symbol type="string" name="menu_alt_shortcut_label" />
+ <java-symbol type="string" name="menu_ctrl_shortcut_label" />
<java-symbol type="string" name="menu_delete_shortcut_label" />
<java-symbol type="string" name="menu_enter_shortcut_label" />
+ <java-symbol type="string" name="menu_function_shortcut_label" />
+ <java-symbol type="string" name="menu_meta_shortcut_label" />
<java-symbol type="string" name="menu_space_shortcut_label" />
+ <java-symbol type="string" name="menu_shift_shortcut_label" />
+ <java-symbol type="string" name="menu_sym_shortcut_label" />
<java-symbol type="string" name="notification_title" />
<java-symbol type="string" name="permission_request_notification_with_subtitle" />
<java-symbol type="string" name="prepend_shortcut_label" />
@@ -1421,6 +1427,7 @@
<java-symbol type="layout" name="action_menu_layout" />
<java-symbol type="layout" name="action_mode_close_item" />
<java-symbol type="layout" name="alert_dialog" />
+ <java-symbol type="layout" name="cascading_menu_item_layout" />
<java-symbol type="layout" name="choose_account" />
<java-symbol type="layout" name="choose_account_row" />
<java-symbol type="layout" name="choose_account_type" />
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index fdbcd8a..25b053b 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -1318,6 +1318,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- volume background -->
+ <item name="panelColorBackground">@color/primary_material_light</item>
</style>
<style name="Theme.DeviceDefault.QuickSettings.Dialog" parent="Theme.DeviceDefault.Light.Dialog">
diff --git a/core/res/res/xml/default_zen_mode_config.xml b/core/res/res/xml/default_zen_mode_config.xml
index 5e463d8..2d3cd1c 100644
--- a/core/res/res/xml/default_zen_mode_config.xml
+++ b/core/res/res/xml/default_zen_mode_config.xml
@@ -18,7 +18,9 @@
-->
<!-- Default configuration for zen mode. See android.service.notification.ZenModeConfig. -->
-<zen version="4">
+<zen version="5">
<allow alarms="true" media="true" system="false" calls="false" messages="false" reminders="false"
events="false" />
+ <!-- all visual effects that exist as of P -->
+ <disallow suppressedVisualEffect="511" />
</zen>
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 53c22f6..0f019e71 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1379,6 +1379,10 @@
android:theme="@style/Theme">
</activity>
+ <activity android:name="android.app.activity.ActivityThreadTest$TestActivity"
+ android:exported="true">
+ </activity>
+
<activity
android:name="android.os.TestVrActivity"
android:enableVrMode="com.android.frameworks.coretests/android.os.TestVrActivity$TestVrListenerService">
diff --git a/core/tests/coretests/AndroidTest.xml b/core/tests/coretests/AndroidTest.xml
index 970a0f0..7b5ad9a 100644
--- a/core/tests/coretests/AndroidTest.xml
+++ b/core/tests/coretests/AndroidTest.xml
@@ -14,15 +14,16 @@
limitations under the License.
-->
<configuration description="Runs Frameworks Core Tests.">
- <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
<option name="test-file-name" value="FrameworksCoreTests.apk" />
<option name="test-file-name" value="BstatsTestApp.apk" />
</target_preparer>
-
- <option name="test-suite-tag" value="apct" />
<option name="test-tag" value="FrameworksCoreTests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.frameworks.coretests" />
- <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
</test>
</configuration>
diff --git a/core/tests/coretests/res/values/styles.xml b/core/tests/coretests/res/values/styles.xml
index ef3a481..bcde4c1 100644
--- a/core/tests/coretests/res/values/styles.xml
+++ b/core/tests/coretests/res/values/styles.xml
@@ -25,8 +25,8 @@
<style name="LayoutInDisplayCutoutModeDefault">
<item name="android:windowLayoutInDisplayCutoutMode">default</item>
</style>
- <style name="LayoutInDisplayCutoutModeAlways">
- <item name="android:windowLayoutInDisplayCutoutMode">always</item>
+ <style name="LayoutInDisplayCutoutModeShortEdges">
+ <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
<style name="LayoutInDisplayCutoutModeNever">
<item name="android:windowLayoutInDisplayCutoutMode">never</item>
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
new file mode 100644
index 0000000..4628aa9
--- /dev/null
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.activity;
+
+import android.app.Activity;
+import android.app.IApplicationThread;
+import android.app.servertransaction.ActivityRelaunchItem;
+import android.app.servertransaction.ClientTransaction;
+import android.app.servertransaction.ClientTransactionItem;
+import android.app.servertransaction.ResumeActivityItem;
+import android.content.Intent;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.MergedConfiguration;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test for verifying {@link android.app.ActivityThread} class.
+ */
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class ActivityThreadTest {
+
+ private final ActivityTestRule mActivityTestRule =
+ new ActivityTestRule(TestActivity.class, true /* initialTouchMode */,
+ false /* launchActivity */);
+
+ @Test
+ public void testDoubleRelaunch() throws Exception {
+ final Activity activity = mActivityTestRule.launchActivity(new Intent());
+ final IApplicationThread appThread = activity.getActivityThread().getApplicationThread();
+
+ appThread.scheduleTransaction(newRelaunchResumeTransaction(activity));
+ appThread.scheduleTransaction(newRelaunchResumeTransaction(activity));
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ }
+
+ @Test
+ public void testResumeAfterRelaunch() throws Exception {
+ final Activity activity = mActivityTestRule.launchActivity(new Intent());
+ final IApplicationThread appThread = activity.getActivityThread().getApplicationThread();
+
+ appThread.scheduleTransaction(newRelaunchResumeTransaction(activity));
+ appThread.scheduleTransaction(newResumeTransaction(activity));
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ }
+
+ private static ClientTransaction newRelaunchResumeTransaction(Activity activity) {
+ final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(null,
+ null, 0, new MergedConfiguration(),
+ false /* preserveWindow */);
+ final ResumeActivityItem resumeStateRequest =
+ ResumeActivityItem.obtain(true /* isForward */);
+ final IApplicationThread appThread = activity.getActivityThread().getApplicationThread();
+ final ClientTransaction transaction =
+ ClientTransaction.obtain(appThread, activity.getActivityToken());
+ transaction.addCallback(callbackItem);
+ transaction.setLifecycleStateRequest(resumeStateRequest);
+
+ return transaction;
+ }
+
+ private static ClientTransaction newResumeTransaction(Activity activity) {
+ final ResumeActivityItem resumeStateRequest =
+ ResumeActivityItem.obtain(true /* isForward */);
+ final IApplicationThread appThread = activity.getActivityThread().getApplicationThread();
+ final ClientTransaction transaction =
+ ClientTransaction.obtain(appThread, activity.getActivityToken());
+ transaction.setLifecycleStateRequest(resumeStateRequest);
+
+ return transaction;
+ }
+
+ // Test activity
+ public static class TestActivity extends Activity {
+ }
+}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 6c72ac1..22a261e 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -263,6 +263,7 @@
Settings.Global.LOW_BATTERY_SOUND,
Settings.Global.LOW_BATTERY_SOUND_TIMEOUT,
Settings.Global.LOW_POWER_MODE,
+ Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX,
Settings.Global.LTE_SERVICE_FORCED,
Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
Settings.Global.MDC_INITIAL_MAX_RETRY,
diff --git a/core/tests/coretests/src/android/view/DisplayCutoutTest.java b/core/tests/coretests/src/android/view/DisplayCutoutTest.java
index d807353..6e9401d 100644
--- a/core/tests/coretests/src/android/view/DisplayCutoutTest.java
+++ b/core/tests/coretests/src/android/view/DisplayCutoutTest.java
@@ -17,7 +17,6 @@
package android.view;
import static android.view.DisplayCutout.NO_CUTOUT;
-import static android.view.DisplayCutout.fromBoundingRect;
import static android.view.DisplayCutout.fromSpec;
import static org.hamcrest.Matchers.not;
@@ -29,17 +28,17 @@
import static org.junit.Assert.assertTrue;
import android.graphics.Rect;
-import android.graphics.Region;
import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.util.Size;
import android.view.DisplayCutout.ParcelableWrapper;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Arrays;
+
@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
@@ -48,7 +47,7 @@
/** This is not a consistent cutout. Useful for verifying insets in one go though. */
final DisplayCutout mCutoutNumbers = new DisplayCutout(
new Rect(1, 2, 3, 4),
- new Region(5, 6, 7, 8), new Size(9, 10));
+ Arrays.asList(new Rect(5, 6, 7, 8)));
final DisplayCutout mCutoutTop = createCutoutTop();
@@ -70,7 +69,7 @@
@Test
public void getBoundingRect() throws Exception {
- assertEquals(new Rect(50, 0, 75, 100), mCutoutTop.getBoundingRect());
+ assertEquals(new Rect(50, 0, 75, 100), mCutoutTop.getBounds().getBounds());
}
@Test
@@ -154,91 +153,7 @@
public void inset_bounds() throws Exception {
DisplayCutout cutout = mCutoutTop.inset(1, 2, 3, 4);
- assertEquals(new Rect(49, -2, 74, 98), cutout.getBoundingRect());
- }
-
- @Test
- public void computeSafeInsets_top() throws Exception {
- DisplayCutout cutout = fromBoundingRect(0, 0, 100, 20)
- .computeSafeInsets(200, 400);
-
- assertEquals(new Rect(0, 20, 0, 0), cutout.getSafeInsets());
- }
-
- @Test
- public void computeSafeInsets_left() throws Exception {
- DisplayCutout cutout = fromBoundingRect(0, 0, 20, 100)
- .computeSafeInsets(400, 200);
-
- assertEquals(new Rect(20, 0, 0, 0), cutout.getSafeInsets());
- }
-
- @Test
- public void computeSafeInsets_bottom() throws Exception {
- DisplayCutout cutout = fromBoundingRect(0, 180, 100, 200)
- .computeSafeInsets(100, 200);
-
- assertEquals(new Rect(0, 0, 0, 20), cutout.getSafeInsets());
- }
-
- @Test
- public void computeSafeInsets_right() throws Exception {
- DisplayCutout cutout = fromBoundingRect(180, 0, 200, 100)
- .computeSafeInsets(200, 100);
-
- assertEquals(new Rect(0, 0, 20, 0), cutout.getSafeInsets());
- }
-
- @Test
- public void computeSafeInsets_bounds() throws Exception {
- DisplayCutout cutout = mCutoutTop.computeSafeInsets(1000, 2000);
-
- assertEquals(mCutoutTop.getBoundingRect(), cutout.getBounds().getBounds());
- }
-
- @Test
- public void calculateRelativeTo_top() throws Exception {
- DisplayCutout cutout = fromBoundingRect(0, 0, 100, 20)
- .computeSafeInsets(200, 400)
- .calculateRelativeTo(new Rect(5, 5, 95, 195));
-
- assertEquals(new Rect(0, 15, 0, 0), cutout.getSafeInsets());
- }
-
- @Test
- public void calculateRelativeTo_left() throws Exception {
- DisplayCutout cutout = fromBoundingRect(0, 0, 20, 100)
- .computeSafeInsets(400, 200)
- .calculateRelativeTo(new Rect(5, 5, 195, 95));
-
- assertEquals(new Rect(15, 0, 0, 0), cutout.getSafeInsets());
- }
-
- @Test
- public void calculateRelativeTo_bottom() throws Exception {
- DisplayCutout cutout = fromBoundingRect(0, 180, 100, 200)
- .computeSafeInsets(100, 200)
- .calculateRelativeTo(new Rect(5, 5, 95, 195));
-
- assertEquals(new Rect(0, 0, 0, 15), cutout.getSafeInsets());
- }
-
- @Test
- public void calculateRelativeTo_right() throws Exception {
- DisplayCutout cutout = fromBoundingRect(180, 0, 200, 100)
- .computeSafeInsets(200, 100)
- .calculateRelativeTo(new Rect(5, 5, 195, 95));
-
- assertEquals(new Rect(0, 0, 15, 0), cutout.getSafeInsets());
- }
-
- @Test
- public void calculateRelativeTo_bounds() throws Exception {
- DisplayCutout cutout = fromBoundingRect(0, 0, 100, 20)
- .computeSafeInsets(200, 400)
- .calculateRelativeTo(new Rect(5, 10, 95, 180));
-
- assertEquals(new Rect(-5, -10, 95, 10), cutout.getBounds().getBounds());
+ assertEquals(new Rect(49, -2, 74, 98), cutout.getBounds().getBounds());
}
@Test
@@ -276,26 +191,26 @@
@Test
public void fromSpec_caches() {
- DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 1f);
- assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 1f), sameInstance(cached));
+ DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f);
+ assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), sameInstance(cached));
}
@Test
public void fromSpec_wontCacheIfSpecChanges() {
- DisplayCutout cached = fromSpec("L1,0 L1000,1000 L0,1 z", 200, 1f);
- assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 1f), not(sameInstance(cached)));
+ DisplayCutout cached = fromSpec("L1,0 L1000,1000 L0,1 z", 200, 400, 1f);
+ assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached)));
}
@Test
public void fromSpec_wontCacheIfScreenWidthChanges() {
- DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 2000, 1f);
- assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 1f), not(sameInstance(cached)));
+ DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 2000, 400, 1f);
+ assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached)));
}
@Test
public void fromSpec_wontCacheIfDensityChanges() {
- DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 2f);
- assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 1f), not(sameInstance(cached)));
+ DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 2f);
+ assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached)));
}
@Test
@@ -348,7 +263,6 @@
private static DisplayCutout createCutoutWithInsets(int left, int top, int right, int bottom) {
return new DisplayCutout(
new Rect(left, top, right, bottom),
- new Region(50, 0, 75, 100),
- null);
+ Arrays.asList(new Rect(50, 0, 75, 100)));
}
}
diff --git a/core/tests/coretests/src/android/view/textclassifier/SelectionEventTest.java b/core/tests/coretests/src/android/view/textclassifier/SelectionEventTest.java
new file mode 100644
index 0000000..b77982b
--- /dev/null
+++ b/core/tests/coretests/src/android/view/textclassifier/SelectionEventTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 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.view.textclassifier;
+
+import static org.junit.Assert.assertEquals;
+
+import android.os.Parcel;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SelectionEventTest {
+
+ @Test
+ public void testParcel() {
+ final SelectionEvent[] captured = new SelectionEvent[1];
+ final Logger logger = new Logger(new Logger.Config(
+ InstrumentationRegistry.getTargetContext(), Logger.WIDGET_TEXTVIEW, null)) {
+ @Override
+ public void writeEvent(SelectionEvent event) {
+ captured[0] = event;
+ }
+ };
+ logger.logSelectionStartedEvent(SelectionEvent.INVOCATION_MANUAL, 0);
+ final SelectionEvent event = captured[0];
+ final Parcel parcel = Parcel.obtain();
+ event.writeToParcel(parcel, event.describeContents());
+ parcel.setDataPosition(0);
+ assertEquals(event, SelectionEvent.CREATOR.createFromParcel(parcel));
+ }
+}
diff --git a/core/tests/coretests/src/android/view/textclassifier/logging/GenerateLinksLoggerTest.java b/core/tests/coretests/src/android/view/textclassifier/logging/GenerateLinksLoggerTest.java
index b920ca3..8e4f02c 100644
--- a/core/tests/coretests/src/android/view/textclassifier/logging/GenerateLinksLoggerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/logging/GenerateLinksLoggerTest.java
@@ -26,6 +26,7 @@
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.util.ArrayMap;
+import android.view.textclassifier.GenerateLinksLogger;
import android.view.textclassifier.TextClassifier;
import android.view.textclassifier.TextLinks;
diff --git a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java
index c8994dd..002df88 100644
--- a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java
+++ b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java
@@ -19,6 +19,7 @@
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
@@ -74,12 +75,12 @@
}
@Test
- public void layoutInDisplayCutoutMode_always() throws Exception {
- createPhoneWindowWithTheme(R.style.LayoutInDisplayCutoutModeAlways);
+ public void layoutInDisplayCutoutMode_shortEdges() throws Exception {
+ createPhoneWindowWithTheme(R.style.LayoutInDisplayCutoutModeShortEdges);
installDecor();
assertThat(mPhoneWindow.getAttributes().layoutInDisplayCutoutMode,
- is(LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS));
+ is(LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES));
}
@Test
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/TestApplication.java b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/TestApplication.java
index dece9a4..bcf9490 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/TestApplication.java
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/TestApplication.java
@@ -16,7 +16,7 @@
package com.android.multidexlegacyandexception;
-import android.support.multidex.MultiDexApplication;
+import androidx.multidex.MultiDexApplication;
public class TestApplication extends MultiDexApplication {
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/MultiDexAndroidJUnitRunner.java b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/MultiDexAndroidJUnitRunner.java
index 758ac1d..92a3b0c 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/MultiDexAndroidJUnitRunner.java
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/MultiDexAndroidJUnitRunner.java
@@ -17,7 +17,7 @@
package com.android.multidexlegacyandexception.tests;
import android.os.Bundle;
-import android.support.multidex.MultiDex;
+import androidx.multidex.MultiDex;
import android.support.test.runner.AndroidJUnitRunner;
public class MultiDexAndroidJUnitRunner extends AndroidJUnitRunner {
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/src/com/android/multidexlegacytestapp/TestApplication.java b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/src/com/android/multidexlegacytestapp/TestApplication.java
index c52ad29..f89d132 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/src/com/android/multidexlegacytestapp/TestApplication.java
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/src/com/android/multidexlegacytestapp/TestApplication.java
@@ -16,7 +16,7 @@
package com.android.multidexlegacytestapp;
-import android.support.multidex.MultiDexApplication;
+import androidx.multidex.MultiDexApplication;
import java.lang.annotation.Annotation;
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/src/com/android/multidexlegacytestapp/test2/MultiDexAndroidJUnitRunner.java b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/src/com/android/multidexlegacytestapp/test2/MultiDexAndroidJUnitRunner.java
index 963f904..9e41a92 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/src/com/android/multidexlegacytestapp/test2/MultiDexAndroidJUnitRunner.java
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/src/com/android/multidexlegacytestapp/test2/MultiDexAndroidJUnitRunner.java
@@ -1,7 +1,7 @@
package com.android.multidexlegacytestapp.test2;
import android.os.Bundle;
-import android.support.multidex.MultiDex;
+import androidx.multidex.MultiDex;
import android.support.test.runner.AndroidJUnitRunner;
public class MultiDexAndroidJUnitRunner extends AndroidJUnitRunner {
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppWithCorruptedDex/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppWithCorruptedDex/AndroidManifest.xml
index 7993c6f..5f006fe 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppWithCorruptedDex/AndroidManifest.xml
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppWithCorruptedDex/AndroidManifest.xml
@@ -9,7 +9,7 @@
android:targetSdkVersion="18" />
<application
- android:name="android.support.multidex.MultiDexApplication"
+ android:name="androidx.multidex.MultiDexApplication"
android:allowBackup="true"
android:label="MultiDexLegacyTestApp_corrupted">
<activity
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/src/com/android/framework/multidexlegacytestservices/AbstractService.java b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/src/com/android/framework/multidexlegacytestservices/AbstractService.java
index cb0a591..bbb4944 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/src/com/android/framework/multidexlegacytestservices/AbstractService.java
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/src/com/android/framework/multidexlegacytestservices/AbstractService.java
@@ -20,7 +20,7 @@
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
-import android.support.multidex.MultiDex;
+import androidx.multidex.MultiDex;
import android.util.Log;
import java.io.File;
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/AndroidManifest.xml
index c7b066d..f3f11b9 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/AndroidManifest.xml
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/AndroidManifest.xml
@@ -9,7 +9,7 @@
android:targetSdkVersion="18" />
<application
- android:name="android.support.multidex.MultiDexApplication"
+ android:name="androidx.multidex.MultiDexApplication"
android:allowBackup="true"
android:label="MultiDexLegacyVersionedTestApp_v1">
<activity
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/AndroidManifest.xml
index 4d24793..e43e56b 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/AndroidManifest.xml
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/AndroidManifest.xml
@@ -9,7 +9,7 @@
android:targetSdkVersion="18" />
<application
- android:name="android.support.multidex.MultiDexApplication"
+ android:name="androidx.multidex.MultiDexApplication"
android:allowBackup="true"
android:label="MultiDexLegacyVersionedTestApp_v2">
<activity
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/AndroidManifest.xml
index 76c92dd..1d97228 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/AndroidManifest.xml
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/AndroidManifest.xml
@@ -9,7 +9,7 @@
android:targetSdkVersion="18" />
<application
- android:name="android.support.multidex.MultiDexApplication"
+ android:name="androidx.multidex.MultiDexApplication"
android:allowBackup="true"
android:label="MultiDexLegacyVersionedTestApp_v3">
<activity
diff --git a/data/etc/hiddenapi-package-whitelist.xml b/data/etc/hiddenapi-package-whitelist.xml
index 1d46d42..be0372d 100644
--- a/data/etc/hiddenapi-package-whitelist.xml
+++ b/data/etc/hiddenapi-package-whitelist.xml
@@ -67,6 +67,8 @@
<hidden-api-whitelisted-app package="com.android.pacprocessor" />
<hidden-api-whitelisted-app package="com.android.phone" />
<hidden-api-whitelisted-app package="com.android.pmc" />
+ <hidden-api-whitelisted-app package="com.android.printservice.recommendation" />
+ <hidden-api-whitelisted-app package="com.android.printspooler" />
<hidden-api-whitelisted-app package="com.android.providers.blockednumber" />
<hidden-api-whitelisted-app package="com.android.providers.contacts" />
<hidden-api-whitelisted-app package="com.android.providers.downloads" />
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 5602a3e..88701fa 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -493,7 +493,7 @@
private boolean mRequireUnpremultiplied = false;
private boolean mMutable = false;
private boolean mConserveMemory = false;
- private boolean mAsAlphaMask = false;
+ private boolean mDecodeAsAlphaMask = false;
private Rect mCropRect;
private Rect mOutPaddingRect;
private Source mSource;
@@ -730,7 +730,7 @@
* Will typically result in a {@link Bitmap.Config#HARDWARE}
* allocation, but may be software for small images. In addition, this will
* switch to software when HARDWARE is incompatible, e.g.
- * {@link #setMutable}, {@link #setAsAlphaMask}.
+ * {@link #setMutable}, {@link #setDecodeAsAlphaMask}.
*/
public static final int ALLOCATOR_DEFAULT = 0;
@@ -753,7 +753,7 @@
* Require a {@link Bitmap.Config#HARDWARE} {@link Bitmap}.
*
* When this is combined with incompatible options, like
- * {@link #setMutable} or {@link #setAsAlphaMask}, {@link #decodeDrawable}
+ * {@link #setMutable} or {@link #setDecodeAsAlphaMask}, {@link #decodeDrawable}
* / {@link #decodeBitmap} will throw an
* {@link java.lang.IllegalStateException}.
*/
@@ -783,6 +783,14 @@
}
/**
+ * Return the allocator for the pixel memory.
+ */
+ @Allocator
+ public int getAllocator() {
+ return mAllocator;
+ }
+
+ /**
* Specify whether the {@link Bitmap} should have unpremultiplied pixels.
*
* <p>By default, ImageDecoder will create a {@link Bitmap} with
@@ -803,6 +811,13 @@
}
/**
+ * Return whether the {@link Bitmap} will have unpremultiplied pixels.
+ */
+ public boolean getRequireUnpremultiplied() {
+ return mRequireUnpremultiplied;
+ }
+
+ /**
* Modify the image after decoding and scaling.
*
* <p>This allows adding effects prior to returning a {@link Drawable} or
@@ -823,6 +838,14 @@
}
/**
+ * Return the {@link PostProcessor} currently set.
+ */
+ @Nullable
+ public PostProcessor getPostProcessor() {
+ return mPostProcessor;
+ }
+
+ /**
* Set (replace) the {@link OnPartialImageListener} on this object.
*
* <p>Will be called if there is an error in the input. Without one, an
@@ -836,6 +859,14 @@
}
/**
+ * Return the {@link OnPartialImageListener} currently set.
+ */
+ @Nullable
+ public OnPartialImageListener getOnPartialImageListener() {
+ return mOnPartialImageListener;
+ }
+
+ /**
* Crop the output to {@code subset} of the (possibly) scaled image.
*
* <p>{@code subset} must be contained within the size set by
@@ -855,6 +886,14 @@
}
/**
+ * Return the cropping rectangle, if set.
+ */
+ @Nullable
+ public Rect getCrop() {
+ return mCropRect;
+ }
+
+ /**
* Set a Rect for retrieving nine patch padding.
*
* If the image is a nine patch, this Rect will be set to the padding
@@ -893,6 +932,13 @@
}
/**
+ * Return whether the {@link Bitmap} will be mutable.
+ */
+ public boolean getMutable() {
+ return mMutable;
+ }
+
+ /**
* Specify whether to potentially save RAM at the expense of quality.
*
* <p>Setting this to {@code true} may result in a {@link Bitmap} with a
@@ -912,24 +958,62 @@
}
/**
+ * Return whether this object will try to save RAM at the expense of quality.
+ *
+ * <p>This returns whether {@link #setConserveMemory} was set to {@code true}.
+ * It may still return {@code true} even if the {@code ImageDecoder} does not
+ * have a way to save RAM at the expense of quality for this image.</p>
+ */
+ public boolean getConserveMemory() {
+ return mConserveMemory;
+ }
+
+ /**
* Specify whether to potentially treat the output as an alpha mask.
*
* <p>If this is set to {@code true} and the image is encoded in a format
* with only one channel, treat that channel as alpha. Otherwise this call has
* no effect.</p>
*
- * <p>setAsAlphaMask is incompatible with {@link #ALLOCATOR_HARDWARE}. Trying to
+ * <p>setDecodeAsAlphaMask is incompatible with {@link #ALLOCATOR_HARDWARE}. Trying to
* combine them will result in {@link #decodeDrawable}/
* {@link #decodeBitmap} throwing an
* {@link java.lang.IllegalStateException}.</p>
*
* @return this object for chaining.
*/
- public ImageDecoder setAsAlphaMask(boolean asAlphaMask) {
- mAsAlphaMask = asAlphaMask;
+ public ImageDecoder setDecodeAsAlphaMask(boolean decodeAsAlphaMask) {
+ mDecodeAsAlphaMask = decodeAsAlphaMask;
return this;
}
+ /** @removed
+ * @deprecated Call {@link #setDecodeAsAlphaMask} instead.
+ */
+ @java.lang.Deprecated
+ public ImageDecoder setAsAlphaMask(boolean asAlphaMask) {
+ return this.setDecodeAsAlphaMask(asAlphaMask);
+ }
+
+ /**
+ * Return whether to treat single channel input as alpha.
+ *
+ * <p>This returns whether {@link #setDecodeAsAlphaMask} was set to {@code true}.
+ * It may still return {@code true} even if the image has more than one
+ * channel and therefore will not be treated as an alpha mask.</p>
+ */
+ public boolean getDecodeAsAlphaMask() {
+ return mDecodeAsAlphaMask;
+ }
+
+ /** @removed
+ * @deprecated Call {@link #getDecodeAsAlphaMask} instead.
+ */
+ @java.lang.Deprecated
+ public boolean getAsAlphaMask() {
+ return this.getDecodeAsAlphaMask();
+ }
+
@Override
public void close() {
mCloseGuard.close();
@@ -960,7 +1044,7 @@
if (mMutable) {
throw new IllegalStateException("Cannot make mutable HARDWARE Bitmap!");
}
- if (mAsAlphaMask) {
+ if (mDecodeAsAlphaMask) {
throw new IllegalStateException("Cannot make HARDWARE Alpha mask Bitmap!");
}
}
@@ -992,7 +1076,7 @@
return nDecodeBitmap(mNativePtr, partialImagePtr,
postProcessPtr, mDesiredWidth, mDesiredHeight, mCropRect,
mMutable, mAllocator, mRequireUnpremultiplied,
- mConserveMemory, mAsAlphaMask);
+ mConserveMemory, mDecodeAsAlphaMask);
}
private void callHeaderDecoded(@Nullable OnHeaderDecodedListener listener,
@@ -1224,7 +1308,7 @@
int width, int height,
@Nullable Rect cropRect, boolean mutable,
int allocator, boolean requireUnpremul,
- boolean conserveMemory, boolean asAlphaMask)
+ boolean conserveMemory, boolean decodeAsAlphaMask)
throws IOException;
private static native Size nGetSampledSize(long nativePtr,
int sampleSize);
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index f27c11d..20c22b7 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -167,10 +167,8 @@
nativeSetDefault(t.native_instance);
}
- // TODO: Make this public API. (b/64852739)
- /** @hide */
- @VisibleForTesting
- public int getWeight() {
+ /** Returns the typeface's weight value */
+ public @IntRange(from = 0, to = 1000) int getWeight() {
return mWeight;
}
@@ -883,6 +881,15 @@
}
/**
+ * This method is used by supportlib-v27.
+ * TODO: Remove private API use in supportlib: http://b/72665240
+ */
+ private static Typeface createFromFamiliesWithDefault(FontFamily[] families, int weight,
+ int italic) {
+ return createFromFamiliesWithDefault(families, DEFAULT_FAMILY, weight, italic);
+ }
+
+ /**
* Create a new typeface from an array of font families, including
* also the font families in the fallback list.
* @param fallbackName the family name. If given families don't support characters, the
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 813eae7..35790b6 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -6,10 +6,7 @@
//"hwui_bugreport_font_cache_usage",
//"hwui_compile_for_perf",
"hwui_pgo",
- // Disable LTO temporarily. LTO does not seem to interact well with
- // PGO profile-file updates and incremental builds in the build
- // servers.
- // "hwui_lto",
+ "hwui_lto",
],
cpp_std: "c++17",
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 44d9099..3dd6879 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -3002,6 +3002,7 @@
// from OMX_VIDEO_HEVCPROFILETYPE
public static final int HEVCProfileMain = 0x01;
public static final int HEVCProfileMain10 = 0x02;
+ public static final int HEVCProfileMainStill = 0x04;
public static final int HEVCProfileMain10HDR10 = 0x1000;
// from OMX_VIDEO_HEVCLEVELTYPE
@@ -3078,6 +3079,23 @@
* {@link VideoCapabilities} to determine the codec capabilities.
*/
public int level;
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj instanceof CodecProfileLevel) {
+ CodecProfileLevel other = (CodecProfileLevel)obj;
+ return other.profile == profile && other.level == level;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Long.hashCode(((long)profile << Integer.SIZE) | level);
+ }
};
/**
diff --git a/media/java/android/media/MediaController2.java b/media/java/android/media/MediaController2.java
index 2a3967c..b51c662 100644
--- a/media/java/android/media/MediaController2.java
+++ b/media/java/android/media/MediaController2.java
@@ -156,17 +156,6 @@
@NonNull List<MediaItem2> playlist) { }
/**
- * Called when the playback state is changed.
- *
- * @param controller the controller for this event
- * @param state latest playback state
- * @hide
- */
- // TODO(jaewan): Remove (b/73971431)
- public void onPlaybackStateChanged(@NonNull MediaController2 controller,
- @NonNull PlaybackState2 state) { }
-
- /**
* Called when the player state is changed.
*
* @param controller the controller for this event
@@ -647,20 +636,6 @@
}
/**
- * Get the lastly cached {@link PlaybackState2} from
- * {@link ControllerCallback#onPlaybackStateChanged(MediaController2, PlaybackState2)}.
- * <p>
- * It may return {@code null} before the first callback or session has sent {@code null}
- * playback state.
- *
- * @return a playback state. Can be {@code null}
- * @hide
- */
- public @Nullable PlaybackState2 getPlaybackState() {
- return mProvider.getPlaybackState_impl();
- }
-
- /**
* Get the lastly cached player state from
* {@link ControllerCallback#onPlayerStateChanged(MediaController2, int)}.
*
@@ -748,7 +723,14 @@
}
/**
- * Return playlist from the session.
+ * Returns the cached playlist from
+ * {@link ControllerCallback#onPlaylistChanged(MediaController2, MediaPlaylistAgent, List,
+ * MediaMetadata2)}.
+ * <p>
+ * This list may differ with the list that was specified with
+ * {@link #setPlaylist(List, MediaMetadata2)} depending on the {@link MediaPlaylistAgent}
+ * implementation. Use media items returned here for other playlist agent APIs such as
+ * {@link MediaPlaylistAgent#skipToPlaylistItem(MediaItem2)}.
*
* @return playlist. Can be {@code null} if the controller doesn't have enough permission.
*/
@@ -758,12 +740,19 @@
/**
* Sets the playlist.
+ * <p>
+ * Even when the playlist is successfully set, use the playlist returned from
+ * {@link #getPlaylist()} for playlist APIs such as {@link #skipToPlaylistItem(MediaItem2)}.
+ * Otherwise the session in the remote process can't distinguish between media items.
*
* @param list playlist
* @param metadata metadata of the playlist
+ * @see #getPlaylist()
+ * @see ControllerCallback#onPlaylistChanged(
+ * MediaController2, MediaPlaylistAgent, List, MediaMetadata2)
*/
public void setPlaylist(@NonNull List<MediaItem2> list, @Nullable MediaMetadata2 metadata) {
- // TODO(jaewan): Implement (b/74174649)
+ mProvider.setPlaylist_impl(list, metadata);
}
/**
@@ -772,17 +761,20 @@
* @param metadata metadata of the playlist
*/
public void updatePlaylistMetadata(@Nullable MediaMetadata2 metadata) {
- // TODO(jaewan): Implement (b/74174649)
+ mProvider.updatePlaylistMetadata_impl(metadata);
}
/**
- * Returns the playlist metadata
+ * Gets the lastly cached playlist playlist metadata either from
+ * {@link ControllerCallback#onPlaylistMetadataChanged(
+ * MediaController2, MediaPlaylistAgent, MediaMetadata2)} or
+ * {@link ControllerCallback#onPlaylistChanged(
+ * MediaController2, MediaPlaylistAgent, List, MediaMetadata2)}.
*
* @return metadata metadata of the playlist, or null if none is set
*/
public @Nullable MediaMetadata2 getPlaylistMetadata() {
- // TODO(jaewan): Implement (b/74174649)
- return null;
+ return mProvider.getPlaylistMetadata_impl();
}
/**
@@ -797,15 +789,14 @@
}
/**
- * Inserts the media item to the play list at position index.
+ * Inserts the media item to the playlist at position index.
* <p>
* This will not change the currently playing media item.
- * If index is less than or equal to the current index of the play list,
- * the current index of the play list will be incremented correspondingly.
+ * If index is less than or equal to the current index of the playlist,
+ * the current index of the playlist will be incremented correspondingly.
*
* @param index the index you want to add
* @param item the media item you want to add
- * @throws IndexOutOfBoundsException if index is outside play list range
*/
public void addPlaylistItem(int index, @NonNull MediaItem2 item) {
mProvider.addPlaylistItem_impl(index, item);
@@ -816,6 +807,8 @@
*<p>
* If the item is the currently playing item of the playlist, current playback
* will be stopped and playback moves to next source in the list.
+ *
+ * @param item the media item you want to add
*/
public void removePlaylistItem(@NonNull MediaItem2 item) {
mProvider.removePlaylistItem_impl(item);
diff --git a/media/java/android/media/MediaItem2.java b/media/java/android/media/MediaItem2.java
index 2db1392..b50c3e4 100644
--- a/media/java/android/media/MediaItem2.java
+++ b/media/java/android/media/MediaItem2.java
@@ -65,6 +65,13 @@
}
/**
+ * @hide
+ */
+ public MediaItem2Provider getProvider() {
+ return mProvider;
+ }
+
+ /**
* Return this object as a bundle to share between processes.
*
* @return a new bundle instance
@@ -141,9 +148,7 @@
@Override
public boolean equals(Object obj) {
- // TODO(jaewan): Override this. MediaItem2 may have auto-generated srcId when the DSD isn't
- // set, and it should be compared for the equals.
- return super.equals(obj);
+ return mProvider.equals_impl(obj);
}
/**
diff --git a/media/java/android/media/MediaLibraryService2.java b/media/java/android/media/MediaLibraryService2.java
index a956bb3..6cab430 100644
--- a/media/java/android/media/MediaLibraryService2.java
+++ b/media/java/android/media/MediaLibraryService2.java
@@ -73,7 +73,7 @@
* Callback for the {@link MediaLibrarySession}.
*/
public static class MediaLibrarySessionCallback extends MediaSession2.SessionCallback {
- public MediaLibrarySessionCallback(Context context) {
+ public MediaLibrarySessionCallback(@NonNull Context context) {
super(context);
}
@@ -226,7 +226,7 @@
}
@Override
- public Builder setVolumeProvider(@NonNull VolumeProvider2 volumeProvider) {
+ public Builder setVolumeProvider(@Nullable VolumeProvider2 volumeProvider) {
return super.setVolumeProvider(volumeProvider);
}
@@ -236,12 +236,12 @@
}
@Override
- public Builder setId(String id) {
+ public Builder setId(@NonNull String id) {
return super.setId(id);
}
@Override
- public Builder setSessionCallback(@NonNull Executor executor,
+ public Builder setSessionCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull MediaLibrarySessionCallback callback) {
return super.setSessionCallback(executor, callback);
}
diff --git a/media/java/android/media/MediaMetadata2.java b/media/java/android/media/MediaMetadata2.java
index 502f929..fb12065 100644
--- a/media/java/android/media/MediaMetadata2.java
+++ b/media/java/android/media/MediaMetadata2.java
@@ -562,7 +562,7 @@
* @param key The key the value is stored under
* @return a CharSequence value, or null
*/
- public @Nullable CharSequence getText(@TextKey String key) {
+ public @Nullable CharSequence getText(@NonNull @TextKey String key) {
return mProvider.getText_impl(key);
}
@@ -611,7 +611,7 @@
* @param key The key the value is stored under
* @return A {@link Rating2} or {@code null}
*/
- public @Nullable Rating2 getRating(@RatingKey String key) {
+ public @Nullable Rating2 getRating(@NonNull @RatingKey String key) {
return mProvider.getRating_impl(key);
}
@@ -622,7 +622,7 @@
* @param key The key the value is stored under
* @return A {@link Bitmap} or null
*/
- public Bitmap getBitmap(@BitmapKey String key) {
+ public @Nullable Bitmap getBitmap(@NonNull @BitmapKey String key) {
return mProvider.getBitmap_impl(key);
}
@@ -749,7 +749,8 @@
* @param value The CharSequence value to store
* @return The Builder to allow chaining
*/
- public @NonNull Builder putText(@TextKey String key, @Nullable CharSequence value) {
+ public @NonNull Builder putText(@NonNull @TextKey String key,
+ @Nullable CharSequence value) {
return mProvider.putText_impl(key, value);
}
@@ -780,7 +781,8 @@
* @param value The String value to store
* @return The Builder to allow chaining
*/
- public @NonNull Builder putString(@TextKey String key, @Nullable String value) {
+ public @NonNull Builder putString(@NonNull @TextKey String key,
+ @Nullable String value) {
return mProvider.putString_impl(key, value);
}
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 745eb74d..1aeed6d 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -17,6 +17,8 @@
package android.media;
import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
@@ -30,7 +32,7 @@
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-
+import java.util.List;
import java.util.Map;
/**
@@ -367,27 +369,79 @@
private native Bitmap _getFrameAtTime(long timeUs, int option, int width, int height);
+ public static final class BitmapParams {
+ private Bitmap.Config inPreferredConfig = Bitmap.Config.ARGB_8888;
+ private Bitmap.Config outActualConfig = Bitmap.Config.ARGB_8888;
+
+ /**
+ * Create a default BitmapParams object. By default, it uses {@link Bitmap.Config#ARGB_8888}
+ * as the preferred bitmap config.
+ */
+ public BitmapParams() {}
+
+ /**
+ * Set the preferred bitmap config for the decoder to decode into.
+ *
+ * If not set, or the request cannot be met, the decoder will output
+ * in {@link Bitmap.Config#ARGB_8888} config by default.
+ *
+ * After decode, the actual config used can be retrieved by {@link #getActualConfig()}.
+ *
+ * @param config the preferred bitmap config to use.
+ */
+ public void setPreferredConfig(@NonNull Bitmap.Config config) {
+ if (config == null) {
+ throw new IllegalArgumentException("preferred config can't be null");
+ }
+ inPreferredConfig = config;
+ }
+
+ /**
+ * Retrieve the preferred bitmap config in the params.
+ *
+ * @return the preferred bitmap config.
+ */
+ public @NonNull Bitmap.Config getPreferredConfig() {
+ return inPreferredConfig;
+ }
+
+ /**
+ * Get the actual bitmap config used to decode the bitmap after the decoding.
+ *
+ * @return the actual bitmap config used.
+ */
+ public @NonNull Bitmap.Config getActualConfig() {
+ return outActualConfig;
+ }
+ }
+
/**
* This method retrieves a video frame by its index. It should only be called
* after {@link #setDataSource}.
*
+ * After the bitmap is returned, you can query the actual parameters that were
+ * used to create the bitmap from the {@code BitmapParams} argument, for instance
+ * to query the bitmap config used for the bitmap with {@link BitmapParams#getActualConfig}.
+ *
* @param frameIndex 0-based index of the video frame. The frame index must be that of
* a valid frame. The total number of frames available for retrieval can be queried
* via the {@link #METADATA_KEY_VIDEO_FRAME_COUNT} key.
+ * @param params BitmapParams that controls the returned bitmap config (such as pixel formats).
+ * If null, default config will be chosen.
*
* @throws IllegalStateException if the container doesn't contain video or image sequences.
* @throws IllegalArgumentException if the requested frame index does not exist.
*
* @return A Bitmap containing the requested video frame, or null if the retrieval fails.
*
- * @see #getFramesAtIndex(int, int)
+ * @see #getFramesAtIndex(int, int, BitmapParams)
*/
- public Bitmap getFrameAtIndex(int frameIndex) {
- Bitmap[] bitmaps = getFramesAtIndex(frameIndex, 1);
- if (bitmaps == null || bitmaps.length < 1) {
+ public Bitmap getFrameAtIndex(int frameIndex, @Nullable BitmapParams params) {
+ List<Bitmap> bitmaps = getFramesAtIndex(frameIndex, 1, params);
+ if (bitmaps == null || bitmaps.size() < 1) {
return null;
}
- return bitmaps[0];
+ return bitmaps.get(0);
}
/**
@@ -395,24 +449,31 @@
* specified index. It should only be called after {@link #setDataSource}.
*
* If the caller intends to retrieve more than one consecutive video frames,
- * this method is preferred over {@link #getFrameAtIndex(int)} for efficiency.
+ * this method is preferred over {@link #getFrameAtIndex(int, BitmapParams)} for efficiency.
+ *
+ * After the bitmaps are returned, you can query the actual parameters that were
+ * used to create the bitmaps from the {@code BitmapParams} argument, for instance
+ * to query the bitmap config used for the bitmaps with {@link BitmapParams#getActualConfig}.
*
* @param frameIndex 0-based index of the first video frame to retrieve. The frame index
* must be that of a valid frame. The total number of frames available for retrieval
* can be queried via the {@link #METADATA_KEY_VIDEO_FRAME_COUNT} key.
* @param numFrames number of consecutive video frames to retrieve. Must be a positive
* value. The stream must contain at least numFrames frames starting at frameIndex.
+ * @param params BitmapParams that controls the returned bitmap config (such as pixel formats).
+ * If null, default config will be chosen.
*
* @throws IllegalStateException if the container doesn't contain video or image sequences.
* @throws IllegalArgumentException if the frameIndex or numFrames is invalid, or the
* stream doesn't contain at least numFrames starting at frameIndex.
- * @return An array of Bitmaps containing the requested video frames. The returned
+ * @return An list of Bitmaps containing the requested video frames. The returned
* array could contain less frames than requested if the retrieval fails.
*
- * @see #getFrameAtIndex(int)
+ * @see #getFrameAtIndex(int, BitmapParams)
*/
- public Bitmap[] getFramesAtIndex(int frameIndex, int numFrames) {
+ public List<Bitmap> getFramesAtIndex(
+ int frameIndex, int numFrames, @Nullable BitmapParams params) {
if (!"yes".equals(extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO))) {
throw new IllegalStateException("Does not contail video or image sequences");
}
@@ -424,24 +485,32 @@
throw new IllegalArgumentException("Invalid frameIndex or numFrames: "
+ frameIndex + ", " + numFrames);
}
- return _getFrameAtIndex(frameIndex, numFrames);
+ return _getFrameAtIndex(frameIndex, numFrames, params);
}
- private native Bitmap[] _getFrameAtIndex(int frameIndex, int numFrames);
+ private native List<Bitmap> _getFrameAtIndex(
+ int frameIndex, int numFrames, @Nullable BitmapParams params);
/**
* This method retrieves a still image by its index. It should only be called
* after {@link #setDataSource}.
*
+ * After the bitmap is returned, you can query the actual parameters that were
+ * used to create the bitmap from the {@code BitmapParams} argument, for instance
+ * to query the bitmap config used for the bitmap with {@link BitmapParams#getActualConfig}.
+ *
* @param imageIndex 0-based index of the image, with negative value indicating
* the primary image.
+ * @param params BitmapParams that controls the returned bitmap config (such as pixel formats).
+ * If null, default config will be chosen.
+ *
* @throws IllegalStateException if the container doesn't contain still images.
* @throws IllegalArgumentException if the requested image does not exist.
*
* @return the requested still image, or null if the image cannot be retrieved.
*
- * @see #getPrimaryImage
+ * @see #getPrimaryImage(BitmapParams)
*/
- public Bitmap getImageAtIndex(int imageIndex) {
+ public Bitmap getImageAtIndex(int imageIndex, @Nullable BitmapParams params) {
if (!"yes".equals(extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_IMAGE))) {
throw new IllegalStateException("Does not contail still images");
}
@@ -451,24 +520,31 @@
throw new IllegalArgumentException("Invalid image index: " + imageCount);
}
- return _getImageAtIndex(imageIndex);
+ return _getImageAtIndex(imageIndex, params);
}
/**
* This method retrieves the primary image of the media content. It should only
* be called after {@link #setDataSource}.
*
+ * After the bitmap is returned, you can query the actual parameters that were
+ * used to create the bitmap from the {@code BitmapParams} argument, for instance
+ * to query the bitmap config used for the bitmap with {@link BitmapParams#getActualConfig}.
+ *
+ * @param params BitmapParams that controls the returned bitmap config (such as pixel formats).
+ * If null, default config will be chosen.
+ *
* @return the primary image, or null if it cannot be retrieved.
*
* @throws IllegalStateException if the container doesn't contain still images.
*
- * @see #getImageAtIndex(int)
+ * @see #getImageAtIndex(int, BitmapParams)
*/
- public Bitmap getPrimaryImage() {
- return getImageAtIndex(-1);
+ public Bitmap getPrimaryImage(@Nullable BitmapParams params) {
+ return getImageAtIndex(-1, params);
}
- private native Bitmap _getImageAtIndex(int imageIndex);
+ private native Bitmap _getImageAtIndex(int imageIndex, @Nullable BitmapParams params);
/**
* Call this method after setDataSource(). This method finds the optional
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index 08defbb..ece19b9 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -214,7 +214,8 @@
* call returns right away, the actual seek operation may take a while to
* finish, especially for audio/video being streamed. When the actual
* seek operation completes, the internal player engine calls a user
- * supplied MediaPlayer2EventCallback.onCallComplete() with {@link #MEDIA_CALL_SEEK_TO}
+ * supplied MediaPlayer2EventCallback.onCallCompleted() with
+ * {@link #CALL_COMPLETED_SEEK_TO}
* if an MediaPlayer2EventCallback has been registered beforehand via
* {@link #setMediaPlayer2EventCallback(Executor, MediaPlayer2EventCallback)}.</li>
* <li>Please
@@ -819,7 +820,7 @@
* of a batch of commands.
*/
// This is an asynchronous call.
- public void notifyWhenCommandLabelReached(Object label) { }
+ public void notifyWhenCommandLabelReached(@NonNull Object label) { }
/**
* Sets the {@link SurfaceHolder} to use for displaying the video
@@ -1051,6 +1052,7 @@
/**
* MediaPlayer2 has not been prepared or just has been reset.
* In this state, MediaPlayer2 doesn't fetch data.
+ * @hide
*/
public static final int MEDIAPLAYER2_STATE_IDLE = 1;
@@ -1058,29 +1060,33 @@
* MediaPlayer2 has been just prepared.
* In this state, MediaPlayer2 just fetches data from media source,
* but doesn't actively render data.
+ * @hide
*/
public static final int MEDIAPLAYER2_STATE_PREPARED = 2;
/**
* MediaPlayer2 is paused.
* In this state, MediaPlayer2 doesn't actively render data.
+ * @hide
*/
public static final int MEDIAPLAYER2_STATE_PAUSED = 3;
/**
* MediaPlayer2 is actively playing back data.
+ * @hide
*/
public static final int MEDIAPLAYER2_STATE_PLAYING = 4;
/**
* MediaPlayer2 has hit some fatal error and cannot continue playback.
+ * @hide
*/
public static final int MEDIAPLAYER2_STATE_ERROR = 5;
/**
* @hide
*/
- @IntDef({
+ @IntDef(flag = false, prefix = "MEDIAPLAYER2_STATE", value = {
MEDIAPLAYER2_STATE_IDLE,
MEDIAPLAYER2_STATE_PREPARED,
MEDIAPLAYER2_STATE_PAUSED,
@@ -1093,6 +1099,7 @@
* Gets the current MediaPlayer2 state.
*
* @return the current MediaPlayer2 state.
+ * @hide
*/
public abstract @MediaPlayer2State int getMediaPlayer2State();
@@ -1170,8 +1177,7 @@
public static final int PLAYBACK_RATE_AUDIO_MODE_DEFAULT = 0;
/** @hide */
- @IntDef(
- value = {
+ @IntDef(flag = false, prefix = "PLAYBACK_RATE_AUDIO_MODE", value = {
PLAYBACK_RATE_AUDIO_MODE_DEFAULT,
PLAYBACK_RATE_AUDIO_MODE_STRETCH,
PLAYBACK_RATE_AUDIO_MODE_RESAMPLE,
@@ -1276,8 +1282,7 @@
public static final int SEEK_CLOSEST = 0x03;
/** @hide */
- @IntDef(
- value = {
+ @IntDef(flag = false, prefix = "SEEK", value = {
SEEK_PREVIOUS_SYNC,
SEEK_NEXT_SYNC,
SEEK_CLOSEST_SYNC,
@@ -1302,16 +1307,6 @@
* If msec is negative, time position zero will be used.
* If msec is larger than duration, duration will be used.
* @param mode the mode indicating where exactly to seek to.
- * Use {@link #SEEK_PREVIOUS_SYNC} if one wants to seek to a sync frame
- * that has a timestamp earlier than or the same as msec. Use
- * {@link #SEEK_NEXT_SYNC} if one wants to seek to a sync frame
- * that has a timestamp later than or the same as msec. Use
- * {@link #SEEK_CLOSEST_SYNC} if one wants to seek to a sync frame
- * that has a timestamp closest to or the same as msec. Use
- * {@link #SEEK_CLOSEST} if one wants to seek to a frame that may
- * or may not be a sync frame but is closest to or the same as msec.
- * {@link #SEEK_CLOSEST} often has larger performance overhead compared
- * to the other options if there is no sync frame located at msec.
*/
// This is an asynchronous call.
public abstract void seekTo(long msec, @SeekMode int mode);
@@ -1753,28 +1748,20 @@
* @param dsd the DataSourceDesc of this data source
* @param data the timed metadata sample associated with this event
*/
- public void onTimedMetaDataAvailable(MediaPlayer2 mp, DataSourceDesc dsd, TimedMetaData data) { }
+ public void onTimedMetaDataAvailable(
+ MediaPlayer2 mp, DataSourceDesc dsd, TimedMetaData data) { }
/**
* Called to indicate an error.
*
* @param mp the MediaPlayer2 the error pertains to
* @param dsd the DataSourceDesc of this data source
- * @param what the type of error that has occurred:
- * <ul>
- * <li>{@link #MEDIA_ERROR_UNKNOWN}
- * </ul>
+ * @param what the type of error that has occurred.
* @param extra an extra code, specific to the error. Typically
* implementation dependent.
- * <ul>
- * <li>{@link #MEDIA_ERROR_IO}
- * <li>{@link #MEDIA_ERROR_MALFORMED}
- * <li>{@link #MEDIA_ERROR_UNSUPPORTED}
- * <li>{@link #MEDIA_ERROR_TIMED_OUT}
- * <li><code>MEDIA_ERROR_SYSTEM (-2147483648)</code> - low-level system error.
- * </ul>
*/
- public void onError(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { }
+ public void onError(
+ MediaPlayer2 mp, DataSourceDesc dsd, @MediaError int what, int extra) { }
/**
* Called to indicate an info or a warning.
@@ -1782,29 +1769,10 @@
* @param mp the MediaPlayer2 the info pertains to.
* @param dsd the DataSourceDesc of this data source
* @param what the type of info or warning.
- * <ul>
- * <li>{@link #MEDIA_INFO_UNKNOWN}
- * <li>{@link #MEDIA_INFO_STARTED_AS_NEXT}
- * <li>{@link #MEDIA_INFO_VIDEO_RENDERING_START}
- * <li>{@link #MEDIA_INFO_AUDIO_RENDERING_START}
- * <li>{@link #MEDIA_INFO_PLAYBACK_COMPLETE}
- * <li>{@link #MEDIA_INFO_PLAYLIST_END}
- * <li>{@link #MEDIA_INFO_PREPARED}
- * <li>{@link #MEDIA_INFO_VIDEO_TRACK_LAGGING}
- * <li>{@link #MEDIA_INFO_BUFFERING_START}
- * <li>{@link #MEDIA_INFO_BUFFERING_END}
- * <li><code>MEDIA_INFO_NETWORK_BANDWIDTH (703)</code> -
- * bandwidth information is available (as <code>extra</code> kbps)
- * <li>{@link #MEDIA_INFO_BAD_INTERLEAVING}
- * <li>{@link #MEDIA_INFO_NOT_SEEKABLE}
- * <li>{@link #MEDIA_INFO_METADATA_UPDATE}
- * <li>{@link #MEDIA_INFO_UNSUPPORTED_SUBTITLE}
- * <li>{@link #MEDIA_INFO_SUBTITLE_TIMED_OUT}
- * </ul>
* @param extra an extra code, specific to the info. Typically
* implementation dependent.
*/
- public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { }
+ public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, @MediaInfo int what, int extra) { }
/**
* Called to acknowledge an API call.
@@ -1812,33 +1780,11 @@
* @param mp the MediaPlayer2 the call was made on.
* @param dsd the DataSourceDesc of this data source
* @param what the enum for the API call.
- * <ul>
- * <li>{@link #MEDIA_CALL_ATTACH_AUX_EFFECT}
- * <li>{@link #MEDIA_CALL_DESELECT_TRACK}
- * <li>{@link #MEDIA_CALL_LOOP_CURRENT}
- * <li>{@link #MEDIA_CALL_PAUSE}
- * <li>{@link #MEDIA_CALL_PLAY}
- * <li>{@link #MEDIA_CALL_PREPARE}
- * <li>{@link #MEDIA_CALL_RELEASE_DRM}
- * <li>{@link #MEDIA_CALL_RESTORE_DRM_KEYS}
- * <li>{@link #MEDIA_CALL_SEEK_TO}
- * <li>{@link #MEDIA_CALL_SELECT_TRACK}
- * <li>{@link #MEDIA_CALL_SET_AUDIO_ATTRIBUTES}
- * <li>{@link #MEDIA_CALL_SET_AUDIO_SESSION_ID}
- * <li>{@link #MEDIA_CALL_SET_AUX_EFFECT_SEND_LEVEL}
- * <li>{@link #MEDIA_CALL_SET_DATA_SOURCE}
- * <li>{@link #MEDIA_CALL_SET_NEXT_DATA_SOURCE}
- * <li>{@link #MEDIA_CALL_SET_NEXT_DATA_SOURCES}
- * <li>{@link #MEDIA_CALL_SET_PLAYBACK_PARAMS}
- * <li>{@link #MEDIA_CALL_SET_PLAYBACK_SPEED}
- * <li>{@link #MEDIA_CALL_SET_PLAYER_VOLUME}
- * <li>{@link #MEDIA_CALL_SET_SURFACE}
- * <li>{@link #MEDIA_CALL_SET_SYNC_PARAMS}
- * <li>{@link #MEDIA_CALL_SKIP_TO_NEXT}
- * </ul>
* @param status the returned status code for the call.
*/
- public void onCallComplete(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) { }
+ public void onCallCompleted(
+ MediaPlayer2 mp, DataSourceDesc dsd, @CallCompleted int what,
+ @CallStatus int status) { }
/**
* Called to indicate media clock has changed.
@@ -1847,7 +1793,8 @@
* @param dsd the DataSourceDesc of this data source
* @param timestamp the new media clock.
*/
- public void onMediaTimeChanged(MediaPlayer2 mp, DataSourceDesc dsd, MediaTimestamp timestamp) { }
+ public void onMediaTimeChanged(
+ MediaPlayer2 mp, DataSourceDesc dsd, MediaTimestamp timestamp) { }
/**
* Called to indicate {@link #notifyWhenCommandLabelReached(Object)} has been processed.
@@ -1856,7 +1803,7 @@
* @param label the application specific Object given by
* {@link #notifyWhenCommandLabelReached(Object)}.
*/
- public void onCommandLabelReached(MediaPlayer2 mp, Object label) { }
+ public void onCommandLabelReached(MediaPlayer2 mp, @NonNull Object label) { }
}
/**
@@ -1929,6 +1876,20 @@
*/
public static final int MEDIA_ERROR_SYSTEM = -2147483648;
+ /**
+ * @hide
+ */
+ @IntDef(flag = false, prefix = "MEDIA_ERROR", value = {
+ MEDIA_ERROR_UNKNOWN,
+ MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK,
+ MEDIA_ERROR_IO,
+ MEDIA_ERROR_MALFORMED,
+ MEDIA_ERROR_UNSUPPORTED,
+ MEDIA_ERROR_TIMED_OUT,
+ MEDIA_ERROR_SYSTEM
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface MediaError {}
/* Do not change these values without updating their counterparts
* in include/media/mediaplayer2.h!
@@ -2059,129 +2020,246 @@
*/
public static final int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902;
+ /**
+ * @hide
+ */
+ @IntDef(flag = false, prefix = "MEDIA_INFO", value = {
+ MEDIA_INFO_UNKNOWN,
+ MEDIA_INFO_STARTED_AS_NEXT,
+ MEDIA_INFO_VIDEO_RENDERING_START,
+ MEDIA_INFO_AUDIO_RENDERING_START,
+ MEDIA_INFO_PLAYBACK_COMPLETE,
+ MEDIA_INFO_PLAYLIST_END,
+ MEDIA_INFO_PREPARED,
+ MEDIA_INFO_VIDEO_TRACK_LAGGING,
+ MEDIA_INFO_BUFFERING_START,
+ MEDIA_INFO_BUFFERING_END,
+ MEDIA_INFO_NETWORK_BANDWIDTH,
+ MEDIA_INFO_BUFFERING_UPDATE,
+ MEDIA_INFO_BAD_INTERLEAVING,
+ MEDIA_INFO_NOT_SEEKABLE,
+ MEDIA_INFO_METADATA_UPDATE,
+ MEDIA_INFO_EXTERNAL_METADATA_UPDATE,
+ MEDIA_INFO_AUDIO_NOT_PLAYING,
+ MEDIA_INFO_VIDEO_NOT_PLAYING,
+ MEDIA_INFO_TIMED_TEXT_ERROR,
+ MEDIA_INFO_UNSUPPORTED_SUBTITLE,
+ MEDIA_INFO_SUBTITLE_TIMED_OUT
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface MediaInfo {}
+
//--------------------------------------------------------------------------
/** The player just completed a call {@link #attachAuxEffect}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_ATTACH_AUX_EFFECT = 1;
+ public static final int CALL_COMPLETED_ATTACH_AUX_EFFECT = 1;
/** The player just completed a call {@link #deselectTrack}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_DESELECT_TRACK = 2;
+ public static final int CALL_COMPLETED_DESELECT_TRACK = 2;
/** The player just completed a call {@link #loopCurrent}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_LOOP_CURRENT = 3;
+ public static final int CALL_COMPLETED_LOOP_CURRENT = 3;
/** The player just completed a call {@link #pause}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_PAUSE = 4;
+ public static final int CALL_COMPLETED_PAUSE = 4;
/** The player just completed a call {@link #play}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_PLAY = 5;
+ public static final int CALL_COMPLETED_PLAY = 5;
/** The player just completed a call {@link #prepare}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_PREPARE = 6;
+ public static final int CALL_COMPLETED_PREPARE = 6;
/** The player just completed a call {@link #releaseDrm}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_RELEASE_DRM = 12;
+ public static final int CALL_COMPLETED_RELEASE_DRM = 12;
/** The player just completed a call {@link #restoreDrmKeys}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_RESTORE_DRM_KEYS = 13;
+ public static final int CALL_COMPLETED_RESTORE_DRM_KEYS = 13;
/** The player just completed a call {@link #seekTo}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_SEEK_TO = 14;
+ public static final int CALL_COMPLETED_SEEK_TO = 14;
/** The player just completed a call {@link #selectTrack}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_SELECT_TRACK = 15;
+ public static final int CALL_COMPLETED_SELECT_TRACK = 15;
/** The player just completed a call {@link #setAudioAttributes}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_SET_AUDIO_ATTRIBUTES = 16;
+ public static final int CALL_COMPLETED_SET_AUDIO_ATTRIBUTES = 16;
/** The player just completed a call {@link #setAudioSessionId}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_SET_AUDIO_SESSION_ID = 17;
+ public static final int CALL_COMPLETED_SET_AUDIO_SESSION_ID = 17;
/** The player just completed a call {@link #setAuxEffectSendLevel}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_SET_AUX_EFFECT_SEND_LEVEL = 18;
+ public static final int CALL_COMPLETED_SET_AUX_EFFECT_SEND_LEVEL = 18;
/** The player just completed a call {@link #setDataSource}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_SET_DATA_SOURCE = 19;
+ public static final int CALL_COMPLETED_SET_DATA_SOURCE = 19;
/** The player just completed a call {@link #setNextDataSource}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_SET_NEXT_DATA_SOURCE = 22;
+ public static final int CALL_COMPLETED_SET_NEXT_DATA_SOURCE = 22;
/** The player just completed a call {@link #setNextDataSources}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_SET_NEXT_DATA_SOURCES = 23;
+ public static final int CALL_COMPLETED_SET_NEXT_DATA_SOURCES = 23;
/** The player just completed a call {@link #setPlaybackParams}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_SET_PLAYBACK_PARAMS = 24;
+ public static final int CALL_COMPLETED_SET_PLAYBACK_PARAMS = 24;
/** The player just completed a call {@link #setPlaybackSpeed}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_SET_PLAYBACK_SPEED = 25;
+ public static final int CALL_COMPLETED_SET_PLAYBACK_SPEED = 25;
/** The player just completed a call {@link #setPlayerVolume}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_SET_PLAYER_VOLUME = 26;
+ public static final int CALL_COMPLETED_SET_PLAYER_VOLUME = 26;
/** The player just completed a call {@link #setSurface}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_SET_SURFACE = 27;
+ public static final int CALL_COMPLETED_SET_SURFACE = 27;
/** The player just completed a call {@link #setSyncParams}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_SET_SYNC_PARAMS = 28;
+ public static final int CALL_COMPLETED_SET_SYNC_PARAMS = 28;
/** The player just completed a call {@link #skipToNext}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
*/
- public static final int MEDIA_CALL_SKIP_TO_NEXT = 29;
+ public static final int CALL_COMPLETED_SKIP_TO_NEXT = 29;
/** The player just completed a call {@link #setBufferingParams}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
* @hide
*/
- public static final int MEDIA_CALL_SET_BUFFERING_PARAMS = 1001;
+ public static final int CALL_COMPLETED_SET_BUFFERING_PARAMS = 1001;
- /** The player just completed a call {@link #setPreferredDevice}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
+ /** The player just completed a call {@code setVideoScalingMode}.
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
* @hide
*/
- public static final int MEDIA_CALL_SET_PREFERRED_DEVICE = 1002;
+ public static final int CALL_COMPLETED_SET_VIDEO_SCALING_MODE = 1002;
+ /** The player just completed a call {@code notifyWhenCommandLabelReached}.
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCommandLabelReached
+ * @hide
+ */
+ public static final int CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED = 1003;
+
+ /**
+ * @hide
+ */
+ @IntDef(flag = false, prefix = "CALL_COMPLETED", value = {
+ CALL_COMPLETED_ATTACH_AUX_EFFECT,
+ CALL_COMPLETED_DESELECT_TRACK,
+ CALL_COMPLETED_LOOP_CURRENT,
+ CALL_COMPLETED_PAUSE,
+ CALL_COMPLETED_PLAY,
+ CALL_COMPLETED_PREPARE,
+ CALL_COMPLETED_RELEASE_DRM,
+ CALL_COMPLETED_RESTORE_DRM_KEYS,
+ CALL_COMPLETED_SEEK_TO,
+ CALL_COMPLETED_SELECT_TRACK,
+ CALL_COMPLETED_SET_AUDIO_ATTRIBUTES,
+ CALL_COMPLETED_SET_AUDIO_SESSION_ID,
+ CALL_COMPLETED_SET_AUX_EFFECT_SEND_LEVEL,
+ CALL_COMPLETED_SET_DATA_SOURCE,
+ CALL_COMPLETED_SET_NEXT_DATA_SOURCE,
+ CALL_COMPLETED_SET_NEXT_DATA_SOURCES,
+ CALL_COMPLETED_SET_PLAYBACK_PARAMS,
+ CALL_COMPLETED_SET_PLAYBACK_SPEED,
+ CALL_COMPLETED_SET_PLAYER_VOLUME,
+ CALL_COMPLETED_SET_SURFACE,
+ CALL_COMPLETED_SET_SYNC_PARAMS,
+ CALL_COMPLETED_SKIP_TO_NEXT,
+ CALL_COMPLETED_SET_BUFFERING_PARAMS,
+ CALL_COMPLETED_SET_VIDEO_SCALING_MODE,
+ CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CallCompleted {}
+
+ /** Status code represents that call is completed without an error.
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
+ */
+ public static final int CALL_STATUS_NO_ERROR = 0;
+
+ /** Status code represents that call is ended with an unknown error.
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
+ */
+ public static final int CALL_STATUS_ERROR_UNKNOWN = Integer.MIN_VALUE;
+
+ /** Status code represents that the player is not in valid state for the operation.
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
+ */
+ public static final int CALL_STATUS_INVALID_OPERATION = 1;
+
+ /** Status code represents that the argument is illegal.
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
+ */
+ public static final int CALL_STATUS_BAD_VALUE = 2;
+
+ /** Status code represents that the operation is not allowed.
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
+ */
+ public static final int CALL_STATUS_PERMISSION_DENIED = 3;
+
+ /** Status code represents a file or network related operation error.
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
+ */
+ public static final int CALL_STATUS_ERROR_IO = 4;
+
+ /** Status code represents that DRM operation is called before preparing a DRM scheme through
+ * {@link #prepareDrm}.
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallCompleted
+ */
+ public static final int CALL_STATUS_NO_DRM_SCHEME = 5;
+
+ /**
+ * @hide
+ */
+ @IntDef(flag = false, prefix = "CALL_STATUS", value = {
+ CALL_STATUS_NO_ERROR,
+ CALL_STATUS_ERROR_UNKNOWN,
+ CALL_STATUS_INVALID_OPERATION,
+ CALL_STATUS_BAD_VALUE,
+ CALL_STATUS_PERMISSION_DENIED,
+ CALL_STATUS_ERROR_IO,
+ CALL_STATUS_NO_DRM_SCHEME})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CallStatus {}
// Modular DRM begin
@@ -2238,13 +2316,10 @@
*
* @param mp the {@code MediaPlayer2} associated with this callback
* @param dsd the DataSourceDesc of this data source
- * @param status the result of DRM preparation which can be
- * {@link #PREPARE_DRM_STATUS_SUCCESS},
- * {@link #PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR},
- * {@link #PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR}, or
- * {@link #PREPARE_DRM_STATUS_PREPARATION_ERROR}.
+ * @param status the result of DRM preparation.
*/
- public void onDrmPrepared(MediaPlayer2 mp, DataSourceDesc dsd, @PrepareDrmStatusCode int status) { }
+ public void onDrmPrepared(
+ MediaPlayer2 mp, DataSourceDesc dsd, @PrepareDrmStatusCode int status) { }
}
/**
@@ -2288,7 +2363,7 @@
/** @hide */
- @IntDef({
+ @IntDef(flag = false, prefix = "PREPARE_DRM_STATUS", value = {
PREPARE_DRM_STATUS_SUCCESS,
PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR,
PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR,
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 7c114df..1c4d898 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -80,6 +80,7 @@
import java.util.UUID;
import java.util.Vector;
import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -102,8 +103,6 @@
private boolean mScreenOnWhilePlaying;
private boolean mStayAwake;
private int mStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE;
- private int mUsage = -1;
- private boolean mBypassInterruptionPolicy;
private final CloseGuard mGuard = CloseGuard.get();
private final Object mSrcLock = new Object();
@@ -117,6 +116,9 @@
private boolean mNextSourcePlayPending = false;
//--- guarded by |mSrcLock| end
+ private AtomicInteger mBufferedPercentageCurrent;
+ private AtomicInteger mBufferedPercentageNext;
+
// Modular DRM
private final Object mDrmLock = new Object();
//--- guarded by |mDrmLock| start
@@ -211,18 +213,13 @@
*/
@Override
public void play() {
- synchronized (mTaskLock) {
- mPendingTasks.add(new Task(MEDIA_CALL_PLAY, false) {
- @Override
- int process() {
- stayAwake(true);
- _start();
- // TODO: define public constants for return value (status).
- return 0;
- }
- });
- processPendingTask_l();
- }
+ addTask(new Task(CALL_COMPLETED_PLAY, false) {
+ @Override
+ void process() {
+ stayAwake(true);
+ _start();
+ }
+ });
}
private native void _start() throws IllegalStateException;
@@ -239,17 +236,12 @@
*/
@Override
public void prepare() {
- synchronized (mTaskLock) {
- mPendingTasks.add(new Task(MEDIA_CALL_PREPARE, true) {
- @Override
- int process() {
- _prepare();
- // TODO: define public constants for return value (status).
- return 0;
- }
- });
- processPendingTask_l();
- }
+ addTask(new Task(CALL_COMPLETED_PREPARE, true) {
+ @Override
+ void process() {
+ _prepare();
+ }
+ });
}
public native void _prepare();
@@ -262,8 +254,13 @@
*/
@Override
public void pause() {
- stayAwake(false);
- _pause();
+ addTask(new Task(CALL_COMPLETED_PAUSE, false) {
+ @Override
+ void process() {
+ stayAwake(false);
+ _pause();
+ }
+ });
}
private native void _pause() throws IllegalStateException;
@@ -275,7 +272,12 @@
*/
@Override
public void skipToNext() {
- // TODO: switch to next data source and play
+ addTask(new Task(CALL_COMPLETED_SKIP_TO_NEXT, false) {
+ @Override
+ void process() {
+ // TODO: switch to next data source and play
+ }
+ });
}
/**
@@ -306,31 +308,38 @@
*/
@Override
public long getBufferedPosition() {
- // TODO: either get buffered position from native code, or cache BUFFERING_UPDATE
- // number and convert it to buffered position.
- return 0;
+ // Use cached buffered percent for now.
+ return getDuration() * mBufferedPercentageCurrent.get() / 100;
}
- /**
- * Gets the current player state.
- *
- * @return the current player state, one of the following:
- * @throws IllegalStateException if the internal player engine has not been
- * initialized or has been released.
- */
@Override
public @PlayerState int getPlayerState() {
- // TODO: use cached state or call native function.
- return PLAYER_STATE_IDLE;
+ int mediaplayer2State = getMediaPlayer2State();
+ int playerState;
+ switch (mediaplayer2State) {
+ case MEDIAPLAYER2_STATE_IDLE:
+ playerState = PLAYER_STATE_IDLE;
+ break;
+ case MEDIAPLAYER2_STATE_PREPARED:
+ case MEDIAPLAYER2_STATE_PAUSED:
+ playerState = PLAYER_STATE_PAUSED;
+ break;
+ case MEDIAPLAYER2_STATE_PLAYING:
+ playerState = PLAYER_STATE_PLAYING;
+ break;
+ case MEDIAPLAYER2_STATE_ERROR:
+ default:
+ playerState = PLAYER_STATE_ERROR;
+ break;
+ }
+
+ return playerState;
}
/**
* Gets the current buffering state of the player.
* During buffering, see {@link #getBufferedPosition()} for the quantifying the amount already
* buffered.
- * @return the buffering state, one of the following:
- * @throws IllegalStateException if the internal player engine has not been
- * initialized or has been released.
*/
@Override
public @BuffState int getBufferingState() {
@@ -348,17 +357,19 @@
*/
@Override
public void setAudioAttributes(@NonNull AudioAttributes attributes) {
- if (attributes == null) {
- final String msg = "Cannot set AudioAttributes to null";
- throw new IllegalArgumentException(msg);
- }
- mUsage = attributes.getUsage();
- mBypassInterruptionPolicy = (attributes.getAllFlags()
- & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0;
- Parcel pattributes = Parcel.obtain();
- attributes.writeToParcel(pattributes, AudioAttributes.FLATTEN_TAGS);
- setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, pattributes);
- pattributes.recycle();
+ addTask(new Task(CALL_COMPLETED_SET_AUDIO_ATTRIBUTES, false) {
+ @Override
+ void process() {
+ if (attributes == null) {
+ final String msg = "Cannot set AudioAttributes to null";
+ throw new IllegalArgumentException(msg);
+ }
+ Parcel pattributes = Parcel.obtain();
+ attributes.writeToParcel(pattributes, AudioAttributes.FLATTEN_TAGS);
+ setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, pattributes);
+ pattributes.recycle();
+ }
+ });
}
@Override
@@ -378,16 +389,21 @@
*/
@Override
public void setDataSource(@NonNull DataSourceDesc dsd) {
- Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null");
- // TODO: setDataSource could update exist data source
- synchronized (mSrcLock) {
- mCurrentDSD = dsd;
- mCurrentSrcId = mSrcIdGenerator++;
- try {
- handleDataSource(true /* isCurrent */, dsd, mCurrentSrcId);
- } catch (IOException e) {
+ addTask(new Task(CALL_COMPLETED_SET_DATA_SOURCE, false) {
+ @Override
+ void process() {
+ Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null");
+ // TODO: setDataSource could update exist data source
+ synchronized (mSrcLock) {
+ mCurrentDSD = dsd;
+ mCurrentSrcId = mSrcIdGenerator++;
+ try {
+ handleDataSource(true /* isCurrent */, dsd, mCurrentSrcId);
+ } catch (IOException e) {
+ }
+ }
}
- }
+ });
}
/**
@@ -400,21 +416,25 @@
*/
@Override
public void setNextDataSource(@NonNull DataSourceDesc dsd) {
- Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null");
-
- synchronized (mSrcLock) {
- mNextDSDs = new ArrayList<DataSourceDesc>(1);
- mNextDSDs.add(dsd);
- mNextSrcId = mSrcIdGenerator++;
- mNextSourceState = NEXT_SOURCE_STATE_INIT;
- mNextSourcePlayPending = false;
- }
- int state = getMediaPlayer2State();
- if (state != MEDIAPLAYER2_STATE_IDLE) {
- synchronized (mSrcLock) {
- prepareNextDataSource_l();
+ addTask(new Task(CALL_COMPLETED_SET_NEXT_DATA_SOURCE, false) {
+ @Override
+ void process() {
+ Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null");
+ synchronized (mSrcLock) {
+ mNextDSDs = new ArrayList<DataSourceDesc>(1);
+ mNextDSDs.add(dsd);
+ mNextSrcId = mSrcIdGenerator++;
+ mNextSourceState = NEXT_SOURCE_STATE_INIT;
+ mNextSourcePlayPending = false;
+ }
+ int state = getMediaPlayer2State();
+ if (state != MEDIAPLAYER2_STATE_IDLE) {
+ synchronized (mSrcLock) {
+ prepareNextDataSource_l();
+ }
+ }
}
- }
+ });
}
/**
@@ -426,28 +446,33 @@
*/
@Override
public void setNextDataSources(@NonNull List<DataSourceDesc> dsds) {
- if (dsds == null || dsds.size() == 0) {
- throw new IllegalArgumentException("data source list cannot be null or empty.");
- }
- for (DataSourceDesc dsd : dsds) {
- if (dsd == null) {
- throw new IllegalArgumentException(
- "DataSourceDesc in the source list cannot be null.");
- }
- }
+ addTask(new Task(CALL_COMPLETED_SET_NEXT_DATA_SOURCES, false) {
+ @Override
+ void process() {
+ if (dsds == null || dsds.size() == 0) {
+ throw new IllegalArgumentException("data source list cannot be null or empty.");
+ }
+ for (DataSourceDesc dsd : dsds) {
+ if (dsd == null) {
+ throw new IllegalArgumentException(
+ "DataSourceDesc in the source list cannot be null.");
+ }
+ }
- synchronized (mSrcLock) {
- mNextDSDs = new ArrayList(dsds);
- mNextSrcId = mSrcIdGenerator++;
- mNextSourceState = NEXT_SOURCE_STATE_INIT;
- mNextSourcePlayPending = false;
- }
- int state = getMediaPlayer2State();
- if (state != MEDIAPLAYER2_STATE_IDLE) {
- synchronized (mSrcLock) {
- prepareNextDataSource_l();
+ synchronized (mSrcLock) {
+ mNextDSDs = new ArrayList(dsds);
+ mNextSrcId = mSrcIdGenerator++;
+ mNextSourceState = NEXT_SOURCE_STATE_INIT;
+ mNextSourcePlayPending = false;
+ }
+ int state = getMediaPlayer2State();
+ if (state != MEDIAPLAYER2_STATE_IDLE) {
+ synchronized (mSrcLock) {
+ prepareNextDataSource_l();
+ }
+ }
}
- }
+ });
}
@Override
@@ -463,8 +488,13 @@
*/
@Override
public void loopCurrent(boolean loop) {
- // TODO: set the looping mode, send notification
- setLooping(loop);
+ addTask(new Task(CALL_COMPLETED_LOOP_CURRENT, false) {
+ @Override
+ void process() {
+ // TODO: set the looping mode, send notification
+ setLooping(loop);
+ }
+ });
}
private native void setLooping(boolean looping);
@@ -480,8 +510,12 @@
*/
@Override
public void setPlaybackSpeed(float speed) {
- // TODO: send notification
- setPlaybackParams(getPlaybackParams().setSpeed(speed));
+ addTask(new Task(CALL_COMPLETED_SET_PLAYBACK_SPEED, false) {
+ @Override
+ void process() {
+ _setPlaybackParams(getPlaybackParams().setSpeed(speed));
+ }
+ });
}
/**
@@ -516,8 +550,12 @@
*/
@Override
public void setPlayerVolume(float volume) {
- // send notification
- _setVolume(volume, volume);
+ addTask(new Task(CALL_COMPLETED_SET_PLAYER_VOLUME, false) {
+ @Override
+ void process() {
+ _setVolume(volume, volume);
+ }
+ });
}
private native void _setVolume(float leftVolume, float rightVolume);
@@ -624,7 +662,17 @@
@Override
public void notifyWhenCommandLabelReached(Object label) {
- // TODO: create an entry in command queue
+ addTask(new Task(CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED, false) {
+ @Override
+ void process() {
+ synchronized (mEventCbLock) {
+ for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
+ cb.first.execute(() -> cb.second.onCommandLabelReached(
+ MediaPlayer2Impl.this, label));
+ }
+ }
+ }
+ });
}
/**
@@ -677,12 +725,17 @@
*/
@Override
public void setSurface(Surface surface) {
- if (mScreenOnWhilePlaying && surface != null) {
- Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for Surface");
- }
- mSurfaceHolder = null;
- _setVideoSurface(surface);
- updateSurfaceScreenOn();
+ addTask(new Task(CALL_COMPLETED_SET_SURFACE, false) {
+ @Override
+ void process() {
+ if (mScreenOnWhilePlaying && surface != null) {
+ Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for Surface");
+ }
+ mSurfaceHolder = null;
+ _setVideoSurface(surface);
+ updateSurfaceScreenOn();
+ }
+ });
}
/**
@@ -706,20 +759,25 @@
*/
@Override
public void setVideoScalingMode(int mode) {
- if (!isVideoScalingModeSupported(mode)) {
- final String msg = "Scaling mode " + mode + " is not supported";
- throw new IllegalArgumentException(msg);
- }
- Parcel request = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- try {
- request.writeInt(INVOKE_ID_SET_VIDEO_SCALE_MODE);
- request.writeInt(mode);
- invoke(request, reply);
- } finally {
- request.recycle();
- reply.recycle();
- }
+ addTask(new Task(CALL_COMPLETED_SET_VIDEO_SCALING_MODE, false) {
+ @Override
+ void process() {
+ if (!isVideoScalingModeSupported(mode)) {
+ final String msg = "Scaling mode " + mode + " is not supported";
+ throw new IllegalArgumentException(msg);
+ }
+ Parcel request = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ try {
+ request.writeInt(INVOKE_ID_SET_VIDEO_SCALE_MODE);
+ request.writeInt(mode);
+ invoke(request, reply);
+ } finally {
+ request.recycle();
+ reply.recycle();
+ }
+ }
+ });
}
/**
@@ -729,6 +787,13 @@
public void clearPendingCommands() {
}
+ private void addTask(Task task) {
+ synchronized (mTaskLock) {
+ mPendingTasks.add(task);
+ processPendingTask_l();
+ }
+ }
+
@GuardedBy("mTaskLock")
private void processPendingTask_l() {
if (mCurrentTask != null) {
@@ -973,8 +1038,10 @@
// Switch to next source only when it's in prepared state.
mCurrentDSD = mNextDSDs.get(0);
mCurrentSrcId = mNextSrcId;
+ mBufferedPercentageCurrent.set(mBufferedPercentageNext.get());
mNextDSDs.remove(0);
mNextSrcId = mSrcIdGenerator++; // make it different from mCurrentSrcId
+ mBufferedPercentageNext.set(0);
mNextSourceState = NEXT_SOURCE_STATE_INIT;
mNextSourcePlayPending = false;
@@ -1324,7 +1391,17 @@
* @hide
*/
@Override
- public native void setBufferingParams(@NonNull BufferingParams params);
+ public void setBufferingParams(@NonNull BufferingParams params) {
+ addTask(new Task(CALL_COMPLETED_SET_BUFFERING_PARAMS, false) {
+ @Override
+ void process() {
+ Preconditions.checkNotNull(params, "the BufferingParams cannot be null");
+ _setBufferingParams(params);
+ }
+ });
+ }
+
+ private native void _setBufferingParams(@NonNull BufferingParams params);
/**
* Sets playback rate and audio mode.
@@ -1378,7 +1455,17 @@
* @throws IllegalArgumentException if params is not supported.
*/
@Override
- public native void setPlaybackParams(@NonNull PlaybackParams params);
+ public void setPlaybackParams(@NonNull PlaybackParams params) {
+ addTask(new Task(CALL_COMPLETED_SET_PLAYBACK_PARAMS, false) {
+ @Override
+ void process() {
+ Preconditions.checkNotNull(params, "the PlaybackParams cannot be null");
+ _setPlaybackParams(params);
+ }
+ });
+ }
+
+ private native void _setPlaybackParams(@NonNull PlaybackParams params);
/**
* Gets the playback params, containing the current playback rate.
@@ -1401,7 +1488,17 @@
* @throws IllegalArgumentException if params are not supported.
*/
@Override
- public native void setSyncParams(@NonNull SyncParams params);
+ public void setSyncParams(@NonNull SyncParams params) {
+ addTask(new Task(CALL_COMPLETED_SET_SYNC_PARAMS, false) {
+ @Override
+ void process() {
+ Preconditions.checkNotNull(params, "the SyncParams cannot be null");
+ _setSyncParams(params);
+ }
+ });
+ }
+
+ private native void _setSyncParams(@NonNull SyncParams params);
/**
* Gets the A/V sync mode.
@@ -1446,20 +1543,28 @@
* @throws IllegalArgumentException if the mode is invalid.
*/
@Override
- public void seekTo(long msec, @SeekMode int mode) {
- if (mode < SEEK_PREVIOUS_SYNC || mode > SEEK_CLOSEST) {
- final String msg = "Illegal seek mode: " + mode;
- throw new IllegalArgumentException(msg);
- }
- // TODO: pass long to native, instead of truncating here.
- if (msec > Integer.MAX_VALUE) {
- Log.w(TAG, "seekTo offset " + msec + " is too large, cap to " + Integer.MAX_VALUE);
- msec = Integer.MAX_VALUE;
- } else if (msec < Integer.MIN_VALUE) {
- Log.w(TAG, "seekTo offset " + msec + " is too small, cap to " + Integer.MIN_VALUE);
- msec = Integer.MIN_VALUE;
- }
- _seekTo(msec, mode);
+ public void seekTo(final long msec, @SeekMode int mode) {
+ addTask(new Task(CALL_COMPLETED_SEEK_TO, true) {
+ @Override
+ void process() {
+ if (mode < SEEK_PREVIOUS_SYNC || mode > SEEK_CLOSEST) {
+ final String msg = "Illegal seek mode: " + mode;
+ throw new IllegalArgumentException(msg);
+ }
+ // TODO: pass long to native, instead of truncating here.
+ long posMs = msec;
+ if (posMs > Integer.MAX_VALUE) {
+ Log.w(TAG, "seekTo offset " + posMs + " is too large, cap to "
+ + Integer.MAX_VALUE);
+ posMs = Integer.MAX_VALUE;
+ } else if (posMs < Integer.MIN_VALUE) {
+ Log.w(TAG, "seekTo offset " + posMs + " is too small, cap to "
+ + Integer.MIN_VALUE);
+ posMs = Integer.MIN_VALUE;
+ }
+ _seekTo(posMs, mode);
+ }
+ });
}
private native final void _seekTo(long msec, int mode);
@@ -1686,7 +1791,16 @@
* @throws IllegalArgumentException if the sessionId is invalid.
*/
@Override
- public native void setAudioSessionId(int sessionId);
+ public void setAudioSessionId(int sessionId) {
+ addTask(new Task(CALL_COMPLETED_SET_AUDIO_SESSION_ID, false) {
+ @Override
+ void process() {
+ _setAudioSessionId(sessionId);
+ }
+ });
+ }
+
+ private native void _setAudioSessionId(int sessionId);
/**
* Returns the audio session ID.
@@ -1712,7 +1826,16 @@
* @param effectId system wide unique id of the effect to attach
*/
@Override
- public native void attachAuxEffect(int effectId);
+ public void attachAuxEffect(int effectId) {
+ addTask(new Task(CALL_COMPLETED_ATTACH_AUX_EFFECT, false) {
+ @Override
+ void process() {
+ _attachAuxEffect(effectId);
+ }
+ });
+ }
+
+ private native void _attachAuxEffect(int effectId);
/**
* Sets the send level of the player to the attached auxiliary effect.
@@ -1728,7 +1851,12 @@
*/
@Override
public void setAuxEffectSendLevel(float level) {
- _setAuxEffectSendLevel(level);
+ addTask(new Task(CALL_COMPLETED_SET_AUX_EFFECT_SEND_LEVEL, false) {
+ @Override
+ void process() {
+ _setAuxEffectSendLevel(level);
+ }
+ });
}
private native void _setAuxEffectSendLevel(float level);
@@ -2467,7 +2595,12 @@
*/
@Override
public void selectTrack(int index) {
- selectOrDeselectTrack(index, true /* select */);
+ addTask(new Task(CALL_COMPLETED_SELECT_TRACK, false) {
+ @Override
+ void process() {
+ selectOrDeselectTrack(index, true /* select */);
+ }
+ });
}
/**
@@ -2486,7 +2619,12 @@
*/
@Override
public void deselectTrack(int index) {
- selectOrDeselectTrack(index, false /* select */);
+ addTask(new Task(CALL_COMPLETED_DESELECT_TRACK, false) {
+ @Override
+ void process() {
+ selectOrDeselectTrack(index, false /* select */);
+ }
+ });
}
private void selectOrDeselectTrack(int index, boolean select)
@@ -2689,8 +2827,11 @@
}
}
synchronized (mTaskLock) {
- if (mCurrentTask.mMediaCallType == MEDIA_CALL_PREPARE
+ if (mCurrentTask != null
+ && mCurrentTask.mMediaCallType == CALL_COMPLETED_PREPARE
+ && mCurrentTask.mDSD == dsd
&& mCurrentTask.mNeedToWaitForEventToComplete) {
+ mCurrentTask.sendCompleteNotification(CALL_STATUS_NO_ERROR);
mCurrentTask = null;
processPendingTask_l();
}
@@ -2773,9 +2914,21 @@
{
final int percent = msg.arg1;
synchronized (mEventCbLock) {
- for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
- cb.first.execute(() -> cb.second.onInfo(
- mMediaPlayer, mCurrentDSD, MEDIA_INFO_BUFFERING_UPDATE, percent));
+ if (srcId == mCurrentSrcId) {
+ mBufferedPercentageCurrent.set(percent);
+ for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
+ cb.first.execute(() -> cb.second.onInfo(
+ mMediaPlayer, mCurrentDSD, MEDIA_INFO_BUFFERING_UPDATE,
+ percent));
+ }
+ } else if (srcId == mNextSrcId && !mNextDSDs.isEmpty()) {
+ mBufferedPercentageNext.set(percent);
+ DataSourceDesc nextDSD = mNextDSDs.get(0);
+ for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
+ cb.first.execute(() -> cb.second.onInfo(
+ mMediaPlayer, nextDSD, MEDIA_INFO_BUFFERING_UPDATE,
+ percent));
+ }
}
}
return;
@@ -2783,10 +2936,13 @@
case MEDIA_SEEK_COMPLETE:
{
- synchronized (mEventCbLock) {
- for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
- cb.first.execute(() -> cb.second.onCallComplete(
- mMediaPlayer, mCurrentDSD, MEDIA_CALL_SEEK_TO, 0));
+ synchronized (mTaskLock) {
+ if (mCurrentTask != null
+ && mCurrentTask.mMediaCallType == CALL_COMPLETED_SEEK_TO
+ && mCurrentTask.mNeedToWaitForEventToComplete) {
+ mCurrentTask.sendCompleteNotification(CALL_STATUS_NO_ERROR);
+ mCurrentTask = null;
+ processPendingTask_l();
}
}
}
@@ -3370,32 +3526,39 @@
public void releaseDrm()
throws NoDrmSchemeException
{
- Log.v(TAG, "releaseDrm:");
+ addTask(new Task(CALL_COMPLETED_RELEASE_DRM, false) {
+ @Override
+ void process() throws NoDrmSchemeException {
+ synchronized (mDrmLock) {
+ Log.v(TAG, "releaseDrm:");
- synchronized (mDrmLock) {
- if (!mActiveDrmScheme) {
- Log.e(TAG, "releaseDrm(): No active DRM scheme to release.");
- throw new NoDrmSchemeExceptionImpl("releaseDrm: No active DRM scheme to release.");
+ if (!mActiveDrmScheme) {
+ Log.e(TAG, "releaseDrm(): No active DRM scheme to release.");
+ throw new NoDrmSchemeExceptionImpl(
+ "releaseDrm: No active DRM scheme to release.");
+ }
+
+ try {
+ // we don't have the player's state in this layer. The below call raises
+ // exception if we're in a non-stopped/prepared state.
+
+ // for cleaning native/mediaserver crypto object
+ _releaseDrm();
+
+ // for cleaning client-side MediaDrm object; only called if above has succeeded
+ cleanDrmObj();
+
+ mActiveDrmScheme = false;
+ } catch (IllegalStateException e) {
+ Log.w(TAG, "releaseDrm: Exception ", e);
+ throw new IllegalStateException(
+ "releaseDrm: The player is not in a valid state.");
+ } catch (Exception e) {
+ Log.e(TAG, "releaseDrm: Exception ", e);
+ }
+ } // synchronized
}
-
- try {
- // we don't have the player's state in this layer. The below call raises
- // exception if we're in a non-stopped/prepared state.
-
- // for cleaning native/mediaserver crypto object
- _releaseDrm();
-
- // for cleaning client-side MediaDrm object; only called if above has succeeded
- cleanDrmObj();
-
- mActiveDrmScheme = false;
- } catch (IllegalStateException e) {
- Log.w(TAG, "releaseDrm: Exception ", e);
- throw new IllegalStateException("releaseDrm: The player is not in a valid state.");
- } catch (Exception e) {
- Log.e(TAG, "releaseDrm: Exception ", e);
- }
- } // synchronized
+ });
}
@@ -3450,7 +3613,8 @@
synchronized (mDrmLock) {
if (!mActiveDrmScheme) {
Log.e(TAG, "getDrmKeyRequest NoDrmSchemeException");
- throw new NoDrmSchemeExceptionImpl("getDrmKeyRequest: Has to set a DRM scheme first.");
+ throw new NoDrmSchemeExceptionImpl(
+ "getDrmKeyRequest: Has to set a DRM scheme first.");
}
try {
@@ -3511,7 +3675,8 @@
if (!mActiveDrmScheme) {
Log.e(TAG, "getDrmKeyRequest NoDrmSchemeException");
- throw new NoDrmSchemeExceptionImpl("getDrmKeyRequest: Has to set a DRM scheme first.");
+ throw new NoDrmSchemeExceptionImpl(
+ "getDrmKeyRequest: Has to set a DRM scheme first.");
}
try {
@@ -3521,8 +3686,8 @@
byte[] keySetResult = mDrmObj.provideKeyResponse(scope, response);
- Log.v(TAG, "provideDrmKeyResponse: keySetId: " + keySetId + " response: " + response +
- " --> " + keySetResult);
+ Log.v(TAG, "provideDrmKeyResponse: keySetId: " + keySetId + " response: " + response
+ + " --> " + keySetResult);
return keySetResult;
@@ -3550,23 +3715,29 @@
public void restoreDrmKeys(@NonNull byte[] keySetId)
throws NoDrmSchemeException
{
- Log.v(TAG, "restoreDrmKeys: keySetId: " + keySetId);
+ addTask(new Task(CALL_COMPLETED_RESTORE_DRM_KEYS, false) {
+ @Override
+ void process() throws NoDrmSchemeException {
+ Log.v(TAG, "restoreDrmKeys: keySetId: " + keySetId);
- synchronized (mDrmLock) {
+ synchronized (mDrmLock) {
- if (!mActiveDrmScheme) {
- Log.w(TAG, "restoreDrmKeys NoDrmSchemeException");
- throw new NoDrmSchemeExceptionImpl("restoreDrmKeys: Has to set a DRM scheme first.");
+ if (!mActiveDrmScheme) {
+ Log.w(TAG, "restoreDrmKeys NoDrmSchemeException");
+ throw new NoDrmSchemeExceptionImpl(
+ "restoreDrmKeys: Has to set a DRM scheme first.");
+ }
+
+ try {
+ mDrmObj.restoreKeys(mDrmSessionId, keySetId);
+ } catch (Exception e) {
+ Log.w(TAG, "restoreKeys Exception " + e);
+ throw e;
+ }
+
+ } // synchronized
}
-
- try {
- mDrmObj.restoreKeys(mDrmSessionId, keySetId);
- } catch (Exception e) {
- Log.w(TAG, "restoreKeys Exception " + e);
- throw e;
- }
-
- } // synchronized
+ });
}
@@ -3591,7 +3762,8 @@
if (!mActiveDrmScheme && !mDrmConfigAllowed) {
Log.w(TAG, "getDrmPropertyString NoDrmSchemeException");
- throw new NoDrmSchemeExceptionImpl("getDrmPropertyString: Has to prepareDrm() first.");
+ throw new NoDrmSchemeExceptionImpl(
+ "getDrmPropertyString: Has to prepareDrm() first.");
}
try {
@@ -3629,7 +3801,8 @@
if ( !mActiveDrmScheme && !mDrmConfigAllowed ) {
Log.w(TAG, "setDrmPropertyString NoDrmSchemeException");
- throw new NoDrmSchemeExceptionImpl("setDrmPropertyString: Has to prepareDrm() first.");
+ throw new NoDrmSchemeExceptionImpl(
+ "setDrmPropertyString: Has to prepareDrm() first.");
}
try {
@@ -4567,34 +4740,61 @@
private abstract class Task implements Runnable {
private final int mMediaCallType;
private final boolean mNeedToWaitForEventToComplete;
+ private DataSourceDesc mDSD;
public Task (int mediaCallType, boolean needToWaitForEventToComplete) {
mMediaCallType = mediaCallType;
mNeedToWaitForEventToComplete = needToWaitForEventToComplete;
}
- abstract int process();
+ abstract void process() throws IOException, NoDrmSchemeException;
@Override
public void run() {
- int status = process();
+ int status = CALL_STATUS_NO_ERROR;
+ try {
+ process();
+ } catch (IllegalStateException e) {
+ status = CALL_STATUS_INVALID_OPERATION;
+ } catch (IllegalArgumentException e) {
+ status = CALL_STATUS_BAD_VALUE;
+ } catch (SecurityException e) {
+ status = CALL_STATUS_PERMISSION_DENIED;
+ } catch (IOException e) {
+ status = CALL_STATUS_ERROR_IO;
+ } catch (NoDrmSchemeException e) {
+ status = CALL_STATUS_NO_DRM_SCHEME;
+ } catch (Exception e) {
+ status = CALL_STATUS_ERROR_UNKNOWN;
+ }
+ synchronized (mSrcLock) {
+ mDSD = mCurrentDSD;
+ }
- if (!mNeedToWaitForEventToComplete) {
- final DataSourceDesc dsd;
- synchronized (mSrcLock) {
- dsd = mCurrentDSD;
- }
- synchronized (mEventCbLock) {
- for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
- cb.first.execute(() -> cb.second.onCallComplete(
- MediaPlayer2Impl.this, dsd, mMediaCallType, status));
- }
- }
+ // TODO: Make native implementations asynchronous and let them send notifications.
+ if (!mNeedToWaitForEventToComplete || status != CALL_STATUS_NO_ERROR) {
+
+ sendCompleteNotification(status);
+
synchronized (mTaskLock) {
mCurrentTask = null;
processPendingTask_l();
}
}
}
+
+ private void sendCompleteNotification(int status) {
+ // In {@link #notifyWhenCommandLabelReached} case, a separate callback
+ // {#link #onCommandLabelReached} is already called in {@code process()}.
+ if (mMediaCallType == CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED) {
+ return;
+ }
+ synchronized (mEventCbLock) {
+ for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
+ cb.first.execute(() -> cb.second.onCallCompleted(
+ MediaPlayer2Impl.this, mDSD, mMediaCallType, status));
+ }
+ }
+ }
};
}
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index c309038..9d2c2828 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -324,7 +324,6 @@
private final Uri mAudioUri;
private final Uri mVideoUri;
private final Uri mImagesUri;
- private final Uri mThumbsUri;
private final Uri mPlaylistsUri;
private final Uri mFilesUri;
private final Uri mFilesUriNoNotify;
@@ -420,7 +419,6 @@
mAudioUri = Audio.Media.getContentUri(volumeName);
mVideoUri = Video.Media.getContentUri(volumeName);
mImagesUri = Images.Media.getContentUri(volumeName);
- mThumbsUri = Images.Thumbnails.getContentUri(volumeName);
mFilesUri = Files.getContentUri(volumeName);
mFilesUriNoNotify = mFilesUri.buildUpon().appendQueryParameter("nonotify", "1").build();
@@ -1287,53 +1285,6 @@
}
}
- private void pruneDeadThumbnailFiles() {
- HashSet<String> existingFiles = new HashSet<String>();
- String directory = "/sdcard/DCIM/.thumbnails";
- String [] files = (new File(directory)).list();
- Cursor c = null;
- if (files == null)
- files = new String[0];
-
- for (int i = 0; i < files.length; i++) {
- String fullPathString = directory + "/" + files[i];
- existingFiles.add(fullPathString);
- }
-
- try {
- c = mMediaProvider.query(
- mThumbsUri,
- new String [] { "_data" },
- null,
- null,
- null, null);
- Log.v(TAG, "pruneDeadThumbnailFiles... " + c);
- if (c != null && c.moveToFirst()) {
- do {
- String fullPathString = c.getString(0);
- existingFiles.remove(fullPathString);
- } while (c.moveToNext());
- }
-
- for (String fileToDelete : existingFiles) {
- if (false)
- Log.v(TAG, "fileToDelete is " + fileToDelete);
- try {
- (new File(fileToDelete)).delete();
- } catch (SecurityException ex) {
- }
- }
-
- Log.v(TAG, "/pruneDeadThumbnailFiles... " + c);
- } catch (RemoteException e) {
- // We will soon be killed...
- } finally {
- if (c != null) {
- c.close();
- }
- }
- }
-
static class MediaBulkDeleter {
StringBuilder whereClause = new StringBuilder();
ArrayList<String> whereArgs = new ArrayList<String>(100);
@@ -1377,9 +1328,6 @@
processPlayLists();
}
- if (mOriginalCount == 0 && mImagesUri.equals(Images.Media.getContentUri("external")))
- pruneDeadThumbnailFiles();
-
// allow GC to clean up
mPlayLists.clear();
}
diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java
index 5c24521..91bface 100644
--- a/media/java/android/media/MediaSession2.java
+++ b/media/java/android/media/MediaSession2.java
@@ -16,6 +16,8 @@
package android.media;
+import static android.media.MediaPlayerBase.PLAYER_STATE_IDLE;
+
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -61,7 +63,7 @@
* sessions can be created to provide finer grain controls of media.
* <p>
* If you want to support background playback, {@link MediaSessionService2} is preferred
- * instead. With it, your playback can be revived even after you've finished playback. See
+ * instead. With it, your playback can be revived even after playback is finished. See
* {@link MediaSessionService2} for details.
* <p>
* A session can be obtained by {@link Builder}. The owner of the session may pass its session token
@@ -180,16 +182,6 @@
public static final int COMMAND_CODE_PLAYBACK_ADJUST_VOLUME = 11;
/**
- * Command code for {@link MediaController2#setPlaylistParams(PlaylistParams)}.
- * <p>
- * Command would be sent directly to the player if the session doesn't reject the request
- * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command)}.
- * @hide
- */
- // TODO(jaewan): Remove (b/74116823)
- public static final int COMMAND_CODE_PLAYBACK_SET_PLAYLIST_PARAMS = 12;
-
- /**
* Command code for {@link MediaController2#skipToPlaylistItem(MediaItem2)}.
* <p>
* Command would be sent directly to the playlist agent if the session doesn't reject the
@@ -254,7 +246,7 @@
public static final int COMMAND_CODE_PLAYLIST_GET_LIST = 18;
/**
- * Command code for {@link MediaController2#setPlaylist(List, MediaMetadata2).
+ * Command code for {@link MediaController2#setPlaylist(List, MediaMetadata2)}.
* <p>
* Command would be sent directly to the playlist agent if the session doesn't reject the
* request through the
@@ -263,11 +255,8 @@
public static final int COMMAND_CODE_PLAYLIST_SET_LIST = 19;
/**
- * Command code for {@link MediaController2#getPlaylistMetadata()} ()}. This will expose
+ * Command code for {@link MediaController2#getPlaylistMetadata()}. This will expose
* metadata information to the controller.
- * *
- * Command code for {@link MediaController2#setPlaylist(List, MediaMetadata2)} and
- * {@link MediaController2#updatePlaylistMetadata(MediaMetadata2)}.
* <p>
* Command would be sent directly to the playlist agent if the session doesn't reject the
* request through the
@@ -315,6 +304,13 @@
public static final int COMMAND_CODE_PREPARE_FROM_SEARCH = 27;
/**
+ * Command code for {@link MediaController2#setRating(String, Rating2)}.
+ * @hide
+ */
+ // TODO(jaewan): Unhide
+ public static final int COMMAND_CODE_SET_RATING = 29;
+
+ /**
* Command code for {@link MediaBrowser2} specific functions that allows navigation and search
* from the {@link MediaLibraryService2}. This would be ignored for a {@link MediaSession2},
* not {@link android.media.MediaLibraryService2.MediaLibrarySession}.
@@ -326,11 +322,6 @@
/**
* @hide
*/
- public static final int COMMAND_CODE_MAX = 28;
-
- /**
- * @hide
- */
@IntDef({ERROR_CODE_UNKNOWN_ERROR, ERROR_CODE_APP_ERROR, ERROR_CODE_NOT_SUPPORTED,
ERROR_CODE_AUTHENTICATION_EXPIRED, ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED,
ERROR_CODE_CONCURRENT_STREAM_LIMIT, ERROR_CODE_PARENTAL_CONTROL_RESTRICTED,
@@ -453,6 +444,13 @@
.createMediaSession2Command(this, COMMAND_CODE_CUSTOM, action, extras);
}
+ /**
+ * @hide
+ */
+ public CommandProvider getProvider() {
+ return mProvider;
+ }
+
public int getCommandCode() {
return mProvider.getCommandCode_impl();
}
@@ -490,7 +488,7 @@
* @return a new Command instance from the Bundle
* @hide
*/
- public static Command fromBundle(@NonNull Context context, Bundle command) {
+ public static Command fromBundle(@NonNull Context context, @NonNull Bundle command) {
return ApiLoader.getProvider(context).fromBundle_MediaSession2Command(context, command);
}
}
@@ -501,17 +499,24 @@
public static final class CommandGroup {
private final CommandGroupProvider mProvider;
- public CommandGroup(Context context) {
+ public CommandGroup(@NonNull Context context) {
mProvider = ApiLoader.getProvider(context)
.createMediaSession2CommandGroup(context, this, null);
}
- public CommandGroup(Context context, CommandGroup others) {
+ public CommandGroup(@NonNull Context context, @Nullable CommandGroup others) {
mProvider = ApiLoader.getProvider(context)
.createMediaSession2CommandGroup(context, this, others);
}
- public void addCommand(Command command) {
+ /**
+ * @hide
+ */
+ public CommandGroup(@NonNull CommandGroupProvider provider) {
+ mProvider = provider;
+ }
+
+ public void addCommand(@NonNull Command command) {
mProvider.addCommand_impl(command);
}
@@ -519,11 +524,11 @@
mProvider.addAllPredefinedCommands_impl();
}
- public void removeCommand(Command command) {
+ public void removeCommand(@NonNull Command command) {
mProvider.removeCommand_impl(command);
}
- public boolean hasCommand(Command command) {
+ public boolean hasCommand(@NonNull Command command) {
return mProvider.hasCommand_impl(command);
}
@@ -531,14 +536,14 @@
return mProvider.hasCommand_impl(code);
}
- public List<Command> getCommands() {
+ public @NonNull List<Command> getCommands() {
return mProvider.getCommands_impl();
}
/**
* @hide
*/
- public CommandGroupProvider getProvider() {
+ public @NonNull CommandGroupProvider getProvider() {
return mProvider;
}
@@ -546,7 +551,7 @@
* @return new bundle from the CommandGroup
* @hide
*/
- public Bundle toBundle() {
+ public @NonNull Bundle toBundle() {
return mProvider.toBundle_impl();
}
@@ -570,7 +575,10 @@
public static abstract class SessionCallback {
private final Context mContext;
- public SessionCallback(Context context) {
+ public SessionCallback(@NonNull Context context) {
+ if (context == null) {
+ throw new IllegalArgumentException("context shouldn't be null");
+ }
mContext = context;
}
@@ -584,7 +592,7 @@
*
* @param session the session for this event
* @param controller controller information.
- * @return allowed commands. Can be {@code null} to reject coonnection.
+ * @return allowed commands. Can be {@code null} to reject connection.
*/
public @Nullable CommandGroup onConnect(@NonNull MediaSession2 session,
@NonNull ControllerInfo controller) {
@@ -620,7 +628,6 @@
* @see #COMMAND_CODE_PLAYBACK_REWIND
* @see #COMMAND_CODE_PLAYBACK_SEEK_TO
* @see #COMMAND_CODE_PLAYLIST_SKIP_TO_PLAYLIST_ITEM
- * @see #COMMAND_CODE_PLAYBACK_SET_PLAYLIST_PARAMS
* @see #COMMAND_CODE_PLAYLIST_ADD_ITEM
* @see #COMMAND_CODE_PLAYLIST_REMOVE_ITEM
* @see #COMMAND_CODE_PLAYLIST_GET_LIST
@@ -824,7 +831,11 @@
@NonNull MediaPlayerBase player, @NonNull MediaItem2 item, @BuffState int state) { }
/**
- * Called when a playlist is changed.
+ * Called when a playlist is changed from the {@link MediaPlaylistAgent}.
+ * <p>
+ * This is called when the underlying agent has called
+ * {@link MediaPlaylistAgent.PlaylistEventCallback#onPlaylistChanged(MediaPlaylistAgent,
+ * List, MediaMetadata2)}.
*
* @param session the session for this event
* @param playlistAgent playlist agent for this event
@@ -901,37 +912,39 @@
}
/**
- * Set the underlying {@link MediaPlayerBase} for this session to dispatch incoming event
+ * Sets the underlying {@link MediaPlayerBase} for this session to dispatch incoming event
* to.
- * <p>
*
* @param player a {@link MediaPlayerBase} that handles actual media playback in your app.
*/
- U setPlayer(@NonNull MediaPlayerBase player) {
+ @NonNull U setPlayer(@NonNull MediaPlayerBase player) {
mProvider.setPlayer_impl(player);
return (U) this;
}
/**
- * Set the {@link MediaPlaylistAgent} for this session to manages playlist of the
- * underlying {@link MediaPlayerBase player}.
+ * Sets the {@link MediaPlaylistAgent} for this session to manages playlist of the
+ * underlying {@link MediaPlayerBase}. The playlist agent should manage
+ * {@link MediaPlayerBase} for calling {@link MediaPlayerBase#setNextDataSources(List)}.
+ * <p>
+ * If the {@link MediaPlaylistAgent} isn't set, session will create the default playlist
+ * agent.
*
* @param playlistAgent a {@link MediaPlaylistAgent} that manages playlist of the
- * {@code player}
+ * {@code player}
*/
U setPlaylistAgent(@NonNull MediaPlaylistAgent playlistAgent) {
- // TODO(jaewan): fix this
mProvider.setPlaylistAgent_impl(playlistAgent);
return (U) this;
}
/**
- * Set the {@link VolumeProvider2} for this session to receive volume button events. If not
- * set, system will adjust the appropriate stream volume for this session's player.
+ * Sets the {@link VolumeProvider2} for this session to handle volume events. If not set,
+ * system will adjust the appropriate stream volume for this session's player.
*
* @param volumeProvider The provider that will receive volume button events.
*/
- U setVolumeProvider(@NonNull VolumeProvider2 volumeProvider) {
+ @NonNull U setVolumeProvider(@Nullable VolumeProvider2 volumeProvider) {
mProvider.setVolumeProvider_impl(volumeProvider);
return (U) this;
}
@@ -943,7 +956,7 @@
*
* @param pi The intent to launch to show UI for this session.
*/
- U setSessionActivity(@Nullable PendingIntent pi) {
+ @NonNull U setSessionActivity(@Nullable PendingIntent pi) {
mProvider.setSessionActivity_impl(pi);
return (U) this;
}
@@ -958,7 +971,7 @@
* @throws IllegalArgumentException if id is {@code null}
* @return
*/
- U setId(@NonNull String id) {
+ @NonNull U setId(@NonNull String id) {
mProvider.setId_impl(id);
return (U) this;
}
@@ -970,7 +983,7 @@
* @param callback session callback.
* @return
*/
- U setSessionCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull U setSessionCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull C callback) {
mProvider.setSessionCallback_impl(executor, callback);
return (U) this;
@@ -983,7 +996,7 @@
* @throws IllegalStateException if the session with the same id is already exists for the
* package.
*/
- T build() {
+ @NonNull T build() {
return mProvider.build_impl();
}
}
@@ -1003,7 +1016,7 @@
}
@Override
- public Builder setPlayer(@NonNull MediaPlayerBase player) {
+ public @NonNull Builder setPlayer(@NonNull MediaPlayerBase player) {
return super.setPlayer(player);
}
@@ -1013,28 +1026,28 @@
}
@Override
- public Builder setVolumeProvider(@NonNull VolumeProvider2 volumeProvider) {
+ public @NonNull Builder setVolumeProvider(@Nullable VolumeProvider2 volumeProvider) {
return super.setVolumeProvider(volumeProvider);
}
@Override
- public Builder setSessionActivity(@Nullable PendingIntent pi) {
+ public @NonNull Builder setSessionActivity(@Nullable PendingIntent pi) {
return super.setSessionActivity(pi);
}
@Override
- public Builder setId(@NonNull String id) {
+ public @NonNull Builder setId(@NonNull String id) {
return super.setId(id);
}
@Override
- public Builder setSessionCallback(@NonNull Executor executor,
+ public @NonNull Builder setSessionCallback(@NonNull Executor executor,
@Nullable SessionCallback callback) {
return super.setSessionCallback(executor, callback);
}
@Override
- public MediaSession2 build() {
+ public @NonNull MediaSession2 build() {
return super.build();
}
}
@@ -1048,8 +1061,8 @@
/**
* @hide
*/
- public ControllerInfo(Context context, int uid, int pid, String packageName,
- IInterface callback) {
+ public ControllerInfo(@NonNull Context context, int uid, int pid,
+ @NonNull String packageName, @NonNull IInterface callback) {
mProvider = ApiLoader.getProvider(context)
.createMediaSession2ControllerInfo(
context, this, uid, pid, packageName, callback);
@@ -1058,7 +1071,7 @@
/**
* @return package name of the controller
*/
- public String getPackageName() {
+ public @NonNull String getPackageName() {
return mProvider.getPackageName_impl();
}
@@ -1083,7 +1096,7 @@
/**
* @hide
*/
- public ControllerInfoProvider getProvider() {
+ public @NonNull ControllerInfoProvider getProvider() {
return mProvider;
}
@@ -1169,7 +1182,7 @@
/**
* @hide
*/
- public CommandButtonProvider getProvider() {
+ public @NonNull CommandButtonProvider getProvider() {
return mProvider;
}
@@ -1184,27 +1197,27 @@
.createMediaSession2CommandButtonBuilder(context, this);
}
- public Builder setCommand(Command command) {
+ public @NonNull Builder setCommand(@Nullable Command command) {
return mProvider.setCommand_impl(command);
}
- public Builder setIconResId(int resId) {
+ public @NonNull Builder setIconResId(int resId) {
return mProvider.setIconResId_impl(resId);
}
- public Builder setDisplayName(String displayName) {
+ public @NonNull Builder setDisplayName(@Nullable String displayName) {
return mProvider.setDisplayName_impl(displayName);
}
- public Builder setEnabled(boolean enabled) {
+ public @NonNull Builder setEnabled(boolean enabled) {
return mProvider.setEnabled_impl(enabled);
}
- public Builder setExtras(Bundle extras) {
+ public @NonNull Builder setExtras(@Nullable Bundle extras) {
return mProvider.setExtras_impl(extras);
}
- public CommandButton build() {
+ public @NonNull CommandButton build() {
return mProvider.build_impl();
}
}
@@ -1363,20 +1376,24 @@
/**
* @hide
*/
- public MediaSession2Provider getProvider() {
+ public @NonNull MediaSession2Provider getProvider() {
return mProvider;
}
/**
- * Set the underlying {@link MediaPlayerBase} for this session to dispatch incoming event
- * to. Events from the {@link MediaController2} will be sent directly to the underlying
- * player on the {@link Handler} where the session is created on.
+ * Sets the underlying {@link MediaPlayerBase} and {@link MediaPlaylistAgent} for this session
+ * to dispatch incoming event to.
+ * <p>
+ * When a {@link MediaPlaylistAgent} is specified here, the playlist agent should manage
+ * {@link MediaPlayerBase} for calling {@link MediaPlayerBase#setNextDataSources(List)}.
+ * <p>
+ * If the {@link MediaPlaylistAgent} isn't set, session will recreate the default playlist
+ * agent.
*
- * @param player a {@link MediaPlayerBase} that handles actual media playback in your app.
- * @param playlistAgent a {@link MediaPlaylistAgent} that manages playlist of the
- * {@code player}
- * @param volumeProvider The provider that will receive volume button events. If
- * {@code null}, system will adjust the appropriate stream volume for this session's player.
+ * @param player a {@link MediaPlayerBase} that handles actual media playback in your app
+ * @param playlistAgent a {@link MediaPlaylistAgent} that manages playlist of the {@code player}
+ * @param volumeProvider a {@link VolumeProvider2}. If {@code null}, system will adjust the
+ * appropriate stream volume for this session's player.
*/
public void updatePlayer(@NonNull MediaPlayerBase player,
@Nullable MediaPlaylistAgent playlistAgent, @Nullable VolumeProvider2 volumeProvider) {
@@ -1391,18 +1408,15 @@
/**
* @return player
*/
- public @NonNull
- MediaPlayerBase getPlayer() {
+ public @NonNull MediaPlayerBase getPlayer() {
return mProvider.getPlayer_impl();
}
/**
- * @return playlist manager
+ * @return playlist agent
*/
- public @Nullable
- MediaPlaylistAgent getPlaylistAgent() {
- // TODO(jaewan): implement this (b/74090741)
- return null;
+ public @NonNull MediaPlaylistAgent getPlaylistAgent() {
+ return mProvider.getPlaylistAgent_impl();
}
/**
@@ -1429,7 +1443,7 @@
*
* @param afr the full request parameters
*/
- public void setAudioFocusRequest(AudioFocusRequest afr) {
+ public void setAudioFocusRequest(@Nullable AudioFocusRequest afr) {
// TODO(jaewan): implement this (b/72529899)
// mProvider.setAudioFocusRequest_impl(focusGain);
}
@@ -1632,13 +1646,36 @@
}
/**
- * Return the {@link PlaybackState2} from the player.
+ * Get the player state.
*
- * @return playback state
+ * @return player state
* @hide
*/
- public PlaybackState2 getPlaybackState() {
- return mProvider.getPlaybackState_impl();
+ public @PlayerState int getPlayerState() {
+ // TODO(jaewan): implement this (b/74578458)
+ return PLAYER_STATE_IDLE;
+ }
+
+ /**
+ * Get the current position.
+ *
+ * @return position
+ * @hide
+ */
+ public long getCurrentPosition() {
+ // TODO(jaewan): implement this (b/74578458)
+ return -1;
+ }
+
+ /**
+ * Get the buffered position.
+ *
+ * @return buffered position
+ * @hide
+ */
+ public long getBufferedPosition() {
+ // TODO(jaewan): implement this (b/74578458)
+ return -1;
}
/**
@@ -1675,7 +1712,7 @@
* <p>
* If it's not set, playback wouldn't happen for the item without data source descriptor.
* <p>
- * The helper will be run on the executor that you've specified by the
+ * The helper will be run on the executor that was specified by
* {@link Builder#setSessionCallback(Executor, SessionCallback)}.
*
* @param helper a data source missing helper.
@@ -1699,40 +1736,46 @@
}
/**
- * Return the playlist which is lastly set.
+ * Returns the playlist from the {@link MediaPlaylistAgent}.
+ * <p>
+ * This list may differ with the list that was specified with
+ * {@link #setPlaylist(List, MediaMetadata2)} depending on the {@link MediaPlaylistAgent}
+ * implementation. Use media items returned here for other playlist agent APIs such as
+ * {@link MediaPlaylistAgent#skipToPlaylistItem(MediaItem2)}.
*
* @return playlist
+ * @see MediaPlaylistAgent#getPlaylist()
+ * @see SessionCallback#onPlaylistChanged(
+ * MediaSession2, MediaPlaylistAgent, List, MediaMetadata2)
*/
public List<MediaItem2> getPlaylist() {
return mProvider.getPlaylist_impl();
}
/**
- * Set a list of {@link MediaItem2} as the current play list.
- *
- * @param playlist A list of {@link MediaItem2} objects to set as a play list.
- * @throws IllegalArgumentException if given {@param playlist} is null.
- * @hide
- */
- // TODO(jaewan): Remove
- public void setPlaylist(@NonNull List<MediaItem2> playlist) {
- mProvider.setPlaylist_impl(playlist);
- }
-
- /**
- * Set a list of {@link MediaItem2} as the current play list. Ensure uniqueness in the
- * {@link MediaItem2} in the playlist so session can uniquely identity individual items.
+ * Sets a list of {@link MediaItem2} to the {@link MediaPlaylistAgent}. Ensure uniqueness of
+ * each {@link MediaItem2} in the playlist so the session can uniquely identity individual
+ * items.
* <p>
- * You may specify a {@link MediaItem2} without {@link DataSourceDesc}. However, in that case,
- * you should set {@link OnDataSourceMissingHelper} for player to prepare.
+ * This may be an asynchronous call, and {@link MediaPlaylistAgent} may keep the copy of the
+ * list. Wait for {@link SessionCallback#onPlaylistChanged(MediaSession2, MediaPlaylistAgent,
+ * List, MediaMetadata2)} to know the operation finishes.
+ * <p>
+ * You may specify a {@link MediaItem2} without {@link DataSourceDesc}. In that case,
+ * {@link MediaPlaylistAgent} has responsibility to dynamically query {@link DataSourceDesc}
+ * when such media item is ready for preparation or play. Default implementation needs
+ * {@link OnDataSourceMissingHelper} for such case.
*
* @param list A list of {@link MediaItem2} objects to set as a play list.
- * @throws IllegalArgumentException if given list is {@code null}, or has duplicated media item.
+ * @throws IllegalArgumentException if given list is {@code null}, or has duplicated media
+ * items.
+ * @see MediaPlaylistAgent#setPlaylist(List, MediaMetadata2)
+ * @see SessionCallback#onPlaylistChanged(
+ * MediaSession2, MediaPlaylistAgent, List, MediaMetadata2)
* @see #setOnDataSourceMissingHelper
*/
public void setPlaylist(@NonNull List<MediaItem2> list, @Nullable MediaMetadata2 metadata) {
- // TODO(jaewan): Handle metadata here (b/74174649)
- // TODO(jaewan): Handle list change (b/74326040)
+ mProvider.setPlaylist_impl(list, metadata);
}
/**
@@ -1742,7 +1785,7 @@
* @throws IllegalArgumentException if the play list is null
* @throws NullPointerException if index is outside play list range
*/
- public void skipToPlaylistItem(MediaItem2 item) {
+ public void skipToPlaylistItem(@NonNull MediaItem2 item) {
mProvider.skipToPlaylistItem_impl(item);
}
@@ -1754,13 +1797,17 @@
mProvider.skipToNextItem_impl();
}
+ /**
+ * Gets the playlist metadata from the {@link MediaPlaylistAgent}.
+ *
+ * @return the playlist metadata
+ */
public MediaMetadata2 getPlaylistMetadata() {
- // TODO(jaewan): Implement (b/74174649)
- return null;
+ return mProvider.getPlaylistMetadata_impl();
}
/**
- * Add the media item to the play list at position index.
+ * Adds the media item to the playlist at position index.
* <p>
* This will not change the currently playing media item.
* If index is less than or equal to the current index of the play list,
@@ -1768,26 +1815,25 @@
*
* @param index the index you want to add
* @param item the media item you want to add
- * @throws IndexOutOfBoundsException if index is outside play list range
*/
public void addPlaylistItem(int index, @NonNull MediaItem2 item) {
mProvider.addPlaylistItem_impl(index, item);
}
/**
- * Remove the media item in the play list.
+ * Removes the media item in the playlist.
* <p>
* If the item is the currently playing item of the playlist, current playback
* will be stopped and playback moves to next source in the list.
*
- * @throws IllegalArgumentException if the play list is null
+ * @param item the media item you want to add
*/
- public void removePlaylistItem(MediaItem2 item) {
+ public void removePlaylistItem(@NonNull MediaItem2 item) {
mProvider.removePlaylistItem_impl(item);
}
/**
- * Replace the media item at index in the playlist. This can be also used to update metadata of
+ * Replaces the media item at index in the playlist. This can be also used to update metadata of
* an item.
*
* @param index the index of the item to replace
@@ -1807,8 +1853,13 @@
return mProvider.getCurrentPlaylistItem_impl();
}
+ /**
+ * Updates the playlist metadata to the {@link MediaPlaylistAgent}.
+ *
+ * @param metadata metadata of the playlist
+ */
public void updatePlaylistMetadata(@Nullable MediaMetadata2 metadata) {
- // TODO(jaewan): Implement (b/74174649)
+ mProvider.updatePlaylistMetadata_impl(metadata);
}
public @RepeatMode int getRepeatMode() {
diff --git a/media/java/android/media/MediaSessionService2.java b/media/java/android/media/MediaSessionService2.java
index d352a86..32caf4b 100644
--- a/media/java/android/media/MediaSessionService2.java
+++ b/media/java/android/media/MediaSessionService2.java
@@ -166,7 +166,7 @@
*
* @return a {@link MediaNotification}. If it's {@code null}, notification wouldn't be shown.
*/
- public MediaNotification onUpdateNotification() {
+ public @Nullable MediaNotification onUpdateNotification() {
return mProvider.onUpdateNotification_impl();
}
@@ -202,7 +202,7 @@
}
/**
- * Returned by {@link #onUpdateNotification()} for making session service forground service
+ * Returned by {@link #onUpdateNotification()} for making session service foreground service
* to keep playback running in the background. It's highly recommended to show media style
* notification here.
*/
@@ -229,7 +229,7 @@
return mProvider.getNotificationId_impl();
}
- public Notification getNotification() {
+ public @NonNull Notification getNotification() {
return mProvider.getNotification_impl();
}
}
diff --git a/media/java/android/media/MiniThumbFile.java b/media/java/android/media/MiniThumbFile.java
index 664308c..9899367 100644
--- a/media/java/android/media/MiniThumbFile.java
+++ b/media/java/android/media/MiniThumbFile.java
@@ -44,13 +44,14 @@
*/
public class MiniThumbFile {
private static final String TAG = "MiniThumbFile";
- private static final int MINI_THUMB_DATA_FILE_VERSION = 3;
+ private static final int MINI_THUMB_DATA_FILE_VERSION = 4;
public static final int BYTES_PER_MINTHUMB = 10000;
private static final int HEADER_SIZE = 1 + 8 + 4;
private Uri mUri;
private RandomAccessFile mMiniThumbFile;
private FileChannel mChannel;
private ByteBuffer mBuffer;
+ private ByteBuffer mEmptyBuffer;
private static final Hashtable<String, MiniThumbFile> sThumbFiles =
new Hashtable<String, MiniThumbFile>();
@@ -127,9 +128,10 @@
return mMiniThumbFile;
}
- public MiniThumbFile(Uri uri) {
+ private MiniThumbFile(Uri uri) {
mUri = uri;
mBuffer = ByteBuffer.allocateDirect(BYTES_PER_MINTHUMB);
+ mEmptyBuffer = ByteBuffer.allocateDirect(BYTES_PER_MINTHUMB);
}
public synchronized void deactivate() {
@@ -184,6 +186,54 @@
return 0;
}
+ public synchronized void eraseMiniThumb(long id) {
+ RandomAccessFile r = miniThumbDataFile();
+ if (r != null) {
+ long pos = id * BYTES_PER_MINTHUMB;
+ FileLock lock = null;
+ try {
+ mBuffer.clear();
+ mBuffer.limit(1 + 8);
+
+ lock = mChannel.lock(pos, BYTES_PER_MINTHUMB, false);
+ // check that we can read the following 9 bytes
+ // (1 for the "status" and 8 for the long)
+ if (mChannel.read(mBuffer, pos) == 9) {
+ mBuffer.position(0);
+ if (mBuffer.get() == 1) {
+ long currentMagic = mBuffer.getLong();
+ if (currentMagic == 0) {
+ // there is no thumbnail stored here
+ Log.i(TAG, "no thumbnail for id " + id);
+ return;
+ }
+ // zero out the thumbnail slot
+ // Log.v(TAG, "clearing slot " + id + ", magic " + currentMagic
+ // + " at offset " + pos);
+ mChannel.write(mEmptyBuffer, pos);
+ }
+ } else {
+ // Log.v(TAG, "No slot");
+ }
+ } catch (IOException ex) {
+ Log.v(TAG, "Got exception checking file magic: ", ex);
+ } catch (RuntimeException ex) {
+ // Other NIO related exception like disk full, read only channel..etc
+ Log.e(TAG, "Got exception when reading magic, id = " + id +
+ ", disk full or mount read-only? " + ex.getClass());
+ } finally {
+ try {
+ if (lock != null) lock.release();
+ }
+ catch (IOException ex) {
+ // ignore it.
+ }
+ }
+ } else {
+ // Log.v(TAG, "No data file");
+ }
+ }
+
public synchronized void saveMiniThumbToFile(byte[] data, long id, long magic)
throws IOException {
RandomAccessFile r = miniThumbDataFile();
diff --git a/media/java/android/media/PlaybackState2.java b/media/java/android/media/PlaybackState2.java
deleted file mode 100644
index afc2bfa..0000000
--- a/media/java/android/media/PlaybackState2.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright 2018 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.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.media.update.ApiLoader;
-import android.media.update.PlaybackState2Provider;
-import android.os.Bundle;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Playback state for a {@link MediaPlayerBase}, to be shared between {@link MediaSession2} and
- * {@link MediaController2}. This includes a playback state {@link #STATE_PLAYING},
- * the current playback position and extra.
- * @hide
- */
-// TODO(jaewan): Remove this (b/73971431)
-public final class PlaybackState2 {
- // Similar to the PlaybackState with following changes
- // - Not implement Parcelable and added from/toBundle()
- // - Removed playback state that doesn't match with the MediaPlayer2
- // Full list should be finalized when the MediaPlayer2 has getter for the playback state.
- // Here's table for the MP2 state and PlaybackState2.State.
- // +----------------------------------------+----------------------------------------+
- // | MediaPlayer2 state | Matching PlaybackState2.State |
- // | (Names are from MP2' Javadoc) | |
- // +----------------------------------------+----------------------------------------+
- // | Idle: Just finished creating MP2 | STATE_NONE |
- // | or reset() is called | |
- // +----------------------------------------+----------------------------------------+
- // | Initialized: setDataSource/Playlist | N/A (Session/Controller don't |
- // | | differentiate with Prepared) |
- // +----------------------------------------+----------------------------------------+
- // | Prepared: Prepared after initialized | STATE_PAUSED |
- // +----------------------------------------+----------------------------------------+
- // | Started: Started playback | STATE_PLAYING |
- // +----------------------------------------+----------------------------------------+
- // | Paused: Paused playback | STATE_PAUSED |
- // +----------------------------------------+----------------------------------------+
- // | PlaybackCompleted: Playback is done | STATE_PAUSED |
- // +----------------------------------------+----------------------------------------+
- // | Stopped: MP2.stop() is called. | STATE_STOPPED |
- // | prepare() is needed to play again | |
- // | (Seemingly the same as initialized | |
- // | because cannot set data source | |
- // | after this) | |
- // +----------------------------------------+----------------------------------------+
- // | Error: an API is called in a state | STATE_ERROR |
- // | that the API isn't supported | |
- // +----------------------------------------+----------------------------------------+
- // | End: MP2.close() is called to release | N/A (MediaSession will be gone) |
- // | MP2. Cannot be reused anymore | |
- // +----------------------------------------+----------------------------------------+
- // | Started, but | STATE_BUFFERING |
- // | EventCallback.onBufferingUpdate() | |
- // +----------------------------------------+----------------------------------------+
- // - Removed actions and custom actions.
- // - Removed error string
- // - Repeat mode / shuffle mode is now in the PlaylistParams
- /**
- * @hide
- */
- @IntDef({STATE_NONE, STATE_STOPPED, STATE_PAUSED, STATE_PLAYING, STATE_BUFFERING, STATE_ERROR})
- @Retention(RetentionPolicy.SOURCE)
- public @interface State {}
-
- /**
- * This is the default playback state and indicates that no media has been
- * added yet, or the performer has been reset and has no content to play.
- */
- public final static int STATE_NONE = 0;
-
- /**
- * State indicating this item is currently stopped.
- */
- public final static int STATE_STOPPED = 1;
-
- /**
- * State indicating this item is currently paused.
- */
- public final static int STATE_PAUSED = 2;
-
- /**
- * State indicating this item is currently playing.
- */
- public final static int STATE_PLAYING = 3;
-
- /**
- * State indicating this item is currently buffering and will begin playing
- * when enough data has buffered.
- */
- public final static int STATE_BUFFERING = 4;
-
- /**
- * State indicating this item is currently in an error state.
- */
- public final static int STATE_ERROR = 5;
-
- /**
- * Use this value for the position to indicate the position is not known.
- */
- public final static long PLAYBACK_POSITION_UNKNOWN = -1;
-
- private final PlaybackState2Provider mProvider;
-
- public PlaybackState2(@NonNull Context context, int state, long position, long updateTime,
- float speed, long bufferedPosition, long activeItemId) {
- mProvider = ApiLoader.getProvider(context).createPlaybackState2(context, this, state,
- position, updateTime, speed, bufferedPosition, activeItemId);
- }
-
- @Override
- public String toString() {
- return mProvider.toString_impl();
- }
-
- /**
- * Get the current state of playback. One of the following:
- * <ul>
- * <li> {@link PlaybackState2#STATE_NONE}</li>
- * <li> {@link PlaybackState2#STATE_STOPPED}</li>
- * <li> {@link PlaybackState2#STATE_PAUSED}</li>
- * <li> {@link PlaybackState2#STATE_PLAYING}</li>
- * <li> {@link PlaybackState2#STATE_BUFFERING}</li>
- * <li> {@link PlaybackState2#STATE_ERROR}</li>
- * </ul>
- */
- @State
- public int getState() {
- return mProvider.getState_impl();
- }
-
- /**
- * Get the current playback position in ms.
- */
- public long getPosition() {
- return mProvider.getPosition_impl();
- }
-
- /**
- * Get the current buffered position in ms. This is the farthest playback
- * point that can be reached from the current position using only buffered
- * content.
- */
- public long getBufferedPosition() {
- return mProvider.getBufferedPosition_impl();
- }
-
- /**
- * Get the current playback speed as a multiple of normal playback. This
- * should be negative when rewinding. A value of 1 means normal playback and
- * 0 means paused.
- *
- * @return The current speed of playback.
- */
- public float getPlaybackSpeed() {
- return mProvider.getPlaybackSpeed_impl();
- }
-
- /**
- * Get the elapsed real time at which position was last updated. If the
- * position has never been set this will return 0;
- *
- * @return The last time the position was updated.
- */
- public long getLastPositionUpdateTime() {
- return mProvider.getLastPositionUpdateTime_impl();
- }
-
- /**
- * Get the id of the currently active item in the playlist.
- *
- * @return The id of the currently active item in the queue
- */
- public long getCurrentPlaylistItemIndex() {
- return mProvider.getCurrentPlaylistItemIndex_impl();
- }
-
- /**
- * Returns this object as a bundle to share between processes.
- */
- public @NonNull Bundle toBundle() {
- return mProvider.toBundle_impl();
- }
-
- /**
- * Creates an instance from a bundle which is previously created by {@link #toBundle()}.
- *
- * @param context context
- * @param bundle A bundle created by {@link #toBundle()}.
- * @return A new {@link PlaybackState2} instance. Returns {@code null} if the given
- * {@param bundle} is null, or if the {@param bundle} has no playback state parameters.
- */
- public @Nullable static PlaybackState2 fromBundle(@NonNull Context context,
- @Nullable Bundle bundle) {
- return ApiLoader.getProvider(context).fromBundle_PlaybackState2(context, bundle);
- }
-}
diff --git a/media/java/android/media/Rating2.java b/media/java/android/media/Rating2.java
index e5b05fb..29bd922 100644
--- a/media/java/android/media/Rating2.java
+++ b/media/java/android/media/Rating2.java
@@ -152,7 +152,8 @@
* or {@link #RATING_PERCENTAGE}.
* @return null if an invalid rating style is passed, a new Rating2 instance otherwise.
*/
- public static @Nullable Rating2 newUnratedRating(@NonNull Context context, @Style int ratingStyle) {
+ public static @Nullable Rating2 newUnratedRating(@NonNull Context context,
+ @Style int ratingStyle) {
return ApiLoader.getProvider(context).newUnratedRating_Rating2(context, ratingStyle);
}
@@ -225,8 +226,7 @@
* {@link #RATING_3_STARS}, {@link #RATING_4_STARS}, {@link #RATING_5_STARS},
* or {@link #RATING_PERCENTAGE}.
*/
- @Style
- public int getRatingStyle() {
+ public @Style int getRatingStyle() {
return mProvider.getRatingStyle_impl();
}
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 6b130cc..051321c 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -775,8 +775,7 @@
public void run() {
final Context context = mContext;
if (context != null) {
- ArrayList<MediaController> controllers
- = new ArrayList<MediaController>();
+ ArrayList<MediaController> controllers = new ArrayList<>();
int size = tokens.size();
for (int i = 0; i < size; i++) {
controllers.add(new MediaController(context, tokens.get(i)));
@@ -814,10 +813,16 @@
private final ISessionTokensListener.Stub mStub = new ISessionTokensListener.Stub() {
@Override
public void onSessionTokensChanged(final List<Bundle> bundles) {
- mExecutor.execute(() -> {
- List<SessionToken2> tokens = toTokenList(mContext, bundles);
- mListener.onSessionTokensChanged(tokens);
- });
+ final Executor executor = mExecutor;
+ if (executor != null) {
+ executor.execute(() -> {
+ final Context context = mContext;
+ final OnSessionTokensChangedListener listener = mListener;
+ if (context != null && listener != null) {
+ listener.onSessionTokensChanged(toTokenList(context, bundles));
+ }
+ });
+ }
}
};
diff --git a/media/java/android/media/update/ApiLoader.java b/media/java/android/media/update/ApiLoader.java
index b928e93..0d190a7 100644
--- a/media/java/android/media/update/ApiLoader.java
+++ b/media/java/android/media/update/ApiLoader.java
@@ -16,6 +16,7 @@
package android.media.update;
+import android.annotation.NonNull;
import android.content.res.Resources;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -33,7 +34,10 @@
private ApiLoader() { }
- public static StaticProvider getProvider(Context context) {
+ public static StaticProvider getProvider(@NonNull Context context) {
+ if (context == null) {
+ throw new IllegalArgumentException("context shouldn't be null");
+ }
try {
return (StaticProvider) getMediaLibraryImpl(context);
} catch (PackageManager.NameNotFoundException | ReflectiveOperationException e) {
diff --git a/media/java/android/media/update/MediaController2Provider.java b/media/java/android/media/update/MediaController2Provider.java
index 06e9544..55672b6 100644
--- a/media/java/android/media/update/MediaController2Provider.java
+++ b/media/java/android/media/update/MediaController2Provider.java
@@ -16,14 +16,13 @@
package android.media.update;
-import android.annotation.NonNull;
import android.app.PendingIntent;
import android.media.AudioAttributes;
import android.media.MediaController2.PlaybackInfo;
import android.media.MediaItem2;
+import android.media.MediaMetadata2;
import android.media.MediaSession2.Command;
import android.media.MediaSession2.PlaylistParams;
-import android.media.PlaybackState2;
import android.media.Rating2;
import android.media.SessionToken2;
import android.net.Uri;
@@ -58,6 +57,9 @@
void setRating_impl(String mediaId, Rating2 rating);
void sendCustomCommand_impl(Command command, Bundle args, ResultReceiver cb);
List<MediaItem2> getPlaylist_impl();
+ void setPlaylist_impl(List<MediaItem2> list, MediaMetadata2 metadata);
+ MediaMetadata2 getPlaylistMetadata_impl();
+ void updatePlaylistMetadata_impl(MediaMetadata2 metadata);
void addPlaylistItem_impl(int index, MediaItem2 item);
void replacePlaylistItem_impl(int index, MediaItem2 item);
@@ -65,7 +67,6 @@
PlaylistParams getPlaylistParams_impl();
void setPlaylistParams_impl(PlaylistParams params);
- PlaybackState2 getPlaybackState_impl();
int getPlayerState_impl();
long getPosition_impl();
float getPlaybackSpeed_impl();
diff --git a/media/java/android/media/update/MediaItem2Provider.java b/media/java/android/media/update/MediaItem2Provider.java
index b494f9e..47db22f 100644
--- a/media/java/android/media/update/MediaItem2Provider.java
+++ b/media/java/android/media/update/MediaItem2Provider.java
@@ -35,6 +35,7 @@
MediaMetadata2 getMetadata_impl();
String getMediaId_impl();
DataSourceDesc getDataSourceDesc_impl();
+ boolean equals_impl(Object obj);
interface BuilderProvider {
Builder setMediaId_impl(String mediaId);
diff --git a/media/java/android/media/update/MediaSession2Provider.java b/media/java/android/media/update/MediaSession2Provider.java
index 5af1952..84ea369 100644
--- a/media/java/android/media/update/MediaSession2Provider.java
+++ b/media/java/android/media/update/MediaSession2Provider.java
@@ -17,6 +17,7 @@
package android.media.update;
import android.app.PendingIntent;
+import android.media.AudioFocusRequest;
import android.media.MediaItem2;
import android.media.MediaMetadata2;
import android.media.MediaPlayerBase;
@@ -46,21 +47,23 @@
void updatePlayer_impl(MediaPlayerBase player, MediaPlaylistAgent playlistAgent,
VolumeProvider2 volumeProvider);
MediaPlayerBase getPlayer_impl();
+ MediaMetadata2 getPlaylistMetadata_impl();
+ void updatePlaylistMetadata_impl(MediaMetadata2 metadata);
+ MediaPlaylistAgent getPlaylistAgent_impl();
VolumeProvider2 getVolumeProvider_impl();
SessionToken2 getToken_impl();
List<ControllerInfo> getConnectedControllers_impl();
void setCustomLayout_impl(ControllerInfo controller, List<CommandButton> layout);
- void setAudioFocusRequest_impl(int focusGain);
+ void setAudioFocusRequest_impl(AudioFocusRequest afr);
void setAllowedCommands_impl(ControllerInfo controller, CommandGroup commands);
void sendCustomCommand_impl(ControllerInfo controller, Command command, Bundle args,
ResultReceiver receiver);
void sendCustomCommand_impl(Command command, Bundle args);
- void setPlaylist_impl(List<MediaItem2> playlist);
void addPlaylistItem_impl(int index, MediaItem2 item);
void removePlaylistItem_impl(MediaItem2 item);
- void editPlaylistItem_impl(MediaItem2 item);
void replacePlaylistItem_impl(int index, MediaItem2 item);
List<MediaItem2> getPlaylist_impl();
+ void setPlaylist_impl(List<MediaItem2> list, MediaMetadata2 metadata);
MediaItem2 getCurrentPlaylistItem_impl();
void setPlaylistParams_impl(PlaylistParams params);
PlaylistParams getPlaylistParams_impl();
diff --git a/media/java/android/media/update/MediaSessionService2Provider.java b/media/java/android/media/update/MediaSessionService2Provider.java
index 8697e70..5eb6254 100644
--- a/media/java/android/media/update/MediaSessionService2Provider.java
+++ b/media/java/android/media/update/MediaSessionService2Provider.java
@@ -20,7 +20,6 @@
import android.content.Intent;
import android.media.MediaSession2;
import android.media.MediaSessionService2.MediaNotification;
-import android.media.PlaybackState2;
import android.os.IBinder;
/**
diff --git a/media/java/android/media/update/PlaybackState2Provider.java b/media/java/android/media/update/PlaybackState2Provider.java
deleted file mode 100644
index 66b8fa5..0000000
--- a/media/java/android/media/update/PlaybackState2Provider.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2018 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.update;
-
-import android.os.Bundle;
-
-/**
- * @hide
- */
-public interface PlaybackState2Provider {
- String toString_impl();
-
- int getState_impl();
-
- long getPosition_impl();
-
- long getBufferedPosition_impl();
-
- float getPlaybackSpeed_impl();
-
- long getLastPositionUpdateTime_impl();
-
- long getCurrentPlaylistItemIndex_impl();
-
- Bundle toBundle_impl();
-}
diff --git a/media/java/android/media/update/StaticProvider.java b/media/java/android/media/update/StaticProvider.java
index 53ced9c..f78d4a4 100644
--- a/media/java/android/media/update/StaticProvider.java
+++ b/media/java/android/media/update/StaticProvider.java
@@ -19,7 +19,6 @@
import android.annotation.Nullable;
import android.app.Notification;
import android.content.Context;
-import android.media.DataSourceDesc;
import android.media.MediaBrowser2;
import android.media.MediaBrowser2.BrowserCallback;
import android.media.MediaController2;
@@ -32,12 +31,10 @@
import android.media.MediaMetadata2;
import android.media.MediaPlaylistAgent;
import android.media.MediaSession2;
-import android.media.MediaSession2.CommandButton.Builder;
import android.media.MediaSession2.PlaylistParams;
import android.media.MediaSession2.SessionCallback;
import android.media.MediaSessionService2;
import android.media.MediaSessionService2.MediaNotification;
-import android.media.PlaybackState2;
import android.media.Rating2;
import android.media.SessionToken2;
import android.media.VolumeProvider2;
@@ -132,10 +129,6 @@
Rating2 newStarRating_Rating2(Context context, int starRatingStyle, float starRating);
Rating2 newPercentageRating_Rating2(Context context, float percent);
- PlaybackState2Provider createPlaybackState2(Context context, PlaybackState2 instance, int state,
- long position, long updateTime, float speed, long bufferedPosition, long activeItemId);
- PlaybackState2 fromBundle_PlaybackState2(Context context, Bundle bundle);
-
MediaPlaylistAgentProvider createMediaPlaylistAgent(Context context,
MediaPlaylistAgent instance);
}
diff --git a/media/java/android/media/update/TransportControlProvider.java b/media/java/android/media/update/TransportControlProvider.java
index a3fb071..eb03ca7f 100644
--- a/media/java/android/media/update/TransportControlProvider.java
+++ b/media/java/android/media/update/TransportControlProvider.java
@@ -17,7 +17,6 @@
package android.media.update;
import android.media.MediaItem2;
-import android.media.PlaybackState2;
/**
* @hide
@@ -34,6 +33,4 @@
void rewind_impl();
void seekTo_impl(long pos);
void skipToPlaylistItem_impl(MediaItem2 item);
-
- PlaybackState2 getPlaybackState_impl();
}
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index ff854c5..3a67142 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -25,6 +25,7 @@
#include <media/IMediaHTTPService.h>
#include <media/mediametadataretriever.h>
#include <media/mediascanner.h>
+#include <nativehelper/ScopedLocalRef.h>
#include <private/media/VideoFrame.h>
#include "jni.h"
@@ -45,6 +46,12 @@
jmethodID createScaledBitmapMethod;
jclass configClazz; // Must be a global ref
jmethodID createConfigMethod;
+ jclass bitmapParamsClazz; // Must be a global ref
+ jfieldID inPreferredConfig;
+ jfieldID outActualConfig;
+ jclass arrayListClazz; // Must be a global ref
+ jmethodID arrayListInit;
+ jmethodID arrayListAdd;
};
static fields_t fields;
@@ -254,16 +261,18 @@
}
static jobject getBitmapFromVideoFrame(
- JNIEnv *env, VideoFrame *videoFrame, jint dst_width, jint dst_height) {
+ JNIEnv *env, VideoFrame *videoFrame, jint dst_width, jint dst_height,
+ SkColorType outColorType) {
ALOGV("getBitmapFromVideoFrame: dimension = %dx%d and bytes = %d",
videoFrame->mDisplayWidth,
videoFrame->mDisplayHeight,
videoFrame->mSize);
- jobject config = env->CallStaticObjectMethod(
- fields.configClazz,
- fields.createConfigMethod,
- GraphicsJNI::colorTypeToLegacyBitmapConfig(kRGB_565_SkColorType));
+ ScopedLocalRef<jobject> config(env,
+ env->CallStaticObjectMethod(
+ fields.configClazz,
+ fields.createConfigMethod,
+ GraphicsJNI::colorTypeToLegacyBitmapConfig(outColorType)));
uint32_t width, height, displayWidth, displayHeight;
bool swapWidthAndHeight = false;
@@ -285,7 +294,7 @@
fields.createBitmapMethod,
width,
height,
- config);
+ config.get());
if (jBitmap == NULL) {
if (env->ExceptionCheck()) {
env->ExceptionClear();
@@ -297,11 +306,19 @@
SkBitmap bitmap;
GraphicsJNI::getSkBitmap(env, jBitmap, &bitmap);
- rotate((uint16_t*)bitmap.getPixels(),
- (uint16_t*)((char*)videoFrame + sizeof(VideoFrame)),
- videoFrame->mWidth,
- videoFrame->mHeight,
- videoFrame->mRotationAngle);
+ if (outColorType == kRGB_565_SkColorType) {
+ rotate((uint16_t*)bitmap.getPixels(),
+ (uint16_t*)((char*)videoFrame + sizeof(VideoFrame)),
+ videoFrame->mWidth,
+ videoFrame->mHeight,
+ videoFrame->mRotationAngle);
+ } else {
+ rotate((uint32_t*)bitmap.getPixels(),
+ (uint32_t*)((char*)videoFrame + sizeof(VideoFrame)),
+ videoFrame->mWidth,
+ videoFrame->mHeight,
+ videoFrame->mRotationAngle);
+ }
if (dst_width <= 0 || dst_height <= 0) {
dst_width = displayWidth;
@@ -323,12 +340,46 @@
dst_width,
dst_height,
true);
+
+ env->DeleteLocalRef(jBitmap);
return scaledBitmap;
}
return jBitmap;
}
+static int getColorFormat(JNIEnv *env, jobject options) {
+ if (options == NULL) {
+ return HAL_PIXEL_FORMAT_RGBA_8888;
+ }
+
+ ScopedLocalRef<jobject> inConfig(env, env->GetObjectField(options, fields.inPreferredConfig));
+ SkColorType prefColorType = GraphicsJNI::getNativeBitmapColorType(env, inConfig.get());
+
+ if (prefColorType == kRGB_565_SkColorType) {
+ return HAL_PIXEL_FORMAT_RGB_565;
+ }
+ return HAL_PIXEL_FORMAT_RGBA_8888;
+}
+
+static SkColorType setOutColorType(JNIEnv *env, int colorFormat, jobject options) {
+ SkColorType outColorType = kN32_SkColorType;
+ if (colorFormat == HAL_PIXEL_FORMAT_RGB_565) {
+ outColorType = kRGB_565_SkColorType;
+ }
+
+ if (options != NULL) {
+ ScopedLocalRef<jobject> config(env,
+ env->CallStaticObjectMethod(
+ fields.configClazz,
+ fields.createConfigMethod,
+ GraphicsJNI::colorTypeToLegacyBitmapConfig(outColorType)));
+
+ env->SetObjectField(options, fields.outActualConfig, config.get());
+ }
+ return outColorType;
+}
+
static jobject android_media_MediaMetadataRetriever_getFrameAtTime(
JNIEnv *env, jobject thiz, jlong timeUs, jint option, jint dst_width, jint dst_height)
{
@@ -351,11 +402,11 @@
return NULL;
}
- return getBitmapFromVideoFrame(env, videoFrame, dst_width, dst_height);
+ return getBitmapFromVideoFrame(env, videoFrame, dst_width, dst_height, kRGB_565_SkColorType);
}
static jobject android_media_MediaMetadataRetriever_getImageAtIndex(
- JNIEnv *env, jobject thiz, jint index)
+ JNIEnv *env, jobject thiz, jint index, jobject params)
{
ALOGV("getImageAtIndex: index %d", index);
sp<MediaMetadataRetriever> retriever = getRetriever(env, thiz);
@@ -364,9 +415,11 @@
return NULL;
}
+ int colorFormat = getColorFormat(env, params);
+
// Call native method to retrieve an image
VideoFrame *videoFrame = NULL;
- sp<IMemory> frameMemory = retriever->getImageAtIndex(index);
+ sp<IMemory> frameMemory = retriever->getImageAtIndex(index, colorFormat);
if (frameMemory != 0) { // cast the shared structure to a VideoFrame object
videoFrame = static_cast<VideoFrame *>(frameMemory->pointer());
}
@@ -375,11 +428,13 @@
return NULL;
}
- return getBitmapFromVideoFrame(env, videoFrame, -1, -1);
+ SkColorType outColorType = setOutColorType(env, colorFormat, params);
+
+ return getBitmapFromVideoFrame(env, videoFrame, -1, -1, outColorType);
}
-static jobjectArray android_media_MediaMetadataRetriever_getFrameAtIndex(
- JNIEnv *env, jobject thiz, jint frameIndex, jint numFrames)
+static jobject android_media_MediaMetadataRetriever_getFrameAtIndex(
+ JNIEnv *env, jobject thiz, jint frameIndex, jint numFrames, jobject params)
{
ALOGV("getFrameAtIndex: frameIndex %d, numFrames %d", frameIndex, numFrames);
sp<MediaMetadataRetriever> retriever = getRetriever(env, thiz);
@@ -389,31 +444,34 @@
return NULL;
}
+ int colorFormat = getColorFormat(env, params);
+
std::vector<sp<IMemory> > frames;
- status_t err = retriever->getFrameAtIndex(&frames, frameIndex, numFrames);
+ status_t err = retriever->getFrameAtIndex(&frames, frameIndex, numFrames, colorFormat);
if (err != OK || frames.size() == 0) {
ALOGE("failed to get frames from retriever, err=%d, size=%zu",
err, frames.size());
return NULL;
}
-
- jobjectArray bitmapArrayObj = env->NewObjectArray(
- frames.size(), fields.bitmapClazz, NULL);
- if (bitmapArrayObj == NULL) {
- ALOGE("can't create bitmap array object");
+ jobject arrayList = env->NewObject(fields.arrayListClazz, fields.arrayListInit);
+ if (arrayList == NULL) {
+ ALOGE("can't create bitmap array list object");
return NULL;
}
+ SkColorType outColorType = setOutColorType(env, colorFormat, params);
+
for (size_t i = 0; i < frames.size(); i++) {
if (frames[i] == NULL || frames[i]->pointer() == NULL) {
ALOGE("video frame at index %zu is a NULL pointer", frameIndex + i);
continue;
}
VideoFrame *videoFrame = static_cast<VideoFrame *>(frames[i]->pointer());
- jobject bitmapObj = getBitmapFromVideoFrame(env, videoFrame, -1, -1);
- env->SetObjectArrayElement(bitmapArrayObj, i, bitmapObj);
+ jobject bitmapObj = getBitmapFromVideoFrame(env, videoFrame, -1, -1, outColorType);
+ env->CallBooleanMethod(arrayList, fields.arrayListAdd, bitmapObj);
+ env->DeleteLocalRef(bitmapObj);
}
- return bitmapArrayObj;
+ return arrayList;
}
static jbyteArray android_media_MediaMetadataRetriever_getEmbeddedPicture(
@@ -488,21 +546,21 @@
// first time an instance of this class is used.
static void android_media_MediaMetadataRetriever_native_init(JNIEnv *env)
{
- jclass clazz = env->FindClass(kClassPathName);
- if (clazz == NULL) {
+ ScopedLocalRef<jclass> clazz(env, env->FindClass(kClassPathName));
+ if (clazz.get() == NULL) {
return;
}
- fields.context = env->GetFieldID(clazz, "mNativeContext", "J");
+ fields.context = env->GetFieldID(clazz.get(), "mNativeContext", "J");
if (fields.context == NULL) {
return;
}
- jclass bitmapClazz = env->FindClass("android/graphics/Bitmap");
- if (bitmapClazz == NULL) {
+ clazz.reset(env->FindClass("android/graphics/Bitmap"));
+ if (clazz.get() == NULL) {
return;
}
- fields.bitmapClazz = (jclass) env->NewGlobalRef(bitmapClazz);
+ fields.bitmapClazz = (jclass) env->NewGlobalRef(clazz.get());
if (fields.bitmapClazz == NULL) {
return;
}
@@ -521,11 +579,11 @@
return;
}
- jclass configClazz = env->FindClass("android/graphics/Bitmap$Config");
- if (configClazz == NULL) {
+ clazz.reset(env->FindClass("android/graphics/Bitmap$Config"));
+ if (clazz.get() == NULL) {
return;
}
- fields.configClazz = (jclass) env->NewGlobalRef(configClazz);
+ fields.configClazz = (jclass) env->NewGlobalRef(clazz.get());
if (fields.configClazz == NULL) {
return;
}
@@ -535,6 +593,42 @@
if (fields.createConfigMethod == NULL) {
return;
}
+
+ clazz.reset(env->FindClass("android/media/MediaMetadataRetriever$BitmapParams"));
+ if (clazz.get() == NULL) {
+ return;
+ }
+ fields.bitmapParamsClazz = (jclass) env->NewGlobalRef(clazz.get());
+ if (fields.bitmapParamsClazz == NULL) {
+ return;
+ }
+ fields.inPreferredConfig = env->GetFieldID(fields.bitmapParamsClazz,
+ "inPreferredConfig", "Landroid/graphics/Bitmap$Config;");
+ if (fields.inPreferredConfig == NULL) {
+ return;
+ }
+ fields.outActualConfig = env->GetFieldID(fields.bitmapParamsClazz,
+ "outActualConfig", "Landroid/graphics/Bitmap$Config;");
+ if (fields.outActualConfig == NULL) {
+ return;
+ }
+
+ clazz.reset(env->FindClass("java/util/ArrayList"));
+ if (clazz.get() == NULL) {
+ return;
+ }
+ fields.arrayListClazz = (jclass) env->NewGlobalRef(clazz.get());
+ if (fields.arrayListClazz == NULL) {
+ return;
+ }
+ fields.arrayListInit = env->GetMethodID(clazz.get(), "<init>", "()V");
+ if (fields.arrayListInit == NULL) {
+ return;
+ }
+ fields.arrayListAdd = env->GetMethodID(clazz.get(), "add", "(Ljava/lang/Object;)Z");
+ if (fields.arrayListAdd == NULL) {
+ return;
+ }
}
static void android_media_MediaMetadataRetriever_native_setup(JNIEnv *env, jobject thiz)
@@ -556,17 +650,36 @@
(void *)android_media_MediaMetadataRetriever_setDataSourceAndHeaders
},
- {"setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaMetadataRetriever_setDataSourceFD},
- {"_setDataSource", "(Landroid/media/MediaDataSource;)V", (void *)android_media_MediaMetadataRetriever_setDataSourceCallback},
- {"_getFrameAtTime", "(JIII)Landroid/graphics/Bitmap;", (void *)android_media_MediaMetadataRetriever_getFrameAtTime},
- {"_getImageAtIndex", "(I)Landroid/graphics/Bitmap;", (void *)android_media_MediaMetadataRetriever_getImageAtIndex},
- {"_getFrameAtIndex", "(II)[Landroid/graphics/Bitmap;", (void *)android_media_MediaMetadataRetriever_getFrameAtIndex},
- {"extractMetadata", "(I)Ljava/lang/String;", (void *)android_media_MediaMetadataRetriever_extractMetadata},
- {"getEmbeddedPicture", "(I)[B", (void *)android_media_MediaMetadataRetriever_getEmbeddedPicture},
- {"release", "()V", (void *)android_media_MediaMetadataRetriever_release},
- {"native_finalize", "()V", (void *)android_media_MediaMetadataRetriever_native_finalize},
- {"native_setup", "()V", (void *)android_media_MediaMetadataRetriever_native_setup},
- {"native_init", "()V", (void *)android_media_MediaMetadataRetriever_native_init},
+ {"setDataSource", "(Ljava/io/FileDescriptor;JJ)V",
+ (void *)android_media_MediaMetadataRetriever_setDataSourceFD},
+ {"_setDataSource", "(Landroid/media/MediaDataSource;)V",
+ (void *)android_media_MediaMetadataRetriever_setDataSourceCallback},
+ {"_getFrameAtTime", "(JIII)Landroid/graphics/Bitmap;",
+ (void *)android_media_MediaMetadataRetriever_getFrameAtTime},
+ {
+ "_getImageAtIndex",
+ "(ILandroid/media/MediaMetadataRetriever$BitmapParams;)Landroid/graphics/Bitmap;",
+ (void *)android_media_MediaMetadataRetriever_getImageAtIndex
+ },
+
+ {
+ "_getFrameAtIndex",
+ "(IILandroid/media/MediaMetadataRetriever$BitmapParams;)Ljava/util/List;",
+ (void *)android_media_MediaMetadataRetriever_getFrameAtIndex
+ },
+
+ {"extractMetadata", "(I)Ljava/lang/String;",
+ (void *)android_media_MediaMetadataRetriever_extractMetadata},
+ {"getEmbeddedPicture", "(I)[B",
+ (void *)android_media_MediaMetadataRetriever_getEmbeddedPicture},
+ {"release", "()V",
+ (void *)android_media_MediaMetadataRetriever_release},
+ {"native_finalize", "()V",
+ (void *)android_media_MediaMetadataRetriever_native_finalize},
+ {"native_setup", "()V",
+ (void *)android_media_MediaMetadataRetriever_native_setup},
+ {"native_init", "()V",
+ (void *)android_media_MediaMetadataRetriever_native_init},
};
// This function only registers the native methods, and is called from
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index 918b82b..918a375 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -1489,7 +1489,7 @@
{"nativePlayNextDataSource", "(J)V", (void *)android_media_MediaPlayer2_playNextDataSource},
{"_setVideoSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaPlayer2_setVideoSurface},
{"getBufferingParams", "()Landroid/media/BufferingParams;", (void *)android_media_MediaPlayer2_getBufferingParams},
- {"setBufferingParams", "(Landroid/media/BufferingParams;)V", (void *)android_media_MediaPlayer2_setBufferingParams},
+ {"_setBufferingParams", "(Landroid/media/BufferingParams;)V", (void *)android_media_MediaPlayer2_setBufferingParams},
{"_prepare", "()V", (void *)android_media_MediaPlayer2_prepare},
{"_start", "()V", (void *)android_media_MediaPlayer2_start},
{"_stop", "()V", (void *)android_media_MediaPlayer2_stop},
@@ -1497,9 +1497,9 @@
{"getVideoWidth", "()I", (void *)android_media_MediaPlayer2_getVideoWidth},
{"getVideoHeight", "()I", (void *)android_media_MediaPlayer2_getVideoHeight},
{"native_getMetrics", "()Landroid/os/PersistableBundle;", (void *)android_media_MediaPlayer2_native_getMetrics},
- {"setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer2_setPlaybackParams},
+ {"_setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer2_setPlaybackParams},
{"getPlaybackParams", "()Landroid/media/PlaybackParams;", (void *)android_media_MediaPlayer2_getPlaybackParams},
- {"setSyncParams", "(Landroid/media/SyncParams;)V", (void *)android_media_MediaPlayer2_setSyncParams},
+ {"_setSyncParams", "(Landroid/media/SyncParams;)V", (void *)android_media_MediaPlayer2_setSyncParams},
{"getSyncParams", "()Landroid/media/SyncParams;", (void *)android_media_MediaPlayer2_getSyncParams},
{"_seekTo", "(JI)V", (void *)android_media_MediaPlayer2_seekTo},
{"_notifyAt", "(J)V", (void *)android_media_MediaPlayer2_notifyAt},
@@ -1522,9 +1522,9 @@
{"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer2_native_setup},
{"native_finalize", "()V", (void *)android_media_MediaPlayer2_native_finalize},
{"getAudioSessionId", "()I", (void *)android_media_MediaPlayer2_get_audio_session_id},
- {"setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer2_set_audio_session_id},
+ {"_setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer2_set_audio_session_id},
{"_setAuxEffectSendLevel", "(F)V", (void *)android_media_MediaPlayer2_setAuxEffectSendLevel},
- {"attachAuxEffect", "(I)V", (void *)android_media_MediaPlayer2_attachAuxEffect},
+ {"_attachAuxEffect", "(I)V", (void *)android_media_MediaPlayer2_attachAuxEffect},
// Modular DRM
{ "_prepareDrm", "([B[B)V", (void *)android_media_MediaPlayer2_prepareDrm },
{ "_releaseDrm", "()V", (void *)android_media_MediaPlayer2_releaseDrm },
diff --git a/packages/CaptivePortalLogin/Android.mk b/packages/CaptivePortalLogin/Android.mk
index e6e0ad3..7dc23ff 100644
--- a/packages/CaptivePortalLogin/Android.mk
+++ b/packages/CaptivePortalLogin/Android.mk
@@ -2,6 +2,7 @@
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml b/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml
index 2324593..c292323 100644
--- a/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml
+++ b/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml
@@ -27,12 +27,17 @@
android:layout_height="wrap_content" />
</FrameLayout>
- <WebView
- android:id="@+id/webview"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_alignParentBottom="false"
- android:layout_alignParentRight="false" />
+ <android.support.v4.widget.SwipeRefreshLayout
+ android:id="@+id/swipe_refresh"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <WebView
+ android:id="@+id/webview"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentBottom="false"
+ android:layout_alignParentRight="false" />
+ </android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>
</FrameLayout>
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index e13aba7..4db0034 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -34,6 +34,7 @@
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
+import android.support.v4.widget.SwipeRefreshLayout;
import android.util.ArrayMap;
import android.util.Log;
import android.util.TypedValue;
@@ -88,6 +89,7 @@
private ConnectivityManager mCm;
private boolean mLaunchBrowser = false;
private MyWebViewClient mWebViewClient;
+ private SwipeRefreshLayout mSwipeRefreshLayout;
// Ensures that done() happens once exactly, handling concurrent callers with atomic operations.
private final AtomicBoolean isDone = new AtomicBoolean(false);
@@ -159,6 +161,13 @@
// Start initial page load so WebView finishes loading proxy settings.
// Actual load of mUrl is initiated by MyWebViewClient.
webview.loadData("", "text/html", null);
+
+ mSwipeRefreshLayout = findViewById(R.id.swipe_refresh);
+ mSwipeRefreshLayout.setOnRefreshListener(() -> {
+ webview.reload();
+ mSwipeRefreshLayout.setRefreshing(true);
+ });
+
}
// Find WebView's proxy BroadcastReceiver and prompt it to read proxy system properties.
@@ -393,6 +402,7 @@
public void onPageFinished(WebView view, String url) {
mPagesLoaded++;
getProgressBar().setVisibility(View.INVISIBLE);
+ mSwipeRefreshLayout.setRefreshing(false);
if (mPagesLoaded == 1) {
// Now that WebView has loaded at least one page we know it has read in the proxy
// settings. Now prompt the WebView read the Network-specific proxy settings.
diff --git a/packages/SettingsLib/common.mk b/packages/SettingsLib/common.mk
index 3c2ca2d..15b50d7 100644
--- a/packages/SettingsLib/common.mk
+++ b/packages/SettingsLib/common.mk
@@ -34,21 +34,21 @@
# Include support-v7-appcompat, if not already included
ifeq (,$(findstring android-support-v7-appcompat,$(LOCAL_STATIC_JAVA_LIBRARIES)))
-LOCAL_RESOURCE_DIR += frameworks/support/v7/appcompat/res
+LOCAL_RESOURCE_DIR += prebuilts/sdk/current/support/v7/appcompat/res
LOCAL_AAPT_FLAGS += --extra-packages android.support.v7.appcompat
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-appcompat
endif
# Include support-v7-recyclerview, if not already included
ifeq (,$(findstring android-support-v7-recyclerview,$(LOCAL_STATIC_JAVA_LIBRARIES)))
-LOCAL_RESOURCE_DIR += frameworks/support/v7/recyclerview/res
+LOCAL_RESOURCE_DIR += prebuilts/sdk/current/support/v7/recyclerview/res
LOCAL_AAPT_FLAGS += --extra-packages android.support.v7.recyclerview
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-recyclerview
endif
# Include android-support-v7-preference, if not already included
ifeq (,$(findstring android-support-v7-preference,$(LOCAL_STATIC_JAVA_LIBRARIES)))
-LOCAL_RESOURCE_DIR += frameworks/support/v7/preference/res
+LOCAL_RESOURCE_DIR += prebuilts/sdk/current/support/v7/preference/res
LOCAL_AAPT_FLAGS += --extra-packages android.support.v7.preference
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-preference
endif
diff --git a/packages/SettingsLib/res/color/batterymeter_plus_color.xml b/packages/SettingsLib/res/color/batterymeter_plus_color.xml
new file mode 100644
index 0000000..949bede
--- /dev/null
+++ b/packages/SettingsLib/res/color/batterymeter_plus_color.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="?android:attr/colorError" />
+</selector>
diff --git a/packages/SettingsLib/res/layout/zen_mode_duration_dialog.xml b/packages/SettingsLib/res/layout/zen_mode_duration_dialog.xml
new file mode 100644
index 0000000..6552296
--- /dev/null
+++ b/packages/SettingsLib/res/layout/zen_mode_duration_dialog.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/zen_duration_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport ="true"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:id="@+id/zen_duration_dialog_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <com.android.settingslib.notification.ZenRadioLayout
+ android:id="@+id/zen_duration_conditions"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_marginEnd="4dp"
+ android:layout_marginStart="4dp"
+ android:paddingBottom="4dp"
+ android:orientation="horizontal">
+ <RadioGroup
+ android:id="@+id/zen_radio_buttons"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ <LinearLayout
+ android:id="@+id/zen_radio_buttons_content"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical"/>
+ </com.android.settingslib.notification.ZenRadioLayout>
+ </LinearLayout>
+
+</ScrollView>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 72d7bfa..e77db82 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1062,10 +1062,13 @@
<!-- Content description of zen mode time condition minus button (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_manual_zen_less_time">Less time.</string>
- <!-- Do not disturb: Label for button in enable zen dialog that will turn on zen mode. [CHAR LIMIT=30] -->
- <string name="zen_mode_enable_dialog_turn_on">Turn on</string>
<!-- Button label for generic cancel action [CHAR LIMIT=20] -->
<string name="cancel">Cancel</string>
+ <!-- Button label for generic OK action [CHAR LIMIT=20] -->
+ <string name="okay">OK</string>
+
+ <!-- Do not disturb: Label for button in enable zen dialog that will turn on zen mode. [CHAR LIMIT=30] -->
+ <string name="zen_mode_enable_dialog_turn_on">Turn on</string>
<!-- Do not disturb: Title for the Do not Disturb dialog to turn on Do not disturb. [CHAR LIMIT=50]-->
<string name="zen_mode_settings_turn_on_dialog_title">Turn on Do Not Disturb</string>
<!-- Sound: Summary for the Do not Disturb option when there is no automatic rules turned on. [CHAR LIMIT=NONE]-->
@@ -1083,4 +1086,8 @@
<!-- Alarm template for far in the future alarms [CHAR LIMIT=25] -->
<string name="alarm_template_far">on <xliff:g id="when" example="Fri 7:00 AM">%1$s</xliff:g></string>
+ <!-- Do not disturb: Title for the dnd duration setting (user can specify how long dnd will last when toggling dnd on from qs or settings) [CHAR LIMIT=30] -->
+ <string name="zen_mode_duration_settings_title">Duration</string>
+ <!-- Do not disturb: Duration option to always prompt for the duration of dnd -->
+ <string name="zen_mode_duration_always_prompt_title">Ask every time</string>
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 61e113b..56a242a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -1,7 +1,6 @@
package com.android.settingslib;
import android.annotation.ColorInt;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
@@ -142,7 +141,7 @@
public static Drawable getUserIcon(Context context, UserManager um, UserInfo user) {
final int iconSize = UserIconDrawable.getSizeForList(context);
if (user.isManagedProfile()) {
- Drawable drawable = UserIconDrawable.getManagedUserBadgeDrawable(context);
+ Drawable drawable = UserIconDrawable.getManagedUserDrawable(context);
drawable.setBounds(0, 0, iconSize, iconSize);
return drawable;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
index 7f469b5..54d1aba 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
@@ -16,6 +16,7 @@
package com.android.settingslib.drawable;
+import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
@@ -36,6 +37,7 @@
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
import com.android.settingslib.R;
@@ -69,15 +71,23 @@
private float mBadgeMargin;
/**
- * Gets the system default managed-user badge as a drawable
+ * Gets the system default managed-user badge as a drawable. This drawable is tint-able.
+ * For badging purpose, consider
+ * {@link android.content.pm.PackageManager#getUserBadgedDrawableForDensity(Drawable, UserHandle, Rect, int)}.
+ *
* @param context
* @return drawable containing just the badge
*/
- public static Drawable getManagedUserBadgeDrawable(Context context) {
- int displayDensity = context.getResources().getDisplayMetrics().densityDpi;
+ public static Drawable getManagedUserDrawable(Context context) {
+ return getDrawableForDisplayDensity
+ (context, com.android.internal.R.drawable.ic_corp_user_badge);
+ }
+
+ private static Drawable getDrawableForDisplayDensity(
+ Context context, @DrawableRes int drawable) {
+ int density = context.getResources().getDisplayMetrics().densityDpi;
return context.getResources().getDrawableForDensity(
- com.android.internal.R.drawable.ic_corp_user_badge,
- displayDensity, context.getTheme());
+ drawable, density, context.getTheme());
}
/**
@@ -164,7 +174,8 @@
boolean isManaged = context.getSystemService(DevicePolicyManager.class)
.getProfileOwnerAsUser(userId) != null;
if (isManaged) {
- badge = getManagedUserBadgeDrawable(context);
+ badge = getDrawableForDisplayDensity(
+ context, com.android.internal.R.drawable.ic_corp_badge_case);
}
return setBadge(badge);
}
@@ -322,7 +333,6 @@
mIntrinsicRadius, mIconPaint);
canvas.restoreToCount(saveId);
}
-
if (mFrameColor != null) {
mFramePaint.setColor(mFrameColor.getColorForState(getState(), Color.TRANSPARENT));
}
@@ -343,7 +353,6 @@
final float borderRadius = mBadge.getBounds().width() * 0.5f + mBadgeMargin;
canvas.drawCircle(badgeLeft + mBadgeRadius, badgeTop + mBadgeRadius,
borderRadius, mClearPaint);
-
mBadge.draw(canvas);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
index 4fe9d56..e2f279a9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
@@ -54,6 +54,7 @@
private int mLevel = -1;
private boolean mCharging;
private boolean mPowerSaveEnabled;
+ private boolean mPowerSaveAsColorError = true;
private boolean mShowPercent;
private static final boolean SINGLE_DIGIT_PERCENT = false;
@@ -150,7 +151,8 @@
mBoltPaint.setColor(Utils.getDefaultColor(mContext, R.color.batterymeter_bolt_color));
mBoltPoints = loadPoints(res, R.array.batterymeter_bolt_points);
- mPlusPaint = new Paint(mBoltPaint);
+ mPlusPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mPlusPaint.setColor(Utils.getDefaultColor(mContext, R.color.batterymeter_plus_color));
mPlusPoints = loadPoints(res, R.array.batterymeter_plus_points);
mIntrinsicWidth = context.getResources().getDimensionPixelSize(R.dimen.battery_width);
@@ -195,6 +197,10 @@
postInvalidate();
}
+ protected void setPowerSaveAsColorError(boolean asError) {
+ mPowerSaveAsColorError = asError;
+ }
+
// an approximation of View.postInvalidate()
protected void postInvalidate() {
unscheduleSelf(this::invalidateSelf);
@@ -254,10 +260,6 @@
}
private int getColorForLevel(int percent) {
- // If we are in power save mode, always use the normal color.
- if (mPowerSaveEnabled) {
- return mIconTint;
- }
int thresh, color = 0;
for (int i = 0; i < mColors.length; i += 2) {
thresh = mColors[i];
@@ -279,7 +281,6 @@
mIconTint = fillColor;
mFramePaint.setColor(backgroundColor);
mBoltPaint.setColor(fillColor);
- mPlusPaint.setColor(fillColor);
mChargeColor = fillColor;
invalidateSelf();
}
@@ -392,14 +393,16 @@
mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height());
}
- float boltPct = (mPlusFrame.bottom - levelTop) / (mPlusFrame.bottom - mPlusFrame.top);
- boltPct = Math.min(Math.max(boltPct, 0), 1);
- if (boltPct <= BOLT_LEVEL_THRESHOLD) {
- // draw the bolt if opaque
+ float fillPct = (mPlusFrame.bottom - levelTop) / (mPlusFrame.bottom - mPlusFrame.top);
+ fillPct = Math.min(Math.max(fillPct, 0), 1);
+ if (fillPct <= BOLT_LEVEL_THRESHOLD) {
+ // draw the plus if opaque
c.drawPath(mPlusPath, mPlusPaint);
} else {
- // otherwise cut the bolt out of the overall shape
mShapePath.op(mPlusPath, Path.Op.DIFFERENCE);
+ if (mPowerSaveAsColorError) {
+ c.drawPath(mPlusPath, mPlusPaint);
+ }
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
new file mode 100644
index 0000000..7369ba8
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.notification;
+
+import android.app.ActivityManager;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.provider.Settings;
+import android.service.notification.Condition;
+import android.service.notification.ZenModeConfig;
+import android.support.annotation.VisibleForTesting;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.CompoundButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.policy.PhoneWindow;
+import com.android.settingslib.R;
+
+import java.util.Arrays;
+
+public class ZenDurationDialog {
+ private static final int[] MINUTE_BUCKETS = ZenModeConfig.MINUTE_BUCKETS;
+ @VisibleForTesting protected static final int MIN_BUCKET_MINUTES = MINUTE_BUCKETS[0];
+ @VisibleForTesting protected static final int MAX_BUCKET_MINUTES =
+ MINUTE_BUCKETS[MINUTE_BUCKETS.length - 1];
+ private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60);
+ @VisibleForTesting protected int mBucketIndex = -1;
+
+ @VisibleForTesting protected static final int FOREVER_CONDITION_INDEX = 0;
+ @VisibleForTesting protected static final int COUNTDOWN_CONDITION_INDEX = 1;
+ @VisibleForTesting protected static final int ALWAYS_ASK_CONDITION_INDEX = 2;
+
+ @VisibleForTesting protected Context mContext;
+ @VisibleForTesting protected LinearLayout mZenRadioGroupContent;
+ private RadioGroup mZenRadioGroup;
+ private int MAX_MANUAL_DND_OPTIONS = 3;
+
+ @VisibleForTesting protected LayoutInflater mLayoutInflater;
+
+ public ZenDurationDialog(Context context) {
+ mContext = context;
+ }
+
+ public Dialog createDialog() {
+ int zenDuration = Settings.Global.getInt(
+ mContext.getContentResolver(), Settings.Global.ZEN_DURATION,
+ Settings.Global.ZEN_DURATION_FOREVER);
+
+ final AlertDialog.Builder builder = new AlertDialog.Builder(mContext)
+ .setTitle(R.string.zen_mode_duration_settings_title)
+ .setNegativeButton(R.string.cancel, null)
+ .setPositiveButton(R.string.okay,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ updateZenDuration(zenDuration);
+ }
+ });
+
+ View contentView = getContentView();
+ setupRadioButtons(zenDuration);
+ builder.setView(contentView);
+ return builder.create();
+ }
+
+ @VisibleForTesting
+ protected void updateZenDuration(int currZenDuration) {
+ final int checkedRadioButtonId = mZenRadioGroup.getCheckedRadioButtonId();
+
+ int newZenDuration = Settings.Global.getInt(
+ mContext.getContentResolver(), Settings.Global.ZEN_DURATION,
+ Settings.Global.ZEN_DURATION_FOREVER);
+ switch (checkedRadioButtonId) {
+ case FOREVER_CONDITION_INDEX:
+ newZenDuration = Settings.Global.ZEN_DURATION_FOREVER;
+ MetricsLogger.action(mContext,
+ MetricsProto.MetricsEvent.
+ NOTIFICATION_ZEN_MODE_DURATION_FOREVER);
+ break;
+ case COUNTDOWN_CONDITION_INDEX:
+ ConditionTag tag = getConditionTagAt(checkedRadioButtonId);
+ newZenDuration = tag.countdownZenDuration;
+ MetricsLogger.action(mContext,
+ MetricsProto.MetricsEvent.
+ NOTIFICATION_ZEN_MODE_DURATION_TIME,
+ newZenDuration);
+ break;
+ case ALWAYS_ASK_CONDITION_INDEX:
+ newZenDuration = Settings.Global.ZEN_DURATION_PROMPT;
+ MetricsLogger.action(mContext,
+ MetricsProto.MetricsEvent.
+ NOTIFICATION_ZEN_MODE_DURATION_PROMPT);
+ break;
+ }
+
+ if (currZenDuration != newZenDuration) {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.ZEN_DURATION, newZenDuration);
+ }
+ }
+
+ @VisibleForTesting
+ protected View getContentView() {
+ if (mLayoutInflater == null) {
+ mLayoutInflater = new PhoneWindow(mContext).getLayoutInflater();
+ }
+ View contentView = mLayoutInflater.inflate(R.layout.zen_mode_duration_dialog,
+ null);
+ ScrollView container = (ScrollView) contentView.findViewById(R.id.zen_duration_container);
+
+ mZenRadioGroup = container.findViewById(R.id.zen_radio_buttons);
+ mZenRadioGroupContent = container.findViewById(R.id.zen_radio_buttons_content);
+
+ for (int i = 0; i < MAX_MANUAL_DND_OPTIONS; i++) {
+ final View radioButton = mLayoutInflater.inflate(R.layout.zen_mode_radio_button,
+ mZenRadioGroup, false);
+ mZenRadioGroup.addView(radioButton);
+ radioButton.setId(i);
+
+ final View radioButtonContent = mLayoutInflater.inflate(R.layout.zen_mode_condition,
+ mZenRadioGroupContent, false);
+ radioButtonContent.setId(i + MAX_MANUAL_DND_OPTIONS);
+ mZenRadioGroupContent.addView(radioButtonContent);
+ }
+
+ return contentView;
+ }
+
+ @VisibleForTesting
+ protected void setupRadioButtons(int zenDuration) {
+ int checkedIndex = ALWAYS_ASK_CONDITION_INDEX;
+ if (zenDuration == 0) {
+ checkedIndex = FOREVER_CONDITION_INDEX;
+ } else if (zenDuration > 0) {
+ checkedIndex = COUNTDOWN_CONDITION_INDEX;
+ }
+
+ bindTag(zenDuration, mZenRadioGroupContent.getChildAt(FOREVER_CONDITION_INDEX),
+ FOREVER_CONDITION_INDEX);
+ bindTag(zenDuration, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX),
+ COUNTDOWN_CONDITION_INDEX);
+ bindTag(zenDuration, mZenRadioGroupContent.getChildAt(ALWAYS_ASK_CONDITION_INDEX),
+ ALWAYS_ASK_CONDITION_INDEX);
+ getConditionTagAt(checkedIndex).rb.setChecked(true);
+ }
+
+ private void bindTag(final int currZenDuration, final View row, final int rowIndex) {
+ final ConditionTag tag = row.getTag() != null ? (ConditionTag) row.getTag() :
+ new ConditionTag();
+ row.setTag(tag);
+
+ if (tag.rb == null) {
+ tag.rb = (RadioButton) mZenRadioGroup.getChildAt(rowIndex);
+ }
+
+ // if duration is set to forever or always prompt, then countdown time defaults to 1 hour
+ if (currZenDuration <= 0) {
+ tag.countdownZenDuration = MINUTE_BUCKETS[DEFAULT_BUCKET_INDEX];
+ } else {
+ tag.countdownZenDuration = currZenDuration;
+ }
+
+ tag.rb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (isChecked) {
+ tag.rb.setChecked(true);
+ }
+ }
+ });
+
+ updateUi(tag, row, rowIndex);
+ }
+
+ @VisibleForTesting
+ protected ConditionTag getConditionTagAt(int index) {
+ return (ConditionTag) mZenRadioGroupContent.getChildAt(index).getTag();
+ }
+
+
+ private void setupUi(ConditionTag tag, View row) {
+ tag.lines = row.findViewById(android.R.id.content);
+ tag.line1 = (TextView) row.findViewById(android.R.id.text1);
+
+ // text2 is not used in zen duration dialog
+ row.findViewById(android.R.id.text2).setVisibility(View.GONE);
+
+ tag.lines.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ tag.rb.setChecked(true);
+ }
+ });
+ }
+
+ private void updateButtons(ConditionTag tag, View row, int rowIndex) {
+ // minus button
+ final ImageView button1 = (ImageView) row.findViewById(android.R.id.button1);
+ button1.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onClickTimeButton(row, tag, false /*down*/, rowIndex);
+ }
+ });
+
+ // plus button
+ final ImageView button2 = (ImageView) row.findViewById(android.R.id.button2);
+ button2.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onClickTimeButton(row, tag, true /*up*/, rowIndex);
+ }
+ });
+
+ final long time = tag.countdownZenDuration;
+ if (rowIndex == COUNTDOWN_CONDITION_INDEX) {
+ button1.setVisibility(View.VISIBLE);
+ button2.setVisibility(View.VISIBLE);
+
+ button1.setEnabled(time > MIN_BUCKET_MINUTES);
+ button2.setEnabled(tag.countdownZenDuration != MAX_BUCKET_MINUTES);
+
+ button1.setAlpha(button1.isEnabled() ? 1f : .5f);
+ button2.setAlpha(button2.isEnabled() ? 1f : .5f);
+ } else {
+ button1.setVisibility(View.GONE);
+ button2.setVisibility(View.GONE);
+ }
+ }
+
+ @VisibleForTesting
+ protected void updateUi(ConditionTag tag, View row, int rowIndex) {
+ if (tag.lines == null) {
+ setupUi(tag, row);
+ }
+
+ updateButtons(tag, row, rowIndex);
+
+ String radioContentText = "";
+ switch (rowIndex) {
+ case FOREVER_CONDITION_INDEX:
+ radioContentText = mContext.getString(
+ com.android.internal.R.string.zen_mode_forever);
+ break;
+ case COUNTDOWN_CONDITION_INDEX:
+ Condition condition = ZenModeConfig.toTimeCondition(mContext,
+ tag.countdownZenDuration, ActivityManager.getCurrentUser(), false);
+ radioContentText = condition.line1;
+ break;
+ case ALWAYS_ASK_CONDITION_INDEX:
+ radioContentText = mContext.getString(
+ R.string.zen_mode_duration_always_prompt_title);
+ break;
+ }
+
+ tag.line1.setText(radioContentText);
+ }
+
+ @VisibleForTesting
+ protected void onClickTimeButton(View row, ConditionTag tag, boolean up, int rowId) {
+ int newDndTimeDuration = -1;
+ final int N = MINUTE_BUCKETS.length;
+ if (mBucketIndex == -1) {
+ // not on a known index, search for the next or prev bucket by time
+ final long time = tag.countdownZenDuration;
+ for (int i = 0; i < N; i++) {
+ int j = up ? i : N - 1 - i;
+ final int bucketMinutes = MINUTE_BUCKETS[j];
+ if (up && bucketMinutes > time || !up && bucketMinutes < time) {
+ mBucketIndex = j;
+ newDndTimeDuration = bucketMinutes;
+ break;
+ }
+ }
+ if (newDndTimeDuration == -1) {
+ mBucketIndex = DEFAULT_BUCKET_INDEX;
+ newDndTimeDuration = MINUTE_BUCKETS[mBucketIndex];
+ }
+ } else {
+ // on a known index, simply increment or decrement
+ mBucketIndex = Math.max(0, Math.min(N - 1, mBucketIndex + (up ? 1 : -1)));
+ newDndTimeDuration = MINUTE_BUCKETS[mBucketIndex];
+ }
+ tag.countdownZenDuration = newDndTimeDuration;
+ bindTag(newDndTimeDuration, row, rowId);
+ tag.rb.setChecked(true);
+ }
+
+ // used as the view tag on condition rows
+ @VisibleForTesting
+ protected static class ConditionTag {
+ public RadioButton rb;
+ public View lines;
+ public TextView line1;
+ public int countdownZenDuration; // only important for countdown radio button
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 2482095..085e112 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -563,8 +563,7 @@
// If there were no scan results, create an AP for the currently connected network (if
// it exists).
- // TODO(sghuman): Investigate if this works for an ephemeral (auto-connected) network
- // when there are no scan results, as it may not have a valid WifiConfiguration
+ // TODO(b/b/73076869): Add support for passpoint (ephemeral) networks
if (accessPoints.isEmpty() && connectionConfig != null) {
AccessPoint activeAp = new AccessPoint(mContext, connectionConfig);
activeAp.update(connectionConfig, mLastInfo, mLastNetworkInfo);
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 54c02a2..e435a72 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -18,9 +18,11 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -50,6 +52,7 @@
import android.text.style.TtsSpan;
import com.android.settingslib.R;
+import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.wifi.AccessPoint.Speed;
import org.junit.Before;
@@ -61,6 +64,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.concurrent.CountDownLatch;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -79,6 +83,8 @@
private Context mContext;
@Mock private RssiCurve mockBadgeCurve;
@Mock private WifiNetworkScoreCache mockWifiNetworkScoreCache;
+ public static final int NETWORK_ID = 123;
+ public static final int DEFAULT_RSSI = -55;
private static ScanResult createScanResult(String ssid, String bssid, int rssi) {
ScanResult scanResult = new ScanResult();
@@ -753,16 +759,15 @@
assertThat(ap.update(config, wifiInfo, newInfo)).isFalse();
}
@Test
- public void testUpdateWithConfigChangeOnly_returnsFalseButInvokesListener() {
- int networkId = 123;
- int rssi = -55;
+ public void testUpdateWithConfigChangeOnly_returnsFalseButInvokesListener()
+ throws InterruptedException {
WifiConfiguration config = new WifiConfiguration();
- config.networkId = networkId;
+ config.networkId = NETWORK_ID;
config.numNoInternetAccessReports = 1;
WifiInfo wifiInfo = new WifiInfo();
- wifiInfo.setNetworkId(networkId);
- wifiInfo.setRssi(rssi);
+ wifiInfo.setNetworkId(NETWORK_ID);
+ wifiInfo.setRssi(DEFAULT_RSSI);
NetworkInfo networkInfo =
new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
@@ -770,8 +775,8 @@
AccessPoint ap = new TestAccessPointBuilder(mContext)
.setNetworkInfo(networkInfo)
- .setNetworkId(networkId)
- .setRssi(rssi)
+ .setNetworkId(NETWORK_ID)
+ .setRssi(DEFAULT_RSSI)
.setWifiInfo(wifiInfo)
.build();
@@ -781,18 +786,131 @@
config.validatedInternetAccess = true;
assertThat(ap.update(newConfig, wifiInfo, networkInfo)).isFalse();
+
+ // Wait for MainHandler to process callback
+ CountDownLatch latch = new CountDownLatch(1);
+ ThreadUtils.postOnMainThread(latch::countDown);
+
+ latch.await();
verify(mockListener).onAccessPointChanged(ap);
}
@Test
- public void testUpdateWithNullWifiConfiguration_doesNotThrowNPE() {
- int networkId = 123;
- int rssi = -55;
+ public void testConnectionInfo_doesNotThrowNPE_ifListenerIsNulledWhileAwaitingExecution()
+ throws InterruptedException {
WifiConfiguration config = new WifiConfiguration();
- config.networkId = networkId;
+ config.networkId = NETWORK_ID;
+ config.numNoInternetAccessReports = 1;
+
WifiInfo wifiInfo = new WifiInfo();
- wifiInfo.setNetworkId(networkId);
- wifiInfo.setRssi(rssi);
+ wifiInfo.setNetworkId(NETWORK_ID);
+ wifiInfo.setRssi(DEFAULT_RSSI);
+
+ NetworkInfo networkInfo =
+ new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
+ networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
+
+ AccessPoint ap = new TestAccessPointBuilder(mContext)
+ .setNetworkInfo(networkInfo)
+ .setNetworkId(NETWORK_ID)
+ .setRssi(DEFAULT_RSSI)
+ .setWifiInfo(wifiInfo)
+ .build();
+
+ WifiConfiguration newConfig = new WifiConfiguration(config);
+ config.validatedInternetAccess = true;
+
+ performGivenUpdateAndThenNullListenerBeforeResumingMainHandlerExecution(
+ ap, () -> assertThat(ap.update(newConfig, wifiInfo, networkInfo)).isFalse());
+
+ }
+
+ private void performGivenUpdateAndThenNullListenerBeforeResumingMainHandlerExecution(
+ AccessPoint ap, Runnable r) {
+ AccessPoint.AccessPointListener mockListener = mock(AccessPoint.AccessPointListener.class);
+ ap.setListener(mockListener);
+
+ // Put a latch on the MainHandler to prevent the callback from being invoked instantly
+ CountDownLatch latch1 = new CountDownLatch(1);
+ ThreadUtils.postOnMainThread(() -> {
+ try{
+ latch1.await();
+ } catch (InterruptedException e) {
+ fail("Interruped Exception thrown while awaiting latch countdown");
+ }
+ });
+
+ r.run();
+
+ ap.setListener(null);
+ latch1.countDown();
+
+ // The second latch ensures the previously posted listener invocation has processed on the
+ // main thread.
+ CountDownLatch latch2 = new CountDownLatch(1);
+ ThreadUtils.postOnMainThread(latch2::countDown);
+
+ try{
+ latch2.await();
+ } catch (InterruptedException e) {
+ fail("Interruped Exception thrown while awaiting latch countdown");
+ }
+ }
+
+ @Test
+ public void testUpdateScanResults_doesNotThrowNPE_ifListenerIsNulledWhileAwaitingExecution()
+ throws InterruptedException {
+ String ssid = "ssid";
+ int newRssi = -80;
+ AccessPoint ap = new TestAccessPointBuilder(mContext).setSsid(ssid).build();
+
+ ScanResult scanResult = new ScanResult();
+ scanResult.SSID = ssid;
+ scanResult.level = newRssi;
+ scanResult.BSSID = "bssid";
+ scanResult.timestamp = SystemClock.elapsedRealtime() * 1000;
+ scanResult.capabilities = "";
+
+ performGivenUpdateAndThenNullListenerBeforeResumingMainHandlerExecution(
+ ap, () -> ap.setScanResults(Collections.singletonList(scanResult)));
+ }
+
+ @Test
+ public void testUpdateConfig_doesNotThrowNPE_ifListenerIsNulledWhileAwaitingExecution()
+ throws InterruptedException {
+ WifiConfiguration config = new WifiConfiguration();
+ config.networkId = NETWORK_ID;
+ config.numNoInternetAccessReports = 1;
+
+ WifiInfo wifiInfo = new WifiInfo();
+ wifiInfo.setNetworkId(NETWORK_ID);
+ wifiInfo.setRssi(DEFAULT_RSSI);
+
+ NetworkInfo networkInfo =
+ new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
+ networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
+
+ AccessPoint ap = new TestAccessPointBuilder(mContext)
+ .setNetworkInfo(networkInfo)
+ .setNetworkId(NETWORK_ID)
+ .setRssi(DEFAULT_RSSI)
+ .setWifiInfo(wifiInfo)
+ .build();
+
+ WifiConfiguration newConfig = new WifiConfiguration(config);
+ config.validatedInternetAccess = true;
+
+ performGivenUpdateAndThenNullListenerBeforeResumingMainHandlerExecution(
+ ap, () -> ap.update(newConfig));
+ }
+
+ @Test
+ public void testUpdateWithNullWifiConfiguration_doesNotThrowNPE() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.networkId = NETWORK_ID;
+ WifiInfo wifiInfo = new WifiInfo();
+ wifiInfo.setNetworkId(NETWORK_ID);
+ wifiInfo.setRssi(DEFAULT_RSSI);
NetworkInfo networkInfo =
new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
@@ -800,8 +918,8 @@
AccessPoint ap = new TestAccessPointBuilder(mContext)
.setNetworkInfo(networkInfo)
- .setNetworkId(networkId)
- .setRssi(rssi)
+ .setNetworkId(NETWORK_ID)
+ .setRssi(DEFAULT_RSSI)
.setWifiInfo(wifiInfo)
.build();
@@ -847,34 +965,34 @@
.thenReturn(buildScoredNetworkWithGivenBadgeCurve(badgeCurve2));
ap.update(
- mockWifiNetworkScoreCache, true /* scoringUiEnabled */, MAX_SCORE_CACHE_AGE_MILLIS);
+ mockWifiNetworkScoreCache, true /* scoringUiEnabled */, MAX_SCORE_CACHE_AGE_MILLIS);
assertThat(ap.getSpeed()).isEqualTo(speed1);
}
@Test
public void testSpeedLabelFallbackScoreIgnoresNullCurves() {
- int rssi = -55;
String bssid = "00:00:00:00:00:00";
- int networkId = 123;
WifiInfo info = new WifiInfo();
- info.setRssi(rssi);
+ info.setRssi(DEFAULT_RSSI);
info.setSSID(WifiSsid.createFromAsciiEncoded(TEST_SSID));
info.setBSSID(bssid);
- info.setNetworkId(networkId);
+ info.setNetworkId(NETWORK_ID);
ArrayList<ScanResult> scanResults = new ArrayList<>();
- ScanResult scanResultUnconnected = createScanResult(TEST_SSID, "11:11:11:11:11:11", rssi);
+ ScanResult scanResultUnconnected =
+ createScanResult(TEST_SSID, "11:11:11:11:11:11", DEFAULT_RSSI);
scanResults.add(scanResultUnconnected);
- ScanResult scanResultConnected = createScanResult(TEST_SSID, bssid, rssi);
+ ScanResult scanResultConnected =
+ createScanResult(TEST_SSID, bssid, DEFAULT_RSSI);
scanResults.add(scanResultConnected);
AccessPoint ap =
new TestAccessPointBuilder(mContext)
.setActive(true)
- .setNetworkId(networkId)
+ .setNetworkId(NETWORK_ID)
.setSsid(TEST_SSID)
.setScanResults(scanResults)
.setWifiInfo(info)
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index ca965f3..7fb4dc5 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -721,7 +721,7 @@
// mStaleAccessPoints is true
verify(mockWifiListenerExecutor, never()).onAccessPointsChanged();
- assertThat(tracker.getAccessPoints().size()).isEqualTo(1);
+ assertThat(tracker.getAccessPoints()).hasSize(1);
assertThat(tracker.getAccessPoints().get(0).isActive()).isTrue();
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
new file mode 100644
index 0000000..9b491c2
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.notification;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyObject;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.AlertDialog;
+import android.app.Fragment;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.ContentResolver;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.provider.Settings;
+import android.service.notification.Condition;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class ZenDurationDialogTest {
+ private ZenDurationDialog mController;
+
+ private Context mContext;
+ private LayoutInflater mLayoutInflater;
+ private Condition mCountdownCondition;
+ private Condition mAlarmCondition;
+ private ContentResolver mContentResolver;
+
+ @Before
+ public void setup() {
+ mContext = RuntimeEnvironment.application;
+ mContentResolver = RuntimeEnvironment.application.getContentResolver();
+ mLayoutInflater = LayoutInflater.from(mContext);
+
+ mController = spy(new ZenDurationDialog(mContext));
+ mController.mLayoutInflater = mLayoutInflater;
+ mController.getContentView();
+ }
+
+ @Test
+ public void testAlwaysPrompt() {
+ Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION,
+ Settings.Global.ZEN_DURATION_PROMPT);
+ mController.createDialog();
+
+ assertFalse(mController.getConditionTagAt(ZenDurationDialog.FOREVER_CONDITION_INDEX).rb
+ .isChecked());
+ assertFalse(mController.getConditionTagAt(ZenDurationDialog.COUNTDOWN_CONDITION_INDEX).rb
+ .isChecked());
+ assertTrue(mController.getConditionTagAt(
+ ZenDurationDialog.ALWAYS_ASK_CONDITION_INDEX).rb.isChecked());
+ }
+
+ @Test
+ public void testForever() {
+ Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION,
+ Settings.Global.ZEN_DURATION_FOREVER);
+ mController.createDialog();
+
+ assertTrue(mController.getConditionTagAt(ZenDurationDialog.FOREVER_CONDITION_INDEX).rb
+ .isChecked());
+ assertFalse(mController.getConditionTagAt(ZenDurationDialog.COUNTDOWN_CONDITION_INDEX).rb
+ .isChecked());
+ assertFalse(mController.getConditionTagAt(
+ ZenDurationDialog.ALWAYS_ASK_CONDITION_INDEX).rb.isChecked());
+ }
+
+ @Test
+ public void testSpecificDuration() {
+ Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION, 45);
+ mController.createDialog();
+
+ assertFalse(mController.getConditionTagAt(ZenDurationDialog.FOREVER_CONDITION_INDEX).rb
+ .isChecked());
+ assertTrue(mController.getConditionTagAt(ZenDurationDialog.COUNTDOWN_CONDITION_INDEX).rb
+ .isChecked());
+ assertFalse(mController.getConditionTagAt(
+ ZenDurationDialog.ALWAYS_ASK_CONDITION_INDEX).rb.isChecked());
+ }
+
+
+ @Test
+ public void testChooseAlwaysPromptSetting() {
+ Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION,
+ Settings.Global.ZEN_DURATION_FOREVER);
+
+ AlertDialog dialog = (AlertDialog) mController.createDialog();
+ mController.getConditionTagAt(ZenDurationDialog.ALWAYS_ASK_CONDITION_INDEX).rb.setChecked(
+ true);
+ mController.updateZenDuration(Settings.Global.ZEN_DURATION_FOREVER);
+
+ assertEquals(Settings.Global.ZEN_DURATION_PROMPT, Settings.Global.getInt(mContentResolver,
+ Settings.Global.ZEN_DURATION, Settings.Global.ZEN_DURATION_FOREVER));
+ }
+
+ @Test
+ public void testChooseForeverSetting() {
+ Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION,
+ Settings.Global.ZEN_DURATION_PROMPT);
+
+ AlertDialog dialog = (AlertDialog) mController.createDialog();
+ mController.getConditionTagAt(ZenDurationDialog.FOREVER_CONDITION_INDEX).rb.setChecked(
+ true);
+ mController.updateZenDuration(Settings.Global.ZEN_DURATION_PROMPT);
+
+ assertEquals(Settings.Global.ZEN_DURATION_FOREVER, Settings.Global.getInt(mContentResolver,
+ Settings.Global.ZEN_DURATION, Settings.Global.ZEN_DURATION_PROMPT));
+ }
+
+ @Test
+ public void testChooseTimeSetting() {
+ Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION,
+ Settings.Global.ZEN_DURATION_PROMPT);
+
+ AlertDialog dialog = (AlertDialog) mController.createDialog();
+ mController.getConditionTagAt(ZenDurationDialog.COUNTDOWN_CONDITION_INDEX).rb.setChecked(
+ true);
+ mController.updateZenDuration(Settings.Global.ZEN_DURATION_PROMPT);
+
+ // countdown defaults to 60 minutes:
+ assertEquals(60, Settings.Global.getInt(mContentResolver,
+ Settings.Global.ZEN_DURATION, Settings.Global.ZEN_DURATION_PROMPT));
+ }
+
+ @Test
+ public void testGetTimeFromBucket() {
+ Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION,
+ Settings.Global.ZEN_DURATION_PROMPT);
+
+ AlertDialog dialog = (AlertDialog) mController.createDialog();
+ // click time button starts at 60 minutes
+ // - 1 hour to MAX_BUCKET_MINUTES (12 hours), increments by 1 hour
+ // - 0-60 minutes increments by 15 minutes
+ View view = mController.mZenRadioGroupContent.getChildAt(
+ ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+ ZenDurationDialog.ConditionTag tag = mController.getConditionTagAt(
+ ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+
+ // test incrementing up:
+ mController.onClickTimeButton(view, tag, true, ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+ assertEquals(120, tag.countdownZenDuration); // goes from 1 hour to 2 hours
+
+ // try clicking up 50 times - should max out at ZenDurationDialog.MAX_BUCKET_MINUTES
+ for (int i = 0; i < 50; i++) {
+ mController.onClickTimeButton(view, tag, true,
+ ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+ }
+ assertEquals(ZenDurationDialog.MAX_BUCKET_MINUTES, tag.countdownZenDuration);
+
+ // reset, test incrementing down:
+ mController.mBucketIndex = -1; // reset current bucket index to reset countdownZenDuration
+ tag.countdownZenDuration = 60; // back to default
+ mController.onClickTimeButton(view, tag, false,
+ ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+ assertEquals(45, tag.countdownZenDuration); // goes from 60 minutes to 45 minutes
+
+ // try clicking down 50 times - should stop at MIN_BUCKET_MINUTES
+ for (int i = 0; i < 50; i++) {
+ mController.onClickTimeButton(view, tag, false,
+ ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+ }
+ assertEquals(ZenDurationDialog.MIN_BUCKET_MINUTES, tag.countdownZenDuration);
+
+ // reset countdownZenDuration to unbucketed number, should round change to nearest bucket
+ mController.mBucketIndex = -1;
+ tag.countdownZenDuration = 50;
+ mController.onClickTimeButton(view, tag, false,
+ ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+ assertEquals(45, tag.countdownZenDuration);
+
+ mController.mBucketIndex = -1;
+ tag.countdownZenDuration = 50;
+ mController.onClickTimeButton(view, tag, true,
+ ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+ assertEquals(60, tag.countdownZenDuration);
+
+ mController.mBucketIndex = -1;
+ tag.countdownZenDuration = 75;
+ mController.onClickTimeButton(view, tag, false,
+ ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+ assertEquals(60, tag.countdownZenDuration);
+
+ mController.mBucketIndex = -1;
+ tag.countdownZenDuration = 75;
+ mController.onClickTimeButton(view, tag, true,
+ ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+ assertEquals(120, tag.countdownZenDuration);
+ }
+}
\ No newline at end of file
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index c173225..1cd02f4 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -200,4 +200,11 @@
<!-- Default for Settings.Secure.BACKUP_LOCAL_TRANSPORT_PARAMETERS -->
<string name="def_backup_local_transport_parameters"></string>
+
+ <!-- Default for Settings.Global.ZEN_DURATION
+ If 0, turning on dnd manually will last indefinitely.
+ Else if non-negative, turning on dnd manually will last for this many minutes.
+ Else (if negative), turning on dnd manually will surface a dialog that prompts
+ user to specify a duration.-->
+ <integer name="def_zen_duration">0</integer>
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 11c869f..ccb4d8c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1141,6 +1141,9 @@
dumpSetting(s, p,
Settings.Global.APP_AUTO_RESTRICTION_ENABLED,
GlobalSettingsProto.APP_AUTO_RESTRICTION_ENABLED);
+ dumpSetting(s, p,
+ Settings.Global.ZEN_DURATION,
+ GlobalSettingsProto.ZEN_DURATION);
// Please insert new settings using the same order as in Settings.Global.
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index baf17cb..6398858 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2938,7 +2938,7 @@
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 156;
+ private static final int SETTINGS_VERSION = 157;
private final int mUserId;
@@ -3604,7 +3604,21 @@
currentVersion = 156;
}
+ if (currentVersion == 156) {
+ // Version 156: Set a default value for zen duration
+ final SettingsState globalSettings = getGlobalSettingsLocked();
+ final Setting currentSetting = globalSettings.getSettingLocked(
+ Global.ZEN_DURATION);
+ if (currentSetting.isNull()) {
+ String defaultZenDuration = Integer.toString(getContext()
+ .getResources().getInteger(R.integer.def_zen_duration));
+ globalSettings.insertSettingLocked(
+ Global.ZEN_DURATION, defaultZenDuration,
+ null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+ currentVersion = 157;
+ }
// vXXX: Add new settings above this point.
if (currentVersion != newVersion) {
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 937b939..589ae2a 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -118,6 +118,7 @@
<uses-permission android:name="android.permission.REGISTER_CONNECTION_MANAGER" />
<uses-permission android:name="android.permission.REGISTER_SIM_SUBSCRIPTION" />
<uses-permission android:name="android.permission.GET_APP_OPS_STATS" />
+ <uses-permission android:name="android.permission.MANAGE_APP_OPS_MODES" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
<uses-permission android:name="android.permission.ACTIVITY_EMBEDDING" />
diff --git a/packages/StatementService/src/com/android/statementservice/DirectStatementService.java b/packages/StatementService/src/com/android/statementservice/DirectStatementService.java
index 449738e..659696e 100644
--- a/packages/StatementService/src/com/android/statementservice/DirectStatementService.java
+++ b/packages/StatementService/src/com/android/statementservice/DirectStatementService.java
@@ -155,17 +155,20 @@
@Override
public void onDestroy() {
super.onDestroy();
- if (mThread != null) {
- mThread.quit();
- }
-
- try {
- if (mHttpResponseCache != null) {
- mHttpResponseCache.delete();
+ final HttpResponseCache responseCache = mHttpResponseCache;
+ mHandler.post(new Runnable() {
+ public void run() {
+ try {
+ if (responseCache != null) {
+ responseCache.delete();
+ }
+ } catch (IOException e) {
+ Log.i(TAG, "HTTP(S) response cache deletion failed:" + e);
+ }
+ Looper.myLooper().quit();
}
- } catch (IOException e) {
- Log.i(TAG, "HTTP(S) response cache deletion failed:" + e);
- }
+ });
+ mHttpResponseCache = null;
}
@Override
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
index 6131acc..aa2fb32 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
@@ -16,6 +16,7 @@
import android.graphics.Canvas;
import android.view.MotionEvent;
+import android.view.View;
import com.android.systemui.plugins.Plugin;
import com.android.systemui.plugins.annotations.ProvidesInterface;
@@ -42,6 +43,8 @@
public void onLayout(boolean changed, int left, int top, int right, int bottom);
+ public void onNavigationButtonLongPress(View v);
+
public default void destroy() { }
}
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
index 828c9df..611aa43 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
@@ -22,7 +22,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:clipToPadding="false"
@@ -37,7 +37,8 @@
android:textColor="?attr/wallpaperTextColor"
android:theme="@style/TextAppearance.Keyguard"
/>
- <LinearLayout android:id="@+id/row"
+ <view class="com.android.keyguard.KeyguardSliceView$Row"
+ android:id="@+id/row"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
diff --git a/packages/SystemUI/res/anim/ic_qs_signal_blink_1.xml b/packages/SystemUI/res/anim/ic_qs_signal_blink_1.xml
deleted file mode 100644
index 57b61da..0000000
--- a/packages/SystemUI/res/anim/ic_qs_signal_blink_1.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<!--
- Copyright (C) 2015 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.
--->
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@android:anim/linear_interpolator"
- android:duration="@integer/carrier_network_change_anim_time"
- android:repeatCount="-1">
-
- <propertyValuesHolder
- android:propertyName="fillColor"
- android:valueType="colorType">
- <keyframe
- android:fraction="0.0"
- android:value="#FFFFFFFF"/>
- <keyframe
- android:fraction="0.32"
- android:value="#FFFFFFFF"/>
- <keyframe
- android:fraction="0.33"
- android:value="#4DFFFFFF"/>
- <keyframe
- android:fraction="1.0"
- android:value="#4DFFFFFF"/>
- </propertyValuesHolder>
-
-</objectAnimator>
diff --git a/packages/SystemUI/res/anim/ic_qs_signal_blink_2.xml b/packages/SystemUI/res/anim/ic_qs_signal_blink_2.xml
deleted file mode 100644
index 09694c3..0000000
--- a/packages/SystemUI/res/anim/ic_qs_signal_blink_2.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<!--
- Copyright (C) 2015 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.
--->
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@android:anim/linear_interpolator"
- android:duration="@integer/carrier_network_change_anim_time"
- android:repeatCount="-1">
-
- <propertyValuesHolder
- android:propertyName="fillColor"
- android:valueType="colorType">
- <keyframe
- android:fraction="0.0"
- android:value="#4DFFFFFF"/>
- <keyframe
- android:fraction="0.32"
- android:value="#4DFFFFFF"/>
- <keyframe
- android:fraction="0.33"
- android:value="#FFFFFFFF"/>
- <keyframe
- android:fraction="0.66"
- android:value="#FFFFFFFF"/>
- <keyframe
- android:fraction="0.67"
- android:value="#4DFFFFFF"/>
- <keyframe
- android:fraction="1.0"
- android:value="#4DFFFFFF"/>
- </propertyValuesHolder>
-
-</objectAnimator>
diff --git a/packages/SystemUI/res/anim/ic_qs_signal_blink_3.xml b/packages/SystemUI/res/anim/ic_qs_signal_blink_3.xml
deleted file mode 100644
index 2270e3f..0000000
--- a/packages/SystemUI/res/anim/ic_qs_signal_blink_3.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<!--
- Copyright (C) 2015 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.
--->
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@android:anim/linear_interpolator"
- android:duration="@integer/carrier_network_change_anim_time"
- android:repeatCount="-1">
-
- <propertyValuesHolder
- android:propertyName="fillColor"
- android:valueType="colorType">
- <keyframe
- android:fraction="0.0"
- android:value="#4DFFFFFF"/>
- <keyframe
- android:fraction="0.66"
- android:value="#4DFFFFFF"/>
- <keyframe
- android:fraction="0.67"
- android:value="#FFFFFFFF"/>
- <keyframe
- android:fraction="1.0"
- android:value="#FFFFFFFF"/>
- </propertyValuesHolder>
-
-</objectAnimator>
diff --git a/packages/SystemUI/res/drawable/fingerprint_dialog_bg.xml b/packages/SystemUI/res/drawable/fingerprint_dialog_bg.xml
new file mode 100644
index 0000000..221f170
--- /dev/null
+++ b/packages/SystemUI/res/drawable/fingerprint_dialog_bg.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2018 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
+ -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/fingerprint_dialog_bg_color" />
+ <corners android:radius="1dp"
+ android:topLeftRadius="@dimen/fingerprint_dialog_corner_size"
+ android:topRightRadius="@dimen/fingerprint_dialog_corner_size"
+ android:bottomLeftRadius="0dp"
+ android:bottomRightRadius="0dp"/>
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_1x_mobiledata.xml b/packages/SystemUI/res/drawable/ic_1x_mobiledata.xml
new file mode 100644
index 0000000..382d9d5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_1x_mobiledata.xml
@@ -0,0 +1,29 @@
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M4,7h4v10H6V9H4V7z M15.83,11.72L18.66,7h-2.33l-1.66,2.77L13,7h-2.33l2.83,4.72L10.33,17h2.33l2-3.34l2,3.34H19 L15.83,11.72z" />
+ <path
+ android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
+ <path
+ android:pathData="M0,0h24v24H0V0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_3g_mobiledata.xml b/packages/SystemUI/res/drawable/ic_3g_mobiledata.xml
new file mode 100644
index 0000000..ce003e4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_3g_mobiledata.xml
@@ -0,0 +1,29 @@
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
+ <path
+ android:pathData="M0,0h24v24H0V0z" />
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M3,7v2h5v2H4v2h4v2H3v2h5c1.1,0,2-0.9,2-2v-1.5c0-0.83-0.67-1.5-1.5-1.5c0.83,0,1.5-0.67,1.5-1.5V9c0-1.1-0.9-2-2-2H3z M21,11v4c0,1.1-0.9,2-2,2h-5c-1.1,0-2-0.9-2-2V9c0-1.1,0.9-2,2-2h5c1.1,0,2,0.9,2,2h-2h-5v6h5v-2h-2.5v-2H21z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_4g_mobiledata.xml b/packages/SystemUI/res/drawable/ic_4g_mobiledata.xml
new file mode 100644
index 0000000..8e22e06
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_4g_mobiledata.xml
@@ -0,0 +1,29 @@
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M9,7H7v5H5V7H3v7h4v3h2v-3h2v-2H9V7z M17,11v2h2v2h-5V9h7c0-1.1-0.9-2-2-2h-5c-1.1,0-2,0.9-2,2v6c0,1.1,0.9,2,2,2h5 c1.1,0,2-0.9,2-2v-4H17z" />
+ <path
+ android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
+ <path
+ android:pathData="M0,0h24v24H0V0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_4g_plus_mobiledata.xml b/packages/SystemUI/res/drawable/ic_4g_plus_mobiledata.xml
new file mode 100644
index 0000000..32add0c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_4g_plus_mobiledata.xml
@@ -0,0 +1,29 @@
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
+ <path
+ android:pathData="M0,0h24v24H0V0z" />
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M13,11v2h2v2h-4V9h6c0-1.1-0.9-2-2-2h-4C9.9,7,9,7.9,9,9v6c0,1.1,0.9,2,2,2h4c1.1,0,2-0.9,2-2v-4H13z M24,11h-2V9h-2v2h-2v2 h2v2h2v-2h2V11z M7,7H5v5H3V7H1v7h4v3h2v-3h1v-2H7V7z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_e_mobiledata.xml b/packages/SystemUI/res/drawable/ic_e_mobiledata.xml
new file mode 100644
index 0000000..80e507b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_e_mobiledata.xml
@@ -0,0 +1,29 @@
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M 16 9 L 16 7 L 8 7 L 8 17 L 16 17 L 16 15 L 10 15 L 10 13 L 16 13 L 16 11 L 10 11 L 10 9 Z" />
+ <path
+ android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
+ <path
+ android:pathData="M0,0h24v24H0V0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_g_mobiledata.xml b/packages/SystemUI/res/drawable/ic_g_mobiledata.xml
new file mode 100644
index 0000000..04049ce
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_g_mobiledata.xml
@@ -0,0 +1,29 @@
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
+ <path
+ android:pathData="M0,0h24v24H0V0z" />
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12,11v2h2v2H9V9h0.44H14h2c0-1.1-0.9-2-2-2H9C7.9,7,7,7.9,7,9v6c0,1.1,0.9,2,2,2h5c1.1,0,2-0.9,2-2v-4H12z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_h_mobiledata.xml b/packages/SystemUI/res/drawable/ic_h_mobiledata.xml
new file mode 100644
index 0000000..31cc4a7
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_h_mobiledata.xml
@@ -0,0 +1,29 @@
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M15,11H9V7H7v10h2v-4h6v4h2V7h-2V11z" />
+ <path
+ android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
+ <path
+ android:pathData="M0,0h24v24H0V0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_h_plus_mobiledata.xml b/packages/SystemUI/res/drawable/ic_h_plus_mobiledata.xml
new file mode 100644
index 0000000..ca1020e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_h_plus_mobiledata.xml
@@ -0,0 +1,32 @@
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
+ <path
+ android:pathData="M0,0h24v24H0V0z" />
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12,11H6V7H4v10h2v-4h6v4h2V7h-2V11z" />
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M22,11h-2V9h-2v2h-2v2h2v2h2v-2h2V11z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_lte_mobiledata.xml b/packages/SystemUI/res/drawable/ic_lte_mobiledata.xml
new file mode 100644
index 0000000..5d90965
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_lte_mobiledata.xml
@@ -0,0 +1,29 @@
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M6,14h3v2H4V8h2V14z M9,10h2v6h2v-6h2V8H9V10z M21,10V8h-5v8h2h3v-2h-3v-0.67V13h3v-2h-3v-1H21z" />
+ <path
+ android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
+ <path
+ android:pathData="M0,0h24v24H0V0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_lte_plus_mobiledata.xml b/packages/SystemUI/res/drawable/ic_lte_plus_mobiledata.xml
new file mode 100644
index 0000000..0366e24
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_lte_plus_mobiledata.xml
@@ -0,0 +1,29 @@
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M3,14h3v2H1V8h2V14z M5,10h2v6h2v-6h2V8H5V10z M12,16h5v-2h-3v-1h3v-2h-3v-1h3V8h-5V16z M24,11h-2V9h-2v2h-2v2h2v2h2v-2h2 V11z" />
+ <path
+ android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
+ <path
+ android:pathData="M0,0h24v24H0V0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_0.xml b/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
deleted file mode 100644
index b78d3bf..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:autoMirrored="true"
- android:width="32.0dp"
- android:height="32.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
- android:fillAlpha="0.3"
- android:fillColor="#FFFFFF"/>
- <path
- android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
- android:fillColor="#FFFFFF"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml b/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml
deleted file mode 100644
index 5217748..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="12.0dp"
- android:height="24dp"
- android:viewportWidth="12.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M3.500000,11.000000L1.800000,11.000000L1.800000,4.400000L0.200000,5.100000L0.200000,3.700000l3.100000,-1.300000l0.200000,0.000000L3.500000,11.000000z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M8.600000,5.500000l1.200000,-3.000000l1.900000,0.000000L9.700000,6.700000l2.200000,4.300000L9.900000,11.000000L8.700000,7.900000L7.400000,11.000000L5.500000,11.000000l2.100000,-4.300000L5.600000,2.500000l1.900000,0.000000L8.600000,5.500000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml
deleted file mode 100644
index 546a96f..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="15dp"
- android:height="24dp"
- android:viewportWidth="15.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M2.000000,6.000000l0.800000,0.000000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000s0.200000,-0.500000 0.200000,-0.900000c0.000000,-0.300000 -0.100000,-0.600000 -0.200000,-0.800000S3.200000,3.700000 2.900000,3.700000C2.700000,3.700000 2.500000,3.800000 2.300000,4.000000S2.100000,4.400000 2.100000,4.700000L0.500000,4.700000C0.500000,4.000000 0.700000,3.400000 1.100000,3.000000s1.000000,-0.600000 1.700000,-0.600000c0.800000,0.000000 1.400000,0.200000 1.900000,0.600000s0.700000,1.000000 0.700000,1.800000c0.000000,0.400000 -0.100000,0.700000 -0.300000,1.100000S4.600000,6.500000 4.300000,6.600000C4.700000,6.800000 5.000000,7.100000 5.200000,7.400000s0.300000,0.700000 0.300000,1.200000c0.000000,0.800000 -0.200000,1.400000 -0.700000,1.800000s-1.100000,0.700000 -1.900000,0.700000c-0.700000,0.000000 -1.300000,-0.200000 -1.800000,-0.600000s-0.700000,-1.000000 -0.700000,-1.800000L2.000000,8.700000C2.000000,9.000000 2.100000,9.300000 2.300000,9.500000s0.400000,0.300000 0.600000,0.300000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000S3.900000,9.000000 3.900000,8.600000c0.000000,-0.500000 -0.100000,-0.800000 -0.300000,-1.000000S3.200000,7.300000 2.800000,7.300000L2.000000,7.300000L2.000000,6.000000z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M12.500000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S6.700000,9.000000 6.700000,7.900000L6.700000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000s1.200000,-0.800000 2.100000,-0.800000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000l-1.600000,0.000000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000s-0.500000,-0.300000 -0.900000,-0.300000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S8.400000,5.000000 8.400000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L10.799999,7.800000L9.600000,7.800000L9.600000,6.600000l2.900000,0.000000L12.500000,9.900000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml
deleted file mode 100644
index 26b68c7..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="12.0dp"
- android:height="24dp"
- android:viewportWidth="12.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M4.600000,7.800000l0.700000,0.000000l0.000000,1.300000L4.600000,9.100000L4.600000,11.000000L3.000000,11.000000L3.000000,9.200000L0.100000,9.200000L0.000000,8.100000L3.000000,2.500000l1.700000,0.000000L4.700000,7.800000zM1.600000,7.800000L3.000000,7.800000l0.000000,-3.000000L2.900000,5.000000L1.600000,7.800000z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M11.900000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S6.100000,9.000000 6.100000,7.900000L6.100000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000S8.100000,2.400000 9.000000,2.400000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000l-1.600000,0.000000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000S9.500000,3.700000 9.000000,3.700000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S7.700000,5.000000 7.700000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L10.099999,7.800000L9.000000,7.800000L9.000000,6.600000l2.900000,0.000000L11.900000,9.900000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
deleted file mode 100644
index 6e4b4c5..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="15.0dp"
- android:height="20.0dp"
- android:viewportWidth="18.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M4.6,7.8l0.7,0.0l0.0,1.3L4.6,9.1L4.6,11.0L3.0,11.0L3.0,9.2L0.1,9.2L0.0,8.2l3.0,-5.7l1.7,0.0L4.6,7.8L4.6,7.8zM1.7,7.8L3.0,7.8l0.0,-3.0L2.9,5.0L1.7,7.8z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M11.9,9.9c-0.2,0.4 -0.6,0.7 -1.0,0.9s-1.0,0.4 -1.8,0.4c-0.9,0.0 -1.7,-0.3 -2.2,-0.8S6.1,9.0 6.1,7.9L6.1,5.6c0.0,-1.1 0.3,-1.9 0.8,-2.4S8.2,2.4 9.0,2.4c1.0,0.0 1.7,0.2 2.1,0.7s0.7,1.2 0.7,2.1l-1.6,0.0c0.0,-0.5 -0.1,-0.9 -0.2,-1.1S9.5,3.7 9.0,3.7c-0.4,0.0 -0.7,0.2 -0.9,0.5S7.8,5.0 7.8,5.6l0.0,2.3c0.0,0.7 0.1,1.1 0.3,1.4c0.2,0.3 0.6,0.5 1.0,0.5c0.3,0.0 0.6,0.0 0.7,-0.1s0.3,-0.2 0.4,-0.3L10.2,7.8L9.0,7.8L9.0,6.6l2.9,0.0L11.9,9.9z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M17.7,4.4l-1.900001,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.900001,0.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml
deleted file mode 100644
index c841a66..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:autoMirrored="true"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M21.799999,22.299999l-1.199999,-1.299999 0.000000,0.000000 -9.600000,-10.000000 0.000000,0.000000 -6.400000,-6.700000 -1.300000,1.300000 6.400000,6.700000 -8.700000,8.700000 16.900000,0.000000 2.600000,2.700001z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M21.000000,1.000000l-8.600000,8.600000 8.600000,9.100000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_e.xml b/packages/SystemUI/res/drawable/ic_qs_signal_e.xml
deleted file mode 100644
index f4b6ed8..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_e.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="12dp"
- android:height="24dp"
- android:viewportWidth="12.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal">
- <group
- android:translateX="3.5" >
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M4.400000,7.300000L1.700000,7.300000l0.000000,2.400000l3.300000,0.000000L5.000000,11.000000L0.000000,11.000000L0.000000,2.500000l4.900000,0.000000l0.000000,1.300000L1.700000,3.800000l0.000000,2.100000l2.800000,0.000000L4.500000,7.300000z"/>
- </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_g.xml
deleted file mode 100644
index 60a7f1e9..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_g.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="12dp"
- android:height="24dp"
- android:viewportWidth="12.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal">
- <group android:translateX="3.5" >
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M6.500000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S0.700000,9.000000 0.700000,7.900000L0.700000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000s1.200000,-0.800000 2.100000,-0.800000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000L4.700000,5.200000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000S4.000000,3.700000 3.600000,3.700000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S2.300000,5.000000 2.300000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L4.700000,7.800000L3.500000,7.800000L3.500000,6.600000l2.900000,0.000000L6.400000,9.900000z"/>
- </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_h.xml b/packages/SystemUI/res/drawable/ic_qs_signal_h.xml
deleted file mode 100644
index 4ffb4be..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_h.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="12dp"
- android:height="24dp"
- android:viewportWidth="12.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal">
- <group
- android:translateX="3.5" >
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M6.000000,11.000000L4.400000,11.000000L4.400000,7.500000L1.700000,7.500000L1.700000,11.000000L0.000000,11.000000L0.000000,2.500000l1.700000,0.000000l0.000000,3.700000l2.700000,0.000000L4.400000,2.500000L6.000000,2.500000L6.000000,11.000000z"/>
- </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml b/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml
deleted file mode 100644
index 816cd32..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="11.9dp"
- android:height="22dp"
- android:viewportWidth="13.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M2.000000,9.700000l2.000000,0.000000L4.000000,11.000000L0.300000,11.000000L0.300000,2.500000L2.000000,2.500000L2.000000,9.700000z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M8.300000,3.800000L7.000000,3.800000L7.000000,11.000000L5.300000,11.000000L5.300000,3.800000L4.000000,3.800000L4.000000,2.500000l4.300000,0.000000L8.300000,3.800000z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M12.400000,7.300000l-1.700000,0.000000l0.000000,2.400000l2.100000,0.000000L12.799999,11.000000L9.000000,11.000000L9.000000,2.500000l3.700000,0.000000l0.000000,1.300000l-2.100000,0.000000l0.000000,2.100000l1.700000,0.000000L12.300000,7.300000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml
deleted file mode 100644
index 4c43e13..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="15.0dp"
- android:height="19.5dp"
- android:viewportWidth="18.5"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M2.0,9.7l2.0,0.0L4.0,11.0L0.4,11.0L0.4,2.5L2.0,2.5L2.0,9.7z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M8.3,3.8L7.0,3.8L7.0,11.0L5.4,11.0L5.4,3.8L4.0,3.8L4.0,2.5l4.3,0.0L8.3,3.8z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M12.4,7.3l-1.7,0.0l0.0,2.4l2.1,0.0L12.799999,11.0L9.0,11.0L9.0,2.5l3.7,0.0l0.0,1.3l-2.1,0.0l0.0,2.1l1.7,0.0L12.4,7.3L12.4,7.3z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M18.4,4.4l-1.9,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.9,0.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_no_signal.xml b/packages/SystemUI/res/drawable/ic_qs_signal_no_signal.xml
deleted file mode 100644
index c8c857c..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_no_signal.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:autoMirrored="true"
- android:width="32dp"
- android:height="32dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M2.000000,22.000000l20.000000,0.000000L22.000000,2.000000L2.000000,22.000000zM20.000000,20.000000L6.800000,20.000000L20.000000,6.800000L20.000000,20.000000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_swap_vert.xml b/packages/SystemUI/res/drawable/ic_swap_vert.xml
new file mode 100644
index 0000000..eed79ff
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_swap_vert.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M16 17.01V10h-2v7.01h-3L15 21l4-3.99h-3zM9 3L5 6.99h3V14h2V6.99h3L9 3z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/rounded_bg_bottom_background.xml b/packages/SystemUI/res/drawable/rounded_bg_bottom_background.xml
index 8d03ce7..622226f 100644
--- a/packages/SystemUI/res/drawable/rounded_bg_bottom_background.xml
+++ b/packages/SystemUI/res/drawable/rounded_bg_bottom_background.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
- <solid android:color="@*android:color/material_grey_200" />
+ <solid android:color="?android:attr/panelColorBackground" />
<corners
android:bottomLeftRadius="@dimen/corner_size"
android:topLeftRadius="0dp"
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_1x.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_1x.xml
deleted file mode 100644
index d7463a4..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_1x.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="8.5dp"
- android:height="17dp"
- android:viewportWidth="12.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M3.500000,11.000000L1.800000,11.000000L1.800000,4.400000L0.200000,5.100000L0.200000,3.700000l3.100000,-1.300000l0.200000,0.000000L3.500000,11.000000z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M8.600000,5.500000l1.200000,-3.000000l1.900000,0.000000L9.700000,6.700000l2.200000,4.300000L9.900000,11.000000L8.700000,7.900000L7.400000,11.000000L5.500000,11.000000l2.100000,-4.300000L5.600000,2.500000l1.900000,0.000000L8.600000,5.500000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_3g.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_3g.xml
deleted file mode 100644
index 6309b6d..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_3g.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="9.208dp"
- android:height="17dp"
- android:viewportWidth="13.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M2.000000,6.000000l0.800000,0.000000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000s0.200000,-0.500000 0.200000,-0.900000c0.000000,-0.300000 -0.100000,-0.600000 -0.200000,-0.800000S3.200000,3.700000 2.900000,3.700000C2.700000,3.700000 2.500000,3.800000 2.300000,4.000000S2.100000,4.400000 2.100000,4.700000L0.500000,4.700000C0.500000,4.000000 0.700000,3.400000 1.100000,3.000000s1.000000,-0.600000 1.700000,-0.600000c0.800000,0.000000 1.400000,0.200000 1.900000,0.600000s0.700000,1.000000 0.700000,1.800000c0.000000,0.400000 -0.100000,0.700000 -0.300000,1.100000S4.600000,6.500000 4.300000,6.600000C4.700000,6.800000 5.000000,7.100000 5.200000,7.400000s0.300000,0.700000 0.300000,1.200000c0.000000,0.800000 -0.200000,1.400000 -0.700000,1.800000s-1.100000,0.700000 -1.900000,0.700000c-0.700000,0.000000 -1.300000,-0.200000 -1.800000,-0.600000s-0.700000,-1.000000 -0.700000,-1.800000L2.000000,8.700000C2.000000,9.000000 2.100000,9.300000 2.300000,9.500000s0.400000,0.300000 0.600000,0.300000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000S3.900000,9.000000 3.900000,8.600000c0.000000,-0.500000 -0.100000,-0.800000 -0.300000,-1.000000S3.200000,7.300000 2.800000,7.300000L2.000000,7.300000L2.000000,6.000000z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M12.500000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S6.700000,9.000000 6.700000,7.900000L6.700000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000s1.200000,-0.800000 2.100000,-0.800000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000l-1.600000,0.000000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000s-0.500000,-0.300000 -0.900000,-0.300000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S8.400000,5.000000 8.400000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L10.799999,7.800000L9.600000,7.800000L9.600000,6.600000l2.900000,0.000000L12.500000,9.900000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g.xml
deleted file mode 100644
index 4067ae5..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="8.5dp"
- android:height="17dp"
- android:viewportWidth="12.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M4.600000,7.800000l0.700000,0.000000l0.000000,1.300000L4.600000,9.100000L4.600000,11.000000L3.000000,11.000000L3.000000,9.200000L0.100000,9.200000L0.000000,8.100000L3.000000,2.500000l1.700000,0.000000L4.700000,7.800000zM1.600000,7.800000L3.000000,7.800000l0.000000,-3.000000L2.900000,5.000000L1.600000,7.800000z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M11.900000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S6.100000,9.000000 6.100000,7.900000L6.100000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000S8.100000,2.400000 9.000000,2.400000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000l-1.600000,0.000000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000S9.500000,3.700000 9.000000,3.700000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S7.700000,5.000000 7.700000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L10.099999,7.800000L9.000000,7.800000L9.000000,6.600000l2.900000,0.000000L11.900000,9.900000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml
deleted file mode 100644
index 719a6ca..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="10.5dp"
- android:height="14.0dp"
- android:viewportWidth="18.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M4.6,7.8l0.7,0.0l0.0,1.3L4.6,9.1L4.6,11.0L3.0,11.0L3.0,9.2L0.1,9.2L0.0,8.2l3.0,-5.7l1.7,0.0L4.6,7.8L4.6,7.8zM1.7,7.8L3.0,7.8l0.0,-3.0L2.9,5.0L1.7,7.8z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M11.9,9.9c-0.2,0.4 -0.6,0.7 -1.0,0.9s-1.0,0.4 -1.8,0.4c-0.9,0.0 -1.7,-0.3 -2.2,-0.8S6.1,9.0 6.1,7.9L6.1,5.6c0.0,-1.1 0.3,-1.9 0.8,-2.4S8.2,2.4 9.0,2.4c1.0,0.0 1.7,0.2 2.1,0.7s0.7,1.2 0.7,2.1l-1.6,0.0c0.0,-0.5 -0.1,-0.9 -0.2,-1.1S9.5,3.7 9.0,3.7c-0.4,0.0 -0.7,0.2 -0.9,0.5S7.8,5.0 7.8,5.6l0.0,2.3c0.0,0.7 0.1,1.1 0.3,1.4c0.2,0.3 0.6,0.5 1.0,0.5c0.3,0.0 0.6,0.0 0.7,-0.1s0.3,-0.2 0.4,-0.3L10.2,7.8L9.0,7.8L9.0,6.6l2.9,0.0L11.9,9.9z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M17.7,4.4l-1.900001,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.900001,0.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_e.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_e.xml
deleted file mode 100644
index acaa9b1..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_e.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="3.541dp"
- android:height="17dp"
- android:viewportWidth="5.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M4.400000,7.300000L1.700000,7.300000l0.000000,2.400000l3.300000,0.000000L5.000000,11.000000L0.000000,11.000000L0.000000,2.500000l4.900000,0.000000l0.000000,1.300000L1.700000,3.800000l0.000000,2.100000l2.800000,0.000000L4.500000,7.300000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_g.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_g.xml
deleted file mode 100644
index 7985237..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_g.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="4.958dp"
- android:height="17dp"
- android:viewportWidth="7.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M6.500000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S0.700000,9.000000 0.700000,7.900000L0.700000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000s1.200000,-0.800000 2.100000,-0.800000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000L4.700000,5.200000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000S4.000000,3.700000 3.600000,3.700000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S2.300000,5.000000 2.300000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L4.700000,7.800000L3.500000,7.800000L3.500000,6.600000l2.900000,0.000000L6.400000,9.900000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_h.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_h.xml
deleted file mode 100644
index fda8761..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_h.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="4.25dp"
- android:height="17dp"
- android:viewportWidth="6.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M6.000000,11.000000L4.400000,11.000000L4.400000,7.500000L1.700000,7.500000L1.700000,11.000000L0.000000,11.000000L0.000000,2.500000l1.700000,0.000000l0.000000,3.700000l2.700000,0.000000L4.400000,2.500000L6.000000,2.500000L6.000000,11.000000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte.xml
deleted file mode 100644
index c08ff20..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="9.208dp"
- android:height="17dp"
- android:viewportWidth="13.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M2.000000,9.700000l2.000000,0.000000L4.000000,11.000000L0.300000,11.000000L0.300000,2.500000L2.000000,2.500000L2.000000,9.700000z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M8.300000,3.800000L7.000000,3.800000L7.000000,11.000000L5.300000,11.000000L5.300000,3.800000L4.000000,3.800000L4.000000,2.500000l4.300000,0.000000L8.300000,3.800000z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M12.400000,7.300000l-1.700000,0.000000l0.000000,2.400000l2.100000,0.000000L12.799999,11.000000L9.000000,11.000000L9.000000,2.500000l3.700000,0.000000l0.000000,1.300000l-2.100000,0.000000l0.000000,2.100000l1.700000,0.000000L12.300000,7.300000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml
deleted file mode 100644
index 62159b3..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="11.08dp"
- android:height="14.0dp"
- android:viewportWidth="19.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M2.0,9.7l2.0,0.0L4.0,11.0L0.4,11.0L0.4,2.5L2.0,2.5L2.0,9.7z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M8.3,3.8L7.0,3.8L7.0,11.0L5.4,11.0L5.4,3.8L4.0,3.8L4.0,2.5l4.3,0.0L8.3,3.8z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M12.4,7.3l-1.7,0.0l0.0,2.4l2.1,0.0L12.799999,11.0L9.0,11.0L9.0,2.5l3.7,0.0l0.0,1.3l-2.1,0.0l0.0,2.1l1.7,0.0L12.4,7.3L12.4,7.3z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M18.4,4.4l-1.9,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.9,0.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
index 478b656..bfabe52 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
@@ -39,23 +39,13 @@
android:theme="@android:style/Theme"
android:layout_alignParentTop="true"/>
- <!-- This progress bar is the countdown timer. -->
- <ProgressBar
- android:id="@+id/countdown_progress"
- android:layout_width="match_parent"
- android:layout_height="@dimen/car_user_switcher_progress_bar_height"
- style="@style/CarUserSwitcher.ProgressBar"
- android:layout_marginTop="@dimen/car_user_switcher_progress_bar_margin_top"
- android:layout_alignParentTop="true"/>
-
<com.android.systemui.statusbar.car.UserGridView
android:id="@+id/user_grid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/car_margin"
android:layout_marginRight="@dimen/car_margin"
- android:layout_marginBottom="@dimen/car_user_grid_margin_bottom"
- android:layout_centerInParent="true" />
+ android:layout_centerInParent="true"/>
<com.android.systemui.statusbar.car.PageIndicator
android:id="@+id/user_switcher_page_indicator"
diff --git a/packages/SystemUI/res/layout/car_qs_panel.xml b/packages/SystemUI/res/layout/car_qs_panel.xml
index 7844cac..447970c 100644
--- a/packages/SystemUI/res/layout/car_qs_panel.xml
+++ b/packages/SystemUI/res/layout/car_qs_panel.xml
@@ -42,7 +42,6 @@
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/car_margin"
android:layout_marginRight="@dimen/car_margin"
- android:layout_marginBottom="@dimen/car_user_grid_margin_bottom"
android:layout_above="@id/user_switcher_page_indicator" />
<com.android.systemui.statusbar.car.PageIndicator
diff --git a/packages/SystemUI/res/layout/data_usage.xml b/packages/SystemUI/res/layout/data_usage.xml
index fdc6f146..0d59369 100644
--- a/packages/SystemUI/res/layout/data_usage.xml
+++ b/packages/SystemUI/res/layout/data_usage.xml
@@ -88,7 +88,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="16dp"
- android:text="@string/accessibility_data_connection_roaming"
+ android:text="@string/data_connection_roaming"
android:textAppearance="@style/TextAppearance.QS.DataUsage.Secondary"
android:visibility="gone" />
diff --git a/packages/SystemUI/res/layout/fingerprint_dialog.xml b/packages/SystemUI/res/layout/fingerprint_dialog.xml
index f02c0ba..1bdaf6e 100644
--- a/packages/SystemUI/res/layout/fingerprint_dialog.xml
+++ b/packages/SystemUI/res/layout/fingerprint_dialog.xml
@@ -26,115 +26,138 @@
<View
android:id="@+id/space"
android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_height="0dp"
android:layout_weight="1" />
<LinearLayout
- android:id="@+id/dialog"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:elevation="2dp"
- android:background="@color/fingerprint_dialog_bg_color">
+ android:layout_height="wrap_content">
- <TextView
- android:id="@+id/title"
- android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginEnd="24dp"
- android:layout_marginStart="24dp"
- android:layout_marginTop="24dp"
- android:gravity="center"
- android:textSize="20sp"
- android:maxLines="1"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:marqueeRepeatLimit="marquee_forever"
- android:textColor="@color/fingerprint_dialog_text_dark_color"/>
-
- <TextView
- android:id="@+id/subtitle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dp"
- android:layout_marginStart="24dp"
- android:layout_marginEnd="24dp"
- android:gravity="center_horizontal"
- android:textSize="14sp"
- android:maxLines="1"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:marqueeRepeatLimit="marquee_forever"
- android:textColor="@color/fingerprint_dialog_text_light_color"/>
-
- <TextView
- android:id="@+id/description"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginEnd="24dp"
- android:layout_marginStart="24dp"
- android:paddingTop="24dp"
- android:textSize="16sp"
- android:maxLines="4"
- android:textColor="@color/fingerprint_dialog_text_dark_color"/>
-
- <ImageView
- android:id="@+id/fingerprint_icon"
- android:layout_width="@dimen/fingerprint_dialog_fp_icon_size"
- android:layout_height="@dimen/fingerprint_dialog_fp_icon_size"
- android:layout_gravity="center_horizontal"
- android:layout_marginTop="32dp"
- android:scaleType="fitXY"
- android:contentDescription="@string/accessibility_fingerprint_dialog_fingerprint_icon" />
-
- <TextView
- android:id="@+id/error"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginEnd="24dp"
- android:layout_marginStart="24dp"
- android:paddingTop="16dp"
- android:paddingBottom="24dp"
- android:textSize="12sp"
- android:gravity="center_horizontal"
- android:accessibilityLiveRegion="polite"
- android:text="@string/fingerprint_dialog_touch_sensor"
- android:contentDescription="@string/accessibility_fingerprint_dialog_help_area"
- android:textColor="@color/fingerprint_dialog_text_light_color"/>
+ <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
+ on horizontal/portrait orientation -->
+ <View
+ android:id="@+id/left_space"
+ android:layout_weight="1"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"/>
<LinearLayout
- android:layout_width="match_parent"
- android:layout_height="72dip"
- android:paddingTop="16dp"
- android:layout_gravity="center_vertical"
- style="?android:attr/buttonBarStyle"
- android:orientation="horizontal"
- android:measureWithLargestChild="true">
- <Space android:id="@+id/leftSpacer"
- android:layout_width="24dp"
- android:layout_height="match_parent"
- android:visibility="visible" />
- <!-- Negative Button -->
- <Button android:id="@+id/button2"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
- android:layout_marginStart="-12dp"
- android:gravity="start|center_vertical"
- android:maxLines="2" />
- <!-- Positive Button -->
- <Button android:id="@+id/button1"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
- android:layout_marginEnd="12dp"
- android:maxLines="2" />
- <Space android:id="@+id/rightSpacer"
- android:layout_width="24dip"
- android:layout_height="match_parent"
- android:visibility="gone" />
+ android:id="@+id/dialog"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:elevation="2dp"
+ android:background="@drawable/fingerprint_dialog_bg">
+
+ <TextView
+ android:id="@+id/title"
+ android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="24dp"
+ android:layout_marginStart="24dp"
+ android:layout_marginTop="24dp"
+ android:gravity="@integer/fingerprint_dialog_text_gravity"
+ android:textSize="20sp"
+ android:maxLines="1"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:marqueeRepeatLimit="marquee_forever"
+ android:textColor="@color/fingerprint_dialog_text_dark_color"/>
+
+ <TextView
+ android:id="@+id/subtitle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_marginStart="24dp"
+ android:layout_marginEnd="24dp"
+ android:gravity="@integer/fingerprint_dialog_text_gravity"
+ android:textSize="16sp"
+ android:maxLines="1"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:marqueeRepeatLimit="marquee_forever"
+ android:textColor="@color/fingerprint_dialog_text_dark_color"/>
+
+ <TextView
+ android:id="@+id/description"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="24dp"
+ android:layout_marginStart="24dp"
+ android:gravity="@integer/fingerprint_dialog_text_gravity"
+ android:paddingTop="8dp"
+ android:textSize="16sp"
+ android:maxLines="4"
+ android:textColor="@color/fingerprint_dialog_text_dark_color"/>
+
+ <ImageView
+ android:id="@+id/fingerprint_icon"
+ android:layout_width="@dimen/fingerprint_dialog_fp_icon_size"
+ android:layout_height="@dimen/fingerprint_dialog_fp_icon_size"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginTop="48dp"
+ android:scaleType="fitXY"
+ android:contentDescription="@string/accessibility_fingerprint_dialog_fingerprint_icon" />
+
+ <TextView
+ android:id="@+id/error"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="24dp"
+ android:layout_marginStart="24dp"
+ android:paddingTop="16dp"
+ android:paddingBottom="24dp"
+ android:textSize="12sp"
+ android:gravity="center_horizontal"
+ android:accessibilityLiveRegion="polite"
+ android:text="@string/fingerprint_dialog_touch_sensor"
+ android:contentDescription="@string/accessibility_fingerprint_dialog_help_area"
+ android:textColor="@color/fingerprint_dialog_text_light_color"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="72dip"
+ android:paddingTop="24dp"
+ android:layout_gravity="center_vertical"
+ style="?android:attr/buttonBarStyle"
+ android:orientation="horizontal"
+ android:measureWithLargestChild="true">
+ <Space android:id="@+id/leftSpacer"
+ android:layout_width="24dp"
+ android:layout_height="match_parent"
+ android:visibility="visible" />
+ <!-- Negative Button -->
+ <Button android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
+ android:layout_marginStart="-12dp"
+ android:gravity="start|center_vertical"
+ android:maxLines="2" />
+ <!-- Positive Button -->
+ <Button android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
+ android:layout_marginEnd="12dp"
+ android:maxLines="2" />
+ <Space android:id="@+id/rightSpacer"
+ android:layout_width="24dip"
+ android:layout_height="match_parent"
+ android:visibility="gone" />
+ </LinearLayout>
</LinearLayout>
+
+ <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
+ on horizontal/portrait orientation -->
+ <View
+ android:id="@+id/right_space"
+ android:layout_weight="1"
+ android:layout_width="0dp"
+ android:layout_height="match_parent" />
+
</LinearLayout>
</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/mobile_signal_group.xml b/packages/SystemUI/res/layout/mobile_signal_group.xml
index 33effba..2e92042 100644
--- a/packages/SystemUI/res/layout/mobile_signal_group.xml
+++ b/packages/SystemUI/res/layout/mobile_signal_group.xml
@@ -16,17 +16,18 @@
** limitations under the License.
*/
-->
-<LinearLayout
+<com.android.keyguard.AlphaOptimizedLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/mobile_combo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:orientation="horizontal"
- >
+ android:layout_gravity="center_vertical"
+ android:orientation="horizontal">
<FrameLayout
android:layout_height="17dp"
- android:layout_width="wrap_content">
+ android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical">
<ImageView
android:id="@+id/mobile_in"
android:layout_height="wrap_content"
@@ -44,9 +45,16 @@
android:visibility="gone"
/>
</FrameLayout>
+ <ImageView
+ android:id="@+id/mobile_type"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:visibility="gone" />
<FrameLayout
android:layout_width="wrap_content"
- android:layout_height="wrap_content">
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical">
<com.android.systemui.statusbar.AnimatedImageView
android:theme="@style/DualToneLightTheme"
android:id="@+id/mobile_signal"
@@ -63,11 +71,6 @@
systemui:hasOverlappingRendering="false"
/>
<ImageView
- android:id="@+id/mobile_type"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- />
- <ImageView
android:id="@+id/mobile_roaming"
android:layout_width="wrap_content"
android:layout_height="17dp"
@@ -76,7 +79,7 @@
android:paddingBottom="3dp"
android:scaleType="fitCenter"
android:src="@drawable/stat_sys_roaming"
- android:contentDescription="@string/accessibility_data_connection_roaming"
+ android:contentDescription="@string/data_connection_roaming"
android:visibility="gone" />
</FrameLayout>
-</LinearLayout>
+</com.android.keyguard.AlphaOptimizedLinearLayout>
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index 759d1ed..b1cb6cf 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -29,6 +29,7 @@
<!-- Package Info -->
<RelativeLayout
+ android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
@@ -140,6 +141,12 @@
android:layout_height="match_parent"
style="@style/TextAppearance.NotificationInfo.Button"/>
<TextView
+ android:id="@+id/minimize"
+ android:text="@string/inline_minimize_button"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ style="@style/TextAppearance.NotificationInfo.Button" />
+ <TextView
android:id="@+id/keep"
android:text="@string/inline_keep_button"
android:layout_width="wrap_content"
@@ -157,10 +164,11 @@
android:visibility="gone"
android:orientation="horizontal" >
<TextView
+ android:id="@+id/confirmation_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/notification_channel_disabled"
- style="@style/TextAppearance.NotificationInfo.Secondary.Warning"/>
+ style="@style/TextAppearance.NotificationInfo.Confirmation"/>
<TextView
android:id="@+id/undo"
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index 9bf7870..7500bc6 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -43,6 +43,14 @@
android:layout_gravity="center_vertical"
android:gravity="end" >
+ <include
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical|start"
+ android:layout_margin="15dp"
+ android:visibility="gone"
+ layout="@layout/mobile_signal_group" />
+
<com.android.keyguard.CarrierText
android:id="@+id/qs_carrier_text"
android:layout_width="0dp"
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index b6d241b..0a3f4eb 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<com.android.systemui.volume.VolumeUiLayout
+<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -73,20 +73,22 @@
<!-- volume rows added and removed here! :-) -->
</LinearLayout>
<FrameLayout
- android:layout_height="wrap_content"
+ android:id="@+id/settings_container"
android:layout_width="match_parent"
+ android:layout_height="wrap_content"
android:background="@drawable/rounded_bg_bottom_background">
<com.android.keyguard.AlphaOptimizedImageButton
android:id="@+id/settings"
- android:src="@drawable/ic_settings"
+ android:src="@drawable/ic_settings_16dp"
android:layout_width="@dimen/volume_dialog_tap_target_size"
android:layout_height="@dimen/volume_dialog_tap_target_size"
android:layout_gravity="center"
+ android:contentDescription="@string/accessibility_volume_settings"
android:background="?android:selectableItemBackgroundBorderless"
- android:tint="#8A000000"
+ android:tint="?android:attr/colorControlNormal"
android:soundEffectsEnabled="false" />
</FrameLayout>
</LinearLayout>
</LinearLayout>
-</com.android.systemui.volume.VolumeUiLayout>
\ No newline at end of file
+</FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml
index def6f6b..bcc3692 100644
--- a/packages/SystemUI/res/layout/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_row.xml
@@ -25,7 +25,6 @@
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:layout_marginTop="@dimen/volume_dialog_slider_margin_top"
android:gravity="center"
android:layout_gravity="center"
android:orientation="vertical" >
@@ -42,6 +41,8 @@
<FrameLayout
android:id="@+id/volume_row_slider_frame"
android:layout_width="match_parent"
+ android:layout_marginTop="@dimen/volume_dialog_slider_margin_top"
+ android:layout_marginBottom="@dimen/volume_dialog_slider_margin_bottom"
android:layoutDirection="rtl"
android:layout_height="@dimen/volume_dialog_slider_height">
<SeekBar
@@ -60,6 +61,7 @@
android:layout_width="@dimen/volume_dialog_tap_target_size"
android:layout_height="@dimen/volume_dialog_tap_target_size"
android:background="?android:selectableItemBackgroundBorderless"
+ android:layout_marginBottom="@dimen/volume_dialog_row_margin_bottom"
android:tint="@color/accent_tint_color_selector"
android:soundEffectsEnabled="false" />
</LinearLayout>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 12fccd4..4d6509d 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -401,9 +401,9 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Aucune\ninterruption"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priorité\nuniquement"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarmes\nuniquement"</string>
- <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement… (rechargé à 100 % dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
- <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement rapide… (à 100 % dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
- <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement lent… (à 100 % dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+ <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement… (rechargé à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement rapide… (à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement lent… (à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Changer d\'utilisateur"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Changer d\'utilisateur (utilisateur actuel : <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Utilisateur actuel : <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-h650dp/dimens.xml b/packages/SystemUI/res/values-h800dp/dimens.xml
similarity index 75%
copy from packages/SystemUI/res/values-h650dp/dimens.xml
copy to packages/SystemUI/res/values-h800dp/dimens.xml
index 8a00953..6a0e880 100644
--- a/packages/SystemUI/res/values-h650dp/dimens.xml
+++ b/packages/SystemUI/res/values-h800dp/dimens.xml
@@ -1,5 +1,5 @@
<!--
- ~ Copyright (C) 2014 The Android Open Source Project
+ ~ Copyright (C) 2018 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.
@@ -15,5 +15,6 @@
-->
<resources>
- <dimen name="keyguard_clock_notifications_margin">32dp</dimen>
+ <!-- Minimum margin between clock and top of screen or ambient indication -->
+ <dimen name="keyguard_clock_top_margin">76dp</dimen>
</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index e2a94df..5b038b1 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -160,12 +160,12 @@
<color name="smart_reply_button_background">#fff2f2f2</color>
<!-- Fingerprint dialog colors -->
- <color name="fingerprint_dialog_bg_color">#f4ffffff</color> <!-- 96% white -->
- <color name="fingerprint_dialog_text_dark_color">#ff212121</color>
- <color name="fingerprint_dialog_text_light_color">#ff757575</color>
+ <color name="fingerprint_dialog_bg_color">#ffffffff</color> <!-- 100% white -->
+ <color name="fingerprint_dialog_text_dark_color">#dd000000</color> <!-- 87% black -->
+ <color name="fingerprint_dialog_text_light_color">#89000000</color> <!-- 54% black -->
<color name="fingerprint_dialog_dim_color">#80000000</color> <!-- 50% black -->
- <color name="fingerprint_dialog_error_message_color">#ffff5722</color>
- <color name="fingerprint_dialog_fingerprint_color">#ff009688</color>
+ <color name="fingerprint_dialog_error_message_color">#ffd93025</color> <!-- google red 600 -->
+ <color name="fingerprint_dialog_fingerprint_color">#ff008577</color> <!-- google blue 600 -->
<!-- Logout button -->
<color name="logout_button_bg_color">#ccffffff</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index e12f7b7..e30b86a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -270,7 +270,7 @@
<dimen name="volume_dialog_panel_width">64dp</dimen>
- <dimen name="volume_dialog_slider_height">101dp</dimen>
+ <dimen name="volume_dialog_slider_height">108dp</dimen>
<dimen name="volume_dialog_row_height">252dp</dimen>
@@ -280,7 +280,13 @@
<dimen name="volume_dialog_spacer">4dp</dimen>
- <dimen name="volume_dialog_slider_margin_top">13dp</dimen>
+ <dimen name="volume_dialog_slider_margin_top">22dp</dimen>
+
+ <dimen name="volume_dialog_slider_margin_bottom">-2dp</dimen>
+
+ <dimen name="volume_dialog_row_margin_bottom">8dp</dimen>
+
+ <dimen name="volume_dialog_settings_icon_size">16dp</dimen>
<!-- Gravity for the notification panel -->
<integer name="notification_panel_layout_gravity">0x31</integer><!-- center_horizontal|top -->
@@ -443,8 +449,8 @@
<!-- The margin between the clock and the notifications on Keyguard.-->
<dimen name="keyguard_clock_notifications_margin">30dp</dimen>
- <!-- Minimum margin between clock and top of screen or ambient indication -->
- <dimen name="keyguard_clock_top_margin">26dp</dimen>
+ <!-- Minimum margin between clock and status bar -->
+ <dimen name="keyguard_clock_top_margin">36dp</dimen>
<dimen name="heads_up_scrim_height">250dp</dimen>
<item name="scrim_behind_alpha" format="float" type="dimen">0.62</item>
@@ -906,8 +912,9 @@
<dimen name="smart_reply_button_line_spacing_extra">6sp</dimen> <!-- Total line height 20sp. -->
<!-- Fingerprint Dialog values -->
- <dimen name="fingerprint_dialog_fp_icon_size">60dp</dimen>
+ <dimen name="fingerprint_dialog_fp_icon_size">64dp</dimen>
<dimen name="fingerprint_dialog_animation_translation_offset">350dp</dimen>
+ <dimen name="fingerprint_dialog_corner_size">2dp</dimen>
<!-- Wireless Charging Animation values -->
<dimen name="wireless_charging_dots_radius_start">0dp</dimen>
diff --git a/packages/SystemUI/res/values/dimens_car.xml b/packages/SystemUI/res/values/dimens_car.xml
index f3c9f89..5679dd2 100644
--- a/packages/SystemUI/res/values/dimens_car.xml
+++ b/packages/SystemUI/res/values/dimens_car.xml
@@ -36,8 +36,6 @@
<dimen name="car_page_indicator_dot_diameter">12dp</dimen>
<dimen name="car_page_indicator_margin_bottom">24dp</dimen>
- <dimen name="car_user_switcher_progress_bar_height">6dp</dimen>
- <dimen name="car_user_switcher_progress_bar_margin_top">@dimen/status_bar_height</dimen>
<dimen name="car_start_driving_corner_radius">16dp</dimen>
<dimen name="car_start_driving_padding_side">30dp</dimen>
<dimen name="car_start_driving_height">80dp</dimen>
@@ -57,7 +55,6 @@
<dimen name="car_user_switcher_container_height">420dp</dimen>
<!-- This must be the negative of car_user_switcher_container_height for the animation. -->
<dimen name="car_user_switcher_container_anim_height">-420dp</dimen>
- <dimen name="car_user_grid_margin_bottom">28dp</dimen>
<dimen name="car_body2_size">26sp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-h650dp/dimens.xml b/packages/SystemUI/res/values/integers.xml
similarity index 76%
rename from packages/SystemUI/res/values-h650dp/dimens.xml
rename to packages/SystemUI/res/values/integers.xml
index 8a00953..8f23283 100644
--- a/packages/SystemUI/res/values-h650dp/dimens.xml
+++ b/packages/SystemUI/res/values/integers.xml
@@ -1,5 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2014 The Android Open Source Project
+ ~ Copyright (C) 2018 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.
@@ -13,7 +14,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
<resources>
- <dimen name="keyguard_clock_notifications_margin">32dp</dimen>
+ <integer name="fingerprint_dialog_text_gravity">8388611</integer> <!-- gravity start -->
</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/integers_car.xml b/packages/SystemUI/res/values/integers_car.xml
index f84dd4b..a462576 100644
--- a/packages/SystemUI/res/values/integers_car.xml
+++ b/packages/SystemUI/res/values/integers_car.xml
@@ -16,8 +16,5 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <integer name="car_user_switcher_timeout_ms">15000</integer>
- <!-- This values less than ProgressBar.PROGRESS_ANIM_DURATION for a smooth animation. -->
- <integer name="car_user_switcher_anim_update_ms">60</integer>
<integer name="car_user_switcher_anim_cascade_delay_ms">27</integer>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 4420103..814b3ef 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -362,41 +362,44 @@
<!-- Content description of an item that is connecting for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_desc_connecting">Connecting.</string>
- <!-- Content description of the data connection type GPRS for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_data_connection_gprs">GPRS</string>
+ <!-- Content description of the data connection type GPRS. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_gprs">GPRS</string>
- <!-- Content description of the data connection type 1x for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_data_connection_1x">1 X</string>
+ <!-- Content description of the data connection type 1x. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_1x">1 X</string>
- <!-- Content description of the data connection type HSPA and its variants for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_data_connection_hspa">HSPA</string>
+ <!-- Content description of the data connection type HSPA and its variants. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_hspa">HSPA</string>
- <!-- Content description of the data connection type 3G for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_data_connection_3g">3G</string>
+ <!-- Content description of the data connection type 3G. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_3g">3G</string>
- <!-- Content description of the data connection type 3.5G for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_data_connection_3.5g">3.5G</string>
+ <!-- Content description of the data connection type 3.5G. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_3_5g">3.5G</string>
- <!-- Content description of the data connection type 4G for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_data_connection_4g">4G</string>
+ <!-- Content description of the data connection type 3.5G+. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_3_5g_plus">3.5G+</string>
- <!-- Content description of the data connection type 4G for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <!-- Content description of the data connection type 4G . [CHAR LIMIT=NONE] -->
+ <string name="data_connection_4g">4G</string>
- <!-- Content description of the data connection type LTE for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_data_connection_lte">LTE</string>
+ <!-- Content description of the data connection type 4G+. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_4g_plus">4G+</string>
- <!-- Content description of the data connection type LTE+ for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_data_connection_lte_plus">LTE+</string>
+ <!-- Content description of the data connection type LTE. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_lte">LTE</string>
- <!-- Content description of the data connection type CDMA for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_data_connection_cdma">CDMA</string>
+ <!-- Content description of the data connection type LTE+. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_lte_plus">LTE+</string>
- <!-- Content description of the roaming data connection type for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_data_connection_roaming">Roaming</string>
+ <!-- Content description of the data connection type CDMA. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_cdma">CDMA</string>
- <!-- Content description of the data connection type Edge for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_data_connection_edge">Edge</string>
+ <!-- Content description of the roaming data connection type. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_roaming">Roaming</string>
+
+ <!-- Content description of the data connection type Edge. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_edge">EDGE</string>
<!-- Content description of the data connection type WiFi for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_data_connection_wifi">Wi-Fi</string>
@@ -411,7 +414,7 @@
<string name="accessibility_cell_data_on">Mobile Data On</string>
<!-- Content description of the cell data being disabled. [CHAR LIMIT=NONE] -->
- <string name="accessibility_cell_data_off">Mobile Data Off</string>
+ <string name="cell_data_off">Mobile data off</string>
<!-- Content description of the bluetooth tethering icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_bluetooth_tether">Bluetooth tethering.</string>
@@ -425,8 +428,8 @@
<!-- Content description of the no sim icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_no_sims">No SIM card.</string>
- <!-- Content description of the carrier network changing icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_carrier_network_change_mode">Carrier network changing.</string>
+ <!-- Content description of the carrier network changing icon. [CHAR LIMIT=NONE] -->
+ <string name="carrier_network_change_mode">Carrier network changing</string>
<!-- Content description of button to open battery details icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_battery_details">Open battery details</string>
@@ -780,6 +783,9 @@
<string name="quick_settings_hotspot_label">Hotspot</string>
<!-- QuickSettings: Hotspot. Secondary label shown when the hotspot is being enabled [CHAR LIMIT=NONE] -->
<string name="quick_settings_hotspot_secondary_label_transient">Turning on…</string>
+ <!-- QuickSettings: Hotspot. Secondary label shown when Data Saver mode is enabled to explain to
+ the user why they can't toggle the hotspot tile. [CHAR LIMIT=20] -->
+ <string name="quick_settings_hotspot_secondary_label_data_saver_enabled">Data Saver is on</string>
<!-- QuickSettings: Hotspot: Secondary label for how many devices are connected to the hotspot [CHAR LIMIT=NONE] -->
<plurals name="quick_settings_hotspot_secondary_label_num_devices">
<item quantity="one">%d device</item>
@@ -1268,6 +1274,9 @@
<!-- Button label for ending zen mode in the volume dialog -->
<string name="volume_zen_end_now">Turn off now</string>
+ <!-- Content description for accessibility (not shown on the screen): volume dialog settings button. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_volume_settings">Sound settings</string>
+
<!-- Content description for accessibility (not shown on the screen): volume dialog expand button. [CHAR LIMIT=NONE] -->
<string name="accessibility_volume_expand">Expand</string>
@@ -1526,6 +1535,9 @@
<!-- Notification Inline Controls: Shown when a channel's notifications are currently blocked -->
<string name="notification_channel_disabled">You won\'t see these notifications anymore</string>
+ <!-- Notification inline controls: Shown when a channel's notifications are minimized -->
+ <string name="notification_channel_minimized">These notifications will be minimized</string>
+
<!-- Notification Inline controls: continue receiving notifications prompt, channel level -->
<string name="inline_blocking_helper">You usually dismiss these notifications.
\nKeep showing them?</string>
@@ -1539,6 +1551,9 @@
<!-- Notification inline controls: keep getting notifications button -->
<string name="inline_keep_button">Keep showing</string>
+ <!-- Notification inline controls: minimize notifications button -->
+ <string name="inline_minimize_button">Minimize</string>
+
<!-- Notification Inline controls: continue receiving notifications prompt, app level -->
<string name="inline_keep_showing_app">Keep showing notifications from this app?</string>
@@ -1941,8 +1956,8 @@
<!-- accessibility label for button to select user [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_user">Signed in as <xliff:g name="user" example="John">%s</xliff:g></string>
- <!-- accessibility label for no internet [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_no_internet">No internet.</string>
+ <!-- Content description for no internet connection [CHAR LIMIT=NONE] -->
+ <string name="data_connection_no_internet">No internet</string>
<!-- accessibility label for quick settings items that open a details page [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_open_details">Open details.</string>
@@ -2096,6 +2111,9 @@
<!-- Quick settings tile for toggling mobile data [CHAR LIMIT=20] -->
<string name="mobile_data">Mobile data</string>
+ <!-- Quick settings tile secondary label format combining roaming with the mobile data type. [CHAR LIMIT=NONE] -->
+ <string name="mobile_data_text_format"><xliff:g name="roaming_status" example="Roaming">%s</xliff:g> \u2014 <xliff:g name="mobile_data_type" example="LTE">%s</xliff:g></string>
+
<!-- Label for when wifi is off in QS detail panel [CHAR LIMIT=NONE] -->
<string name="wifi_is_off">Wi-Fi is off</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index d006af1..1470dfa 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -335,6 +335,7 @@
<style name="qs_theme" parent="qs_base">
<item name="lightIconTheme">@style/QSIconTheme</item>
<item name="darkIconTheme">@style/QSIconTheme</item>
+ <item name="android:windowIsFloating">true</item>
</style>
<style name="systemui_theme_remote_input" parent="@android:style/Theme.DeviceDefault.Light">
@@ -345,7 +346,9 @@
<style name="Theme.SystemUI.Dialog.Alert" parent="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert" />
- <style name="Theme.SystemUI.Dialog.GlobalActions" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar.Fullscreen" />
+ <style name="Theme.SystemUI.Dialog.GlobalActions" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar.Fullscreen">
+ <item name="android:windowIsFloating">true</item>
+ </style>
<style name="QSBorderlessButton">
<item name="android:padding">12dp</item>
@@ -456,6 +459,12 @@
<item name="android:alpha">0.87</item>
</style>
+ <style name="TextAppearance.NotificationInfo.Confirmation">
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:textSize">14sp</item>
+ <item name="android:alpha">0.87</item>
+ </style>
+
<style name="TextAppearance.NotificationInfo.Secondary">
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:textSize">14sp</item>
diff --git a/packages/SystemUI/res/values/styles_car.xml b/packages/SystemUI/res/values/styles_car.xml
index c66792c..2aaef86 100644
--- a/packages/SystemUI/res/values/styles_car.xml
+++ b/packages/SystemUI/res/values/styles_car.xml
@@ -16,14 +16,6 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <style name="CarUserSwitcher.ProgressBar" parent="@android:style/Widget.ProgressBar.Horizontal">
- <item name="android:progressDrawable">@drawable/car_progress_bar</item>
- <item name="android:min">0</item>
- <item name="android:max">@integer/car_user_switcher_timeout_ms</item>
- <item name="android:progress">0</item>
- <item name="android:interpolator">@android:anim/linear_interpolator</item>
- </style>
-
<style name="CarUserSwitcher.StartDrivingButton" parent="@android:style/Widget.Material.Button">
<item name="android:background">@drawable/car_round_button</item>
<item name="android:textSize">@dimen/car_start_driving_text_size</item>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
index ef36610..8612445 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
@@ -80,4 +80,17 @@
* Sent when overview is to be hidden.
*/
void onOverviewHidden(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
+
+ /**
+ * Sent when a user swipes up over the navigation bar to launch overview. Swipe up is determined
+ * by passing the touch slop in the direction towards launcher from navigation bar. During and
+ * after this event is sent the caller will continue to send motion events. The motion
+ * {@param event} passed after the touch slop was exceeded will also be passed after by
+ * {@link onMotionEvent}. Since motion events will be sent, motion up or cancel can still be
+ * sent to cancel overview regardless the current state of launcher (eg. if overview is already
+ * visible, this event will still be sent if user swipes up). When this signal is sent,
+ * navigation bar will not handle any gestures such as quick scrub or switch and the home button
+ * will cancel (long) press.
+ */
+ void onQuickStep(in MotionEvent event);
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index 846aadd..4799f39 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -36,11 +36,6 @@
void startScreenPinning(int taskId) = 1;
/**
- * Called when the overview service has started the recents animation.
- */
- void onRecentsAnimationStarted() = 2;
-
- /**
* Specifies the text to be shown for onboarding the new swipe-up gesture to access recents.
*/
void setRecentsOnboardingText(CharSequence text) = 3;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/IconLoader.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/IconLoader.java
index 3bc1d9a..14767f1 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/IconLoader.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/IconLoader.java
@@ -103,12 +103,13 @@
int userId = taskKey.userId;
Bitmap tdIcon = desc.getInMemoryIcon();
if (tdIcon != null) {
- return createDrawableFromBitmap(tdIcon, userId);
+ return createDrawableFromBitmap(tdIcon, userId, desc);
}
if (desc.getIconResource() != 0) {
// TODO: Use task context here
try {
- return createBadgedDrawable(mContext.getDrawable(desc.getIconResource()), userId);
+ return createBadgedDrawable(
+ mContext.getDrawable(desc.getIconResource()), userId, desc);
} catch (Resources.NotFoundException e) {
Log.e(TAG, "Could not find icon drawable from resource", e);
}
@@ -117,13 +118,13 @@
tdIcon = ActivityManager.TaskDescription.loadTaskDescriptionIcon(
desc.getIconFilename(), userId);
if (tdIcon != null) {
- return createDrawableFromBitmap(tdIcon, userId);
+ return createDrawableFromBitmap(tdIcon, userId, desc);
}
// Load the icon from the activity info and cache it
ActivityInfo activityInfo = getAndUpdateActivityInfo(taskKey);
if (activityInfo != null) {
- Drawable icon = getBadgedActivityIcon(activityInfo, userId);
+ Drawable icon = getBadgedActivityIcon(activityInfo, userId, desc);
if (icon != null) {
return icon;
}
@@ -135,16 +136,20 @@
public abstract Drawable getDefaultIcon(int userId);
- protected Drawable createDrawableFromBitmap(Bitmap icon, int userId) {
- return createBadgedDrawable(new BitmapDrawable(mContext.getResources(), icon), userId);
+ protected Drawable createDrawableFromBitmap(Bitmap icon, int userId,
+ ActivityManager.TaskDescription desc) {
+ return createBadgedDrawable(
+ new BitmapDrawable(mContext.getResources(), icon), userId, desc);
}
- protected abstract Drawable createBadgedDrawable(Drawable icon, int userId);
+ protected abstract Drawable createBadgedDrawable(Drawable icon, int userId,
+ ActivityManager.TaskDescription desc);
/**
* @return the activity icon for the ActivityInfo for a user, badging if necessary.
*/
- protected abstract Drawable getBadgedActivityIcon(ActivityInfo info, int userId);
+ protected abstract Drawable getBadgedActivityIcon(ActivityInfo info, int userId,
+ ActivityManager.TaskDescription desc);
public static class DefaultIconLoader extends IconLoader {
@@ -168,7 +173,8 @@
}
@Override
- protected Drawable createBadgedDrawable(Drawable icon, int userId) {
+ protected Drawable createBadgedDrawable(Drawable icon, int userId,
+ ActivityManager.TaskDescription desc) {
if (userId != UserHandle.myUserId()) {
icon = mContext.getPackageManager().getUserBadgedIcon(icon, new UserHandle(userId));
}
@@ -176,7 +182,8 @@
}
@Override
- protected Drawable getBadgedActivityIcon(ActivityInfo info, int userId) {
+ protected Drawable getBadgedActivityIcon(ActivityInfo info, int userId,
+ ActivityManager.TaskDescription desc) {
return mDrawableFactory.getBadgedIcon(info, info.applicationInfo, userId);
}
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
index dd1763b..924e85d 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
@@ -31,6 +31,7 @@
public int orientation;
public Rect insets;
public boolean reducedResolution;
+ public boolean isRealSnapshot;
public float scale;
public ThumbnailData() {
@@ -39,6 +40,7 @@
insets = new Rect();
reducedResolution = false;
scale = 1f;
+ isRealSnapshot = true;
}
public ThumbnailData(TaskSnapshot snapshot) {
@@ -47,5 +49,6 @@
orientation = snapshot.getOrientation();
reducedResolution = snapshot.isReducedResolution();
scale = snapshot.getScale();
+ isRealSnapshot = snapshot.isRealSnapshot();
}
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/LatencyTrackerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/LatencyTrackerCompat.java
new file mode 100644
index 0000000..0d5933e
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/LatencyTrackerCompat.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.shared.system;
+
+import android.content.Context;
+
+import com.android.internal.util.LatencyTracker;
+
+/**
+ * @see LatencyTracker
+ */
+public class LatencyTrackerCompat {
+ public static boolean isEnabled(Context context) {
+ return LatencyTracker.isEnabled(context);
+ }
+
+ public static void logToggleRecents(int duration) {
+ LatencyTracker.logAction(LatencyTracker.ACTION_TOGGLE_RECENTS, duration);
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index 9a7abf8..940c9ef 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -51,6 +51,14 @@
}
}
+ public void setAnimationTargetsBehindSystemBars(boolean behindSystemBars) {
+ try {
+ mAnimationController.setAnimationTargetsBehindSystemBars(behindSystemBars);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to set whether animation targets are behind system bars", e);
+ }
+ }
+
public void finish(boolean toHome) {
try {
mAnimationController.finish(toHome);
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index b8c5049..0f52209 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -18,7 +18,6 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
-import android.app.WindowConfiguration;
import android.graphics.Point;
import android.graphics.Rect;
import android.view.RemoteAnimationTarget;
@@ -39,6 +38,7 @@
public final int prefixOrderIndex;
public final Point position;
public final Rect sourceContainerBounds;
+ public final boolean isNotInRecents;
private final RemoteAnimationTarget mTarget;
@@ -52,6 +52,7 @@
position = app.position;
sourceContainerBounds = app.sourceContainerBounds;
prefixOrderIndex = app.prefixOrderIndex;
+ isNotInRecents = app.isNotInRecents;
}
public static RemoteAnimationTargetCompat[] wrap(RemoteAnimationTarget[] apps) {
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierText.java b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
index 45d1aad8..5b0f1c3 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierText.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
@@ -39,9 +39,15 @@
import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.telephony.TelephonyIntents;
import com.android.settingslib.WirelessUtils;
+
import android.telephony.TelephonyManager;
public class CarrierText extends TextView {
+ /** Do not show missing sim message. */
+ public static final int FLAG_HIDE_MISSING_SIM = 1 << 0;
+ /** Do not show airplane mode message. */
+ public static final int FLAG_HIDE_AIRPLANE_MODE = 1 << 1;
+
private static final boolean DEBUG = KeyguardConstants.DEBUG;
private static final String TAG = "CarrierText";
@@ -55,6 +61,8 @@
private boolean[] mSimErrorState = new boolean[TelephonyManager.getDefault().getPhoneCount()];
+ private int mFlags;
+
private KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
@Override
public void onRefreshCarrierInfo() {
@@ -85,6 +93,11 @@
}
};
};
+
+ public void setDisplayFlags(int flags) {
+ mFlags = flags;
+ }
+
/**
* The status of this lock screen. Primarily used for widgets on LockScreen.
*/
@@ -196,8 +209,7 @@
// Grab the first subscripton, because they all should contain the emergency text,
// described above.
displayText = makeCarrierStringOnEmergencyCapable(
- getContext().getText(R.string.keyguard_missing_sim_message_short),
- subs.get(0).getCarrierName());
+ getMissingSimMessage(), subs.get(0).getCarrierName());
} else {
// We don't have a SubscriptionInfo to get the emergency calls only from.
// Grab it from the old sticky broadcast if possible instead. We can use it
@@ -223,8 +235,7 @@
text = concatenate(plmn, spn);
}
}
- displayText = makeCarrierStringOnEmergencyCapable(
- getContext().getText(R.string.keyguard_missing_sim_message_short), text);
+ displayText = makeCarrierStringOnEmergencyCapable(getMissingSimMessage(), text);
}
}
@@ -232,11 +243,21 @@
// APM (airplane mode) != no carrier state. There are carrier services
// (e.g. WFC = Wi-Fi calling) which may operate in APM.
if (!anySimReadyAndInService && WirelessUtils.isAirplaneModeOn(mContext)) {
- displayText = getContext().getString(R.string.airplane_mode);
+ displayText = getAirplaneModeMessage();
}
setText(displayText);
}
+ private String getMissingSimMessage() {
+ return (mFlags & FLAG_HIDE_MISSING_SIM) == 0
+ ? getContext().getString(R.string.keyguard_missing_sim_message_short) : "";
+ }
+
+ private String getAirplaneModeMessage() {
+ return (mFlags & FLAG_HIDE_AIRPLANE_MODE) == 0
+ ? getContext().getString(R.string.airplane_mode) : "";
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
index 474fc90..62b5004 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
@@ -149,7 +149,6 @@
mSecurityContainer.setLockPatternUtils(mLockPatternUtils);
mSecurityContainer.setSecurityCallback(this);
mSecurityContainer.showPrimarySecurityScreen(false);
- // mSecurityContainer.updateSecurityViews(false /* not bouncing */);
}
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index 6b99206..f0952f9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -331,6 +331,37 @@
updateVisibility();
}
+ public static class Row extends LinearLayout {
+
+ public Row(Context context) {
+ super(context);
+ }
+
+ public Row(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public Row(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public Row(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ for (int i = 0; i < getChildCount(); i++) {
+ View child = getChildAt(i);
+ if (child instanceof KeyguardSliceButton) {
+ ((KeyguardSliceButton) child).setMaxWidth(width / 2);
+ }
+ }
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+ }
+
/**
* Representation of an item that appears under the clock on main keyguard message.
*/
@@ -344,7 +375,6 @@
setPadding(horizontalPadding / 2, 0, horizontalPadding / 2, 0);
setCompoundDrawablePadding((int) context.getResources()
.getDimension(R.dimen.widget_icon_padding));
- setMaxWidth(KeyguardSliceView.this.getWidth() / 2);
setMaxLines(1);
setEllipsize(TruncateAt.END);
}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index cad155c..5fce0a6 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -45,6 +45,7 @@
import com.android.systemui.power.PowerNotificationWarnings;
import com.android.systemui.power.PowerUI;
import com.android.systemui.statusbar.AppOpsListener;
+import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
import com.android.systemui.statusbar.phone.LightBarController;
@@ -317,6 +318,8 @@
mProviders.put(AppOpsListener.class, () -> new AppOpsListener(mContext));
+ mProviders.put(VibratorHelper.class, () -> new VibratorHelper(mContext));
+
// Put all dependencies above here so the factory can override them if it wants.
SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
}
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
index 041af0e..a4af6b2 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -102,15 +102,6 @@
}
}
- public void onRecentsAnimationStarted() {
- long token = Binder.clearCallingIdentity();
- try {
- mHandler.post(OverviewProxyService.this::notifyRecentsAnimationStarted);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
public void onSplitScreenInvoked() {
long token = Binder.clearCallingIdentity();
try {
@@ -283,9 +274,9 @@
}
}
- private void notifyRecentsAnimationStarted() {
+ public void notifyQuickStepStarted() {
for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
- mConnectionCallbacks.get(i).onRecentsAnimationStarted();
+ mConnectionCallbacks.get(i).onQuickStepStarted();
}
}
@@ -300,7 +291,7 @@
public interface OverviewProxyListener {
default void onConnectionChanged(boolean isConnected) {}
- default void onRecentsAnimationStarted() {}
+ default void onQuickStepStarted() {}
default void onInteractionFlagsChanged(@InteractionType int flags) {}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 903f3aa..4d54bdd 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -31,7 +31,9 @@
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.graphics.Region;
import android.hardware.display.DisplayManager;
+import android.os.SystemProperties;
import android.provider.Settings.Secure;
import android.support.annotation.VisibleForTesting;
import android.util.DisplayMetrics;
@@ -64,6 +66,8 @@
public class ScreenDecorations extends SystemUI implements Tunable {
public static final String SIZE = "sysui_rounded_size";
public static final String PADDING = "sysui_rounded_content_padding";
+ private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS =
+ SystemProperties.getBoolean("debug.screenshot_rounded_corners", false);
private int mRoundedDefault;
private View mOverlay;
@@ -235,8 +239,10 @@
| WindowManager.LayoutParams.FLAG_SLIPPERY
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT);
- lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS
- | WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
+ lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ if (!DEBUG_SCREENSHOT_ROUNDED_CORNERS) {
+ lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
+ }
lp.setTitle("ScreenDecorOverlay");
lp.gravity = Gravity.TOP | Gravity.LEFT;
lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
@@ -312,6 +318,7 @@
private final DisplayInfo mInfo = new DisplayInfo();
private final Paint mPaint = new Paint();
+ private final Region mBounds = new Region();
private final Rect mBoundingRect = new Rect();
private final Path mBoundingPath = new Path();
private final int[] mLocation = new int[2];
@@ -370,11 +377,13 @@
private void update() {
requestLayout();
getDisplay().getDisplayInfo(mInfo);
+ mBounds.setEmpty();
mBoundingRect.setEmpty();
mBoundingPath.reset();
int newVisible;
if (hasCutout()) {
- mBoundingRect.set(mInfo.displayCutout.getBoundingRect());
+ mBounds.set(mInfo.displayCutout.getBounds());
+ localBounds(mBoundingRect);
mInfo.displayCutout.getBounds().getBoundaryPath(mBoundingPath);
newVisible = VISIBLE;
} else {
@@ -402,7 +411,7 @@
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (mBoundingRect.isEmpty()) {
+ if (mBounds.isEmpty()) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return;
}
@@ -410,5 +419,50 @@
resolveSizeAndState(mBoundingRect.width(), widthMeasureSpec, 0),
resolveSizeAndState(mBoundingRect.height(), heightMeasureSpec, 0));
}
+
+ public static void boundsFromDirection(DisplayCutout displayCutout, int gravity, Rect out) {
+ Region bounds = displayCutout.getBounds();
+ switch (gravity) {
+ case Gravity.TOP:
+ bounds.op(0, 0, Integer.MAX_VALUE, displayCutout.getSafeInsetTop(),
+ Region.Op.INTERSECT);
+ out.set(bounds.getBounds());
+ break;
+ case Gravity.LEFT:
+ bounds.op(0, 0, displayCutout.getSafeInsetLeft(), Integer.MAX_VALUE,
+ Region.Op.INTERSECT);
+ out.set(bounds.getBounds());
+ break;
+ case Gravity.BOTTOM:
+ bounds.op(0, displayCutout.getSafeInsetTop() + 1, Integer.MAX_VALUE,
+ Integer.MAX_VALUE, Region.Op.INTERSECT);
+ out.set(bounds.getBounds());
+ break;
+ case Gravity.RIGHT:
+ bounds.op(displayCutout.getSafeInsetLeft() + 1, 0, Integer.MAX_VALUE,
+ Integer.MAX_VALUE, Region.Op.INTERSECT);
+ out.set(bounds.getBounds());
+ break;
+ }
+ bounds.recycle();
+ }
+
+ private void localBounds(Rect out) {
+ final DisplayCutout displayCutout = mInfo.displayCutout;
+
+ if (mStart) {
+ if (displayCutout.getSafeInsetLeft() > 0) {
+ boundsFromDirection(displayCutout, Gravity.LEFT, out);
+ } else if (displayCutout.getSafeInsetTop() > 0) {
+ boundsFromDirection(displayCutout, Gravity.TOP, out);
+ }
+ } else {
+ if (displayCutout.getSafeInsetRight() > 0) {
+ boundsFromDirection(displayCutout, Gravity.RIGHT, out);
+ } else if (displayCutout.getSafeInsetBottom() > 0) {
+ boundsFromDirection(displayCutout, Gravity.BOTTOM, out);
+ }
+ }
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
index 526e5fa..e18ac74 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
@@ -79,8 +79,8 @@
@Override
public float getFalseTouchEvaluation(int type, Stroke stroke) {
Data data = mStrokeMap.get(stroke);
- return AnglesVarianceEvaluator.evaluate(data.getAnglesVariance())
- + AnglesPercentageEvaluator.evaluate(data.getAnglesPercentage());
+ return AnglesVarianceEvaluator.evaluate(data.getAnglesVariance(), type)
+ + AnglesPercentageEvaluator.evaluate(data.getAnglesPercentage(), type);
}
private static class Data {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java
index e6c42da..e6e42f2 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java
@@ -17,10 +17,11 @@
package com.android.systemui.classifier;
public class AnglesPercentageEvaluator {
- public static float evaluate(float value) {
+ public static float evaluate(float value, int type) {
+ final boolean secureUnlock = type == Classifier.BOUNCER_UNLOCK;
float evaluation = 0.0f;
- if (value < 1.00) evaluation++;
- if (value < 0.90) evaluation++;
+ if (value < 1.00 && !secureUnlock) evaluation++;
+ if (value < 0.90 && !secureUnlock) evaluation++;
if (value < 0.70) evaluation++;
return evaluation;
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java
index 99cc1a6..6883dd0 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java
@@ -17,14 +17,15 @@
package com.android.systemui.classifier;
public class AnglesVarianceEvaluator {
- public static float evaluate(float value) {
+ public static float evaluate(float value, int type) {
+ final boolean secureUnlock = type == Classifier.BOUNCER_UNLOCK;
float evaluation = 0.0f;
if (value > 0.05) evaluation++;
if (value > 0.10) evaluation++;
if (value > 0.20) evaluation++;
- if (value > 0.40) evaluation++;
- if (value > 0.80) evaluation++;
- if (value > 1.50) evaluation++;
+ if (value > 0.40 && !secureUnlock) evaluation++;
+ if (value > 0.80 && !secureUnlock) evaluation++;
+ if (value > 1.50 && !secureUnlock) evaluation++;
return evaluation;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
index cb761a9..909896e 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
@@ -31,6 +31,7 @@
public static final int LEFT_AFFORDANCE = 5;
public static final int RIGHT_AFFORDANCE = 6;
public static final int GENERIC = 7;
+ public static final int BOUNCER_UNLOCK = 8;
/**
* Contains all the information about touch events from which the classifier can query
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DirectionEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/DirectionEvaluator.java
index e20b1ca6..5f04222 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/DirectionEvaluator.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/DirectionEvaluator.java
@@ -33,6 +33,7 @@
}
break;
case Classifier.UNLOCK:
+ case Classifier.BOUNCER_UNLOCK:
if (!vertical || yDiff >= 0.0) {
return falsingEvaluation;
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index ed659e2..913e781 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -356,11 +356,12 @@
mDataCollector.setQsExpanded(expanded);
}
- public void onTrackingStarted() {
+ public void onTrackingStarted(boolean secure) {
if (FalsingLog.ENABLED) {
FalsingLog.i("onTrackingStarted", "");
}
- mHumanInteractionClassifier.setType(Classifier.UNLOCK);
+ mHumanInteractionClassifier.setType(secure ?
+ Classifier.BOUNCER_UNLOCK : Classifier.UNLOCK);
mDataCollector.onTrackingStarted();
}
diff --git a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java
index 1d43b1d..4b15fbc 100644
--- a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java
@@ -180,8 +180,8 @@
}
}
mReceiver = null;
- mWindowManager.removeView(mDialogView);
mDialogShowing = false;
+ mDialogView.startDismiss();
}
private void handleButtonNegative() {
diff --git a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java
index e828b2c..ebdc703 100644
--- a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java
+++ b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java
@@ -17,6 +17,7 @@
package com.android.systemui.fingerprint;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
@@ -27,6 +28,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -42,6 +44,7 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.util.leak.RotationUtils;
/**
* This class loads the view for the system-provided dialog. The view consists of:
@@ -61,7 +64,7 @@
private final IBinder mWindowToken = new Binder();
private final Interpolator mLinearOutSlowIn;
- private final Interpolator mFastOutLinearIn;
+ private final WindowManager mWindowManager;
private final float mAnimationTranslationOffset;
private final int mErrorTextColor;
private final int mTextColor;
@@ -74,11 +77,13 @@
private final LinearLayout mDialog;
private int mLastState;
+ private final float mDisplayWidth;
+
public FingerprintDialogView(Context context, Handler handler) {
super(context);
mHandler = handler;
mLinearOutSlowIn = Interpolators.LINEAR_OUT_SLOW_IN;
- mFastOutLinearIn = Interpolators.FAST_OUT_LINEAR_IN;
+ mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
mAnimationTranslationOffset = getResources()
.getDimension(R.dimen.fingerprint_dialog_animation_translation_offset);
mErrorTextColor = Color.parseColor(
@@ -88,6 +93,10 @@
mFingerprintColor = Color.parseColor(
getResources().getString(R.color.fingerprint_dialog_fingerprint_color));
+ DisplayMetrics metrics = new DisplayMetrics();
+ mWindowManager.getDefaultDisplay().getMetrics(metrics);
+ mDisplayWidth = metrics.widthPixels;
+
// Create the dialog
LayoutInflater factory = LayoutInflater.from(getContext());
mLayout = (ViewGroup) factory.inflate(R.layout.fingerprint_dialog, this, false);
@@ -117,15 +126,14 @@
});
final View space = mLayout.findViewById(R.id.space);
+ final View leftSpace = mLayout.findViewById(R.id.left_space);
+ final View rightSpace = mLayout.findViewById(R.id.right_space);
final Button negative = mLayout.findViewById(R.id.button2);
final Button positive = mLayout.findViewById(R.id.button1);
- space.setClickable(true);
- space.setOnTouchListener((View view, MotionEvent event) -> {
- mHandler.obtainMessage(FingerprintDialogImpl.MSG_HIDE_DIALOG, true /* userCanceled */)
- .sendToTarget();
- return true;
- });
+ setDismissesDialog(space);
+ setDismissesDialog(leftSpace);
+ setDismissesDialog(rightSpace);
negative.setOnClickListener((View v) -> {
mHandler.obtainMessage(FingerprintDialogImpl.MSG_BUTTON_NEGATIVE).sendToTarget();
@@ -149,6 +157,8 @@
final Button negative = mLayout.findViewById(R.id.button2);
final Button positive = mLayout.findViewById(R.id.button1);
+ mDialog.getLayoutParams().width = (int) mDisplayWidth;
+
mLastState = STATE_NONE;
updateFingerprintIcon(STATE_FINGERPRINT);
@@ -189,6 +199,43 @@
});
}
+ private void setDismissesDialog(View v) {
+ v.setClickable(true);
+ v.setOnTouchListener((View view, MotionEvent event) -> {
+ mHandler.obtainMessage(FingerprintDialogImpl.MSG_HIDE_DIALOG, true /* userCanceled */)
+ .sendToTarget();
+ return true;
+ });
+ }
+
+ public void startDismiss() {
+ final Runnable endActionRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mWindowManager.removeView(FingerprintDialogView.this);
+ }
+ };
+
+ postOnAnimation(new Runnable() {
+ @Override
+ public void run() {
+ mLayout.animate()
+ .alpha(0f)
+ .setDuration(ANIMATION_DURATION)
+ .setInterpolator(mLinearOutSlowIn)
+ .withLayer()
+ .start();
+ mDialog.animate()
+ .translationY(mAnimationTranslationOffset)
+ .setDuration(ANIMATION_DURATION)
+ .setInterpolator(mLinearOutSlowIn)
+ .withLayer()
+ .withEndAction(endActionRunnable)
+ .start();
+ }
+ });
+ }
+
public void setBundle(Bundle bundle) {
mBundle = bundle;
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 6f43a18..e171b53 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -14,6 +14,7 @@
package com.android.systemui.globalactions;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
@@ -1356,11 +1357,17 @@
// Window initialization
Window window = getWindow();
window.requestFeature(Window.FEATURE_NO_TITLE);
- window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND
- | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
+ // Inflate the decor view, so the attributes below are not overwritten by the theme.
+ window.getDecorView();
+ window.getAttributes().systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ window.setLayout(MATCH_PARENT, MATCH_PARENT);
+ window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
window.addFlags(
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index 3563437..a1adfa6 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -15,12 +15,14 @@
package com.android.systemui.globalactions;
import static android.app.StatusBarManager.DISABLE2_GLOBAL_ACTIONS;
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import android.app.Dialog;
import android.app.KeyguardManager;
import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.Point;
+import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
@@ -80,15 +82,21 @@
com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);
// Window initialization
Window window = d.getWindow();
+ window.requestFeature(Window.FEATURE_NO_TITLE);
+ window.getAttributes().systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ // Inflate the decor view, so the attributes below are not overwritten by the theme.
+ window.getDecorView();
window.getAttributes().width = ViewGroup.LayoutParams.MATCH_PARENT;
window.getAttributes().height = ViewGroup.LayoutParams.MATCH_PARENT;
+ window.getAttributes().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
- window.requestFeature(Window.FEATURE_NO_TITLE);
- window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND
- | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
+ window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
window.addFlags(
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 6940264..a1b17e4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -83,6 +83,7 @@
import com.android.systemui.UiOffloadThread;
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.statusbar.phone.FingerprintUnlockController;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -2011,8 +2012,9 @@
}
public StatusBarKeyguardViewManager registerStatusBar(StatusBar statusBar,
- ViewGroup container, FingerprintUnlockController fingerprintUnlockController) {
- mStatusBarKeyguardViewManager.registerStatusBar(statusBar, container,
+ ViewGroup container, NotificationPanelView panelView,
+ FingerprintUnlockController fingerprintUnlockController) {
+ mStatusBarKeyguardViewManager.registerStatusBar(statusBar, container, panelView,
fingerprintUnlockController, mDismissCallbackRegistry);
return mStatusBarKeyguardViewManager;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index e9888df..dbf1745 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.Intent;
+import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.Drawable;
@@ -27,6 +28,7 @@
import android.os.UserManager;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
@@ -36,15 +38,18 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.keyguard.CarrierText;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.settingslib.Utils;
import com.android.settingslib.drawable.UserIconDrawable;
+import com.android.settingslib.graph.SignalDrawable;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.R.dimen;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.qs.TouchAnimator.Builder;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.MultiUserSwitch;
import com.android.systemui.statusbar.phone.SettingsButton;
@@ -64,7 +69,7 @@
private UserInfoController mUserInfoController;
private SettingsButton mSettingsButton;
protected View mSettingsContainer;
- private View mCarrierText;
+ private CarrierText mCarrierText;
private boolean mQsDisabled;
private QSPanel mQsPanel;
@@ -86,9 +91,15 @@
private View mActionsContainer;
private View mDragHandle;
+ private View mMobileGroup;
+ private ImageView mMobileSignal;
+ private ImageView mMobileRoaming;
+ private final int mColorForeground;
+ private final CellSignalState mInfo = new CellSignalState();
public QSFooterImpl(Context context, AttributeSet attrs) {
super(context, attrs);
+ mColorForeground = Utils.getColorAttr(context, android.R.attr.colorForeground);
}
@Override
@@ -104,7 +115,12 @@
mSettingsContainer = findViewById(R.id.settings_button_container);
mSettingsButton.setOnClickListener(this);
+ mMobileGroup = findViewById(R.id.mobile_combo);
+ mMobileSignal = findViewById(R.id.mobile_signal);
+ mMobileRoaming = findViewById(R.id.mobile_roaming);
mCarrierText = findViewById(R.id.qs_carrier_text);
+ mCarrierText.setDisplayFlags(
+ CarrierText.FLAG_HIDE_AIRPLANE_MODE | CarrierText.FLAG_HIDE_MISSING_SIM);
mMultiUserSwitch = findViewById(R.id.multi_user_switch);
mMultiUserAvatar = mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
@@ -165,6 +181,7 @@
return new TouchAnimator.Builder()
.addFloat(mDivider, "alpha", 0, 1)
.addFloat(mCarrierText, "alpha", 0, 0, 1)
+ .addFloat(mMobileGroup, "alpha", 0, 1)
.addFloat(mActionsContainer, "alpha", 0, 1)
.addFloat(mDragHandle, "alpha", 1, 0, 0)
.setStartDelay(0.15f)
@@ -338,4 +355,64 @@
}
mMultiUserAvatar.setImageDrawable(picture);
}
+
+ private void handleUpdateState() {
+ mMobileGroup.setVisibility(mInfo.visible ? View.VISIBLE : View.GONE);
+ if (mInfo.visible) {
+ mMobileRoaming.setVisibility(mInfo.roaming ? View.VISIBLE : View.GONE);
+ mMobileRoaming.setImageTintList(ColorStateList.valueOf(mColorForeground));
+ SignalDrawable d = new SignalDrawable(mContext);
+ d.setDarkIntensity(QuickStatusBarHeader.getColorIntensity(mColorForeground));
+ mMobileSignal.setImageDrawable(d);
+ mMobileSignal.setImageLevel(mInfo.mobileSignalIconId);
+
+ StringBuilder contentDescription = new StringBuilder();
+ if (mInfo.contentDescription != null) {
+ contentDescription.append(mInfo.contentDescription).append(", ");
+ }
+ if (mInfo.roaming) {
+ contentDescription
+ .append(mContext.getString(R.string.data_connection_roaming))
+ .append(", ");
+ }
+ // TODO: show mobile data off/no internet text for 5 seconds before carrier text
+ if (TextUtils.equals(mInfo.typeContentDescription,
+ mContext.getString(R.string.data_connection_no_internet))
+ || TextUtils.equals(mInfo.typeContentDescription,
+ mContext.getString(R.string.cell_data_off))) {
+ contentDescription.append(mInfo.typeContentDescription);
+ }
+ mMobileSignal.setContentDescription(contentDescription);
+ }
+ }
+
+ @Override
+ public void setMobileDataIndicators(NetworkController.IconState statusIcon,
+ NetworkController.IconState qsIcon, int statusType,
+ int qsType, boolean activityIn, boolean activityOut,
+ String typeContentDescription,
+ String description, boolean isWide, int subId, boolean roaming) {
+ mInfo.visible = statusIcon.visible;
+ mInfo.mobileSignalIconId = statusIcon.icon;
+ mInfo.contentDescription = statusIcon.contentDescription;
+ mInfo.typeContentDescription = typeContentDescription;
+ mInfo.roaming = roaming;
+ handleUpdateState();
+ }
+
+ @Override
+ public void setNoSims(boolean hasNoSims, boolean simDetected) {
+ if (hasNoSims) {
+ mInfo.visible = false;
+ }
+ handleUpdateState();
+ }
+
+ private final class CellSignalState {
+ boolean visible;
+ int mobileSignalIconId;
+ public String contentDescription;
+ String typeContentDescription;
+ boolean roaming;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index ec4d1a6..a48dcc6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -18,6 +18,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.annotation.ColorInt;
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.content.Context;
@@ -31,6 +32,7 @@
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
@@ -60,6 +62,8 @@
*/
public class QuickStatusBarHeader extends RelativeLayout implements CommandQueue.Callbacks,
View.OnClickListener, NextAlarmController.NextAlarmChangeCallback {
+ private static final String TAG = "QuickStatusBarHeader";
+ private static final boolean DEBUG = false;
/** Delay for auto fading out the long press tooltip after it's fully visible (in ms). */
private static final long AUTO_FADE_OUT_DELAY_MS = DateUtils.SECOND_IN_MILLIS * 6;
@@ -128,7 +132,7 @@
Rect tintArea = new Rect(0, 0, 0, 0);
int colorForeground = Utils.getColorAttr(getContext(), android.R.attr.colorForeground);
- float intensity = colorForeground == Color.WHITE ? 0 : 1;
+ float intensity = getColorIntensity(colorForeground);
int fillColor = fillColorForIntensity(intensity, getContext());
// Set light text on the header icons because they will always be on a black background
@@ -292,6 +296,7 @@
@Override
public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
mNextAlarmText = nextAlarm != null ? formatNextAlarm(nextAlarm) : null;
+
if (mNextAlarmText != null) {
hideLongPressTooltip(true /* shouldFadeInAlarmText */);
} else {
@@ -351,6 +356,7 @@
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
+ if (DEBUG) Log.d(TAG, "hideLongPressTooltip: Hid long press tip");
mLongPressTooltipView.setVisibility(View.INVISIBLE);
if (shouldShowAlarmText) {
@@ -361,7 +367,6 @@
.start();
} else {
mLongPressTooltipView.setVisibility(View.INVISIBLE);
-
if (shouldShowAlarmText) {
showAlarmText();
}
@@ -377,9 +382,11 @@
mNextAlarmView.setVisibility(View.VISIBLE);
mNextAlarmTextView.setText(mNextAlarmText);
+ // Animate the alarm back in. Make sure to clear the animator listener for the animation!
mNextAlarmView.animate()
.alpha(1f)
.setDuration(FADE_ANIMATION_DURATION_MS)
+ .setListener(null)
.start();
}
@@ -394,6 +401,8 @@
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
+ if (DEBUG) Log.d(TAG, "hideAlarmText: Hid alarm text");
+
// Reset the alpha regardless of how the animation ends for the next
// time we show this view/want to animate it.
mNextAlarmView.setVisibility(View.INVISIBLE);
@@ -443,4 +452,9 @@
.getBestDateTimePattern(Locale.getDefault(), skeleton);
return android.text.format.DateFormat.format(pattern, info.getTriggerTime()).toString();
}
+
+ public static float getColorIntensity(@ColorInt int color) {
+ return color == Color.WHITE ? 0 : 1;
+ }
+
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 66823ca..1cb89c4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -92,9 +92,10 @@
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int numTiles = mRecords.size();
final int width = MeasureSpec.getSize(widthMeasureSpec);
- final int rows = (numTiles + mColumns - 1) / mColumns;
+ final int numRows = (numTiles + mColumns - 1) / mColumns;
mCellWidth = (width - (mCellMarginHorizontal * (mColumns + 1))) / mColumns;
+ // Measure each QS tile.
View previousView = this;
for (TileRecord record : mRecords) {
if (record.tileView.getVisibility() == GONE) continue;
@@ -104,9 +105,10 @@
// Only include the top margin in our measurement if we have more than 1 row to show.
// Otherwise, don't add the extra margin buffer at top.
- int height = (mCellHeight + mCellMarginVertical) * rows +
- (rows != 0 ? (mCellMarginTop - mCellMarginVertical) : 0);
+ int height = (mCellHeight + mCellMarginVertical) * numRows +
+ (numRows != 0 ? (mCellMarginTop - mCellMarginVertical) : 0);
if (height < 0) height = 0;
+
setMeasuredDimension(width, height);
}
@@ -122,24 +124,30 @@
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int w = getWidth();
- boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+ final boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
int row = 0;
int column = 0;
+
+ // Layout each QS tile.
for (int i = 0; i < mRecords.size(); i++, column++) {
+ // If we reached the last column available to layout a tile, wrap back to the next row.
if (column == mColumns) {
+ column = 0;
row++;
- column -= mColumns;
}
- TileRecord record = mRecords.get(i);
- int left = getColumnStart(column);
+
+ final TileRecord record = mRecords.get(i);
final int top = getRowTop(row);
- int right;
+ final int right;
+ final int left;
if (isRtl) {
- right = w - left;
+ right = w - getColumnStart(column);
left = right - mCellWidth;
} else {
+ left = getColumnStart(column);
right = left + mCellWidth;
}
+
record.tileView.layout(left, top, right, top + record.tileView.getMeasuredHeight());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index 95504ed..89f86c5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -129,6 +129,7 @@
super.setBatteryLevel(MAX_BATTERY);
setPowerSave(true);
setCharging(false);
+ setPowerSaveAsColorError(false);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 0ce3e6a..b7a64e1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -18,18 +18,18 @@
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
import android.content.res.Resources;
-import android.os.SystemProperties;
+import android.provider.Settings;
import android.service.quicksettings.Tile;
+import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager.LayoutParams;
import android.widget.Switch;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.net.DataUsageController;
@@ -41,7 +41,6 @@
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile.SignalState;
import com.android.systemui.qs.CellTileView;
-import com.android.systemui.qs.CellTileView.SignalIcon;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.phone.SystemUIDialog;
@@ -52,16 +51,6 @@
/** Quick settings tile: Cellular **/
public class CellularTile extends QSTileImpl<SignalState> {
- private static final ComponentName CELLULAR_SETTING_COMPONENT = new ComponentName(
- "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity");
- private static final ComponentName DATA_PLAN_CELLULAR_COMPONENT = new ComponentName(
- "com.android.settings", "com.android.settings.Settings$DataPlanUsageSummaryActivity");
-
- private static final Intent CELLULAR_SETTINGS =
- new Intent().setComponent(CELLULAR_SETTING_COMPONENT);
- private static final Intent DATA_PLAN_CELLULAR_SETTINGS =
- new Intent().setComponent(DATA_PLAN_CELLULAR_COMPONENT);
-
private static final String ENABLE_SETTINGS_DATA_PLAN = "enable.settings.data.plan";
private final NetworkController mController;
@@ -107,7 +96,7 @@
@Override
public Intent getLongClickIntent() {
- return getCellularSettingIntent(mContext);
+ return getCellularSettingIntent();
}
@Override
@@ -148,8 +137,7 @@
showDetail(true);
} else {
mActivityStarter
- .postStartActivityDismissingKeyguard(getCellularSettingIntent(mContext),
- 0 /* delay */);
+ .postStartActivityDismissingKeyguard(getCellularSettingIntent(),0 /* delay */);
}
}
@@ -168,35 +156,43 @@
final Resources r = mContext.getResources();
state.activityIn = cb.enabled && cb.activityIn;
state.activityOut = cb.enabled && cb.activityOut;
- state.isOverlayIconWide = cb.isDataTypeIconWide;
- state.overlayIconId = cb.dataTypeIconId;
-
state.label = r.getString(R.string.mobile_data);
-
- final String signalContentDesc = cb.enabled && (cb.mobileSignalIconId > 0)
- ? cb.signalContentDescription
- : r.getString(R.string.accessibility_no_signal);
- if (cb.noSim) {
- state.contentDescription = state.label;
- } else {
- state.contentDescription = signalContentDesc + ", " + state.label;
- }
-
- state.expandedAccessibilityClassName = Switch.class.getName();
- state.value = mDataController.isMobileDataSupported()
+ boolean mobileDataEnabled = mDataController.isMobileDataSupported()
&& mDataController.isMobileDataEnabled();
-
+ state.value = mobileDataEnabled;
+ state.expandedAccessibilityClassName = Switch.class.getName();
if (cb.noSim) {
state.icon = ResourceIcon.get(R.drawable.ic_qs_no_sim);
} else {
- state.icon = new SignalIcon(cb.mobileSignalIconId);
+ state.icon = ResourceIcon.get(R.drawable.ic_swap_vert);
}
- if (cb.airplaneModeEnabled | cb.noSim) {
+ if (cb.noSim) {
state.state = Tile.STATE_UNAVAILABLE;
- } else {
+ state.secondaryLabel = r.getString(R.string.keyguard_missing_sim_message_short);
+ } else if (cb.airplaneModeEnabled) {
+ state.state = Tile.STATE_UNAVAILABLE;
+ state.secondaryLabel = r.getString(R.string.status_bar_airplane);
+ } else if (mobileDataEnabled) {
state.state = Tile.STATE_ACTIVE;
+ state.secondaryLabel = getMobileDataDescription(cb);
+ } else {
+ state.state = Tile.STATE_INACTIVE;
+ state.secondaryLabel = r.getString(R.string.cell_data_off);
}
+ state.contentDescription = state.label + ", " + state.secondaryLabel;
+ }
+
+ private CharSequence getMobileDataDescription(CallbackInfo cb) {
+ if (cb.roaming && !TextUtils.isEmpty(cb.dataContentDescription)) {
+ String roaming = mContext.getString(R.string.data_connection_roaming);
+ String dataDescription = cb.dataContentDescription;
+ return mContext.getString(R.string.mobile_data_text_format, roaming, dataDescription);
+ }
+ if (cb.roaming) {
+ return mContext.getString(R.string.data_connection_roaming);
+ }
+ return cb.dataContentDescription;
}
@Override
@@ -209,40 +205,18 @@
return mController.hasMobileDataFeature();
}
- // Remove the period from the network name
- public static String removeTrailingPeriod(String string) {
- if (string == null) return null;
- final int length = string.length();
- if (string.endsWith(".")) {
- return string.substring(0, length - 1);
- }
- return string;
- }
-
private static final class CallbackInfo {
boolean enabled;
- boolean wifiEnabled;
boolean airplaneModeEnabled;
- int mobileSignalIconId;
- String signalContentDescription;
- int dataTypeIconId;
String dataContentDescription;
boolean activityIn;
boolean activityOut;
- String enabledDesc;
boolean noSim;
- boolean isDataTypeIconWide;
boolean roaming;
}
private final class CellSignalCallback implements SignalCallback {
private final CallbackInfo mInfo = new CallbackInfo();
- @Override
- public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
- boolean activityIn, boolean activityOut, String description, boolean isTransient) {
- mInfo.wifiEnabled = enabled;
- refreshState(mInfo);
- }
@Override
public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
@@ -253,14 +227,9 @@
return;
}
mInfo.enabled = qsIcon.visible;
- mInfo.mobileSignalIconId = qsIcon.icon;
- mInfo.signalContentDescription = qsIcon.contentDescription;
- mInfo.dataTypeIconId = qsType;
mInfo.dataContentDescription = typeContentDescription;
mInfo.activityIn = activityIn;
mInfo.activityOut = activityOut;
- mInfo.enabledDesc = description;
- mInfo.isDataTypeIconWide = qsType != 0 && isWide;
mInfo.roaming = roaming;
refreshState(mInfo);
}
@@ -268,16 +237,6 @@
@Override
public void setNoSims(boolean show, boolean simDetected) {
mInfo.noSim = show;
- if (mInfo.noSim) {
- // Make sure signal gets cleared out when no sims.
- mInfo.mobileSignalIconId = 0;
- mInfo.dataTypeIconId = 0;
- // Show a No SIMs description to avoid emergency calls message.
- mInfo.enabled = true;
- mInfo.enabledDesc = mContext.getString(
- R.string.keyguard_missing_sim_message_short);
- mInfo.signalContentDescription = mInfo.enabledDesc;
- }
refreshState(mInfo);
}
@@ -293,25 +252,8 @@
}
}
- static Intent getCellularSettingIntent(Context context) {
- // TODO(b/62349208): We should replace feature flag check below with data plans
- // availability check. If the data plans are available we display the data plans usage
- // summary otherwise we display data usage summary without data plans.
- boolean isDataPlanFeatureEnabled =
- SystemProperties.getBoolean(ENABLE_SETTINGS_DATA_PLAN, false /* default */);
- context.getPackageManager()
- .setComponentEnabledSetting(
- DATA_PLAN_CELLULAR_COMPONENT,
- isDataPlanFeatureEnabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
- : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP);
- context.getPackageManager()
- .setComponentEnabledSetting(
- CELLULAR_SETTING_COMPONENT,
- isDataPlanFeatureEnabled ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
- : PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
- PackageManager.DONT_KILL_APP);
- return isDataPlanFeatureEnabled ? DATA_PLAN_CELLULAR_SETTINGS : CELLULAR_SETTINGS;
+ static Intent getCellularSettingIntent() {
+ return new Intent(Settings.ACTION_DATA_USAGE_SETTINGS);
}
private final class CellularDetailAdapter implements DetailAdapter {
@@ -330,7 +272,7 @@
@Override
public Intent getSettingsIntent() {
- return getCellularSettingIntent(mContext);
+ return getCellularSettingIntent();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
index a102696..ace361b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -55,7 +55,7 @@
@Override
public Intent getLongClickIntent() {
- return CellularTile.getCellularSettingIntent(mContext);
+ return CellularTile.getCellularSettingIntent();
}
@Override
protected void handleClick() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 2d31669..f3a2ae3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -19,6 +19,7 @@
import static android.provider.Settings.Global.ZEN_MODE_ALARMS;
import static android.provider.Settings.Global.ZEN_MODE_OFF;
+import android.app.ActivityManager;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -28,6 +29,7 @@
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.net.Uri;
import android.os.UserManager;
import android.provider.Settings;
import android.provider.Settings.Global;
@@ -139,15 +141,29 @@
@Override
public void showDetail(boolean show) {
- mUiHandler.post(() -> {
- Dialog mDialog = new EnableZenModeDialog(mContext).createDialog();
- mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- SystemUIDialog.setShowForAllUsers(mDialog, true);
- SystemUIDialog.registerDismissListener(mDialog);
- SystemUIDialog.setWindowOnTop(mDialog);
- mUiHandler.post(() -> mDialog.show());
- mHost.collapsePanels();
- });
+ int zenDuration = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.ZEN_DURATION, 0);
+ switch (zenDuration) {
+ case Settings.Global.ZEN_DURATION_PROMPT:
+ mUiHandler.post(() -> {
+ Dialog mDialog = new EnableZenModeDialog(mContext).createDialog();
+ mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+ SystemUIDialog.setShowForAllUsers(mDialog, true);
+ SystemUIDialog.registerDismissListener(mDialog);
+ SystemUIDialog.setWindowOnTop(mDialog);
+ mUiHandler.post(() -> mDialog.show());
+ mHost.collapsePanels();
+ });
+ break;
+ case Settings.Global.ZEN_DURATION_FOREVER:
+ mController.setZen(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG);
+ break;
+ default:
+ Uri conditionId = ZenModeConfig.toTimeCondition(mContext, zenDuration,
+ ActivityManager.getCurrentUser(), true).id;
+ mController.setZen(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ conditionId, TAG);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index d675f5e..00d6bd0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -19,7 +19,6 @@
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Intent;
-import android.content.IntentFilter;
import android.os.UserManager;
import android.provider.Settings.Global;
import android.service.quicksettings.Tile;
@@ -32,24 +31,27 @@
import com.android.systemui.qs.GlobalSetting;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.HotspotController;
/** Quick settings tile: Hotspot **/
public class HotspotTile extends QSTileImpl<AirplaneBooleanState> {
- static final Intent TETHER_SETTINGS = new Intent().setComponent(new ComponentName(
+ private static final Intent TETHER_SETTINGS = new Intent().setComponent(new ComponentName(
"com.android.settings", "com.android.settings.TetherSettings"));
private final Icon mEnabledStatic = ResourceIcon.get(R.drawable.ic_hotspot);
- private final Icon mUnavailable = ResourceIcon.get(R.drawable.ic_hotspot_unavailable);
- private final HotspotController mController;
- private final Callback mCallback = new Callback();
+ private final HotspotController mHotspotController;
+ private final DataSaverController mDataSaverController;
+
+ private final HotspotAndDataSaverCallbacks mCallbacks = new HotspotAndDataSaverCallbacks();
private final GlobalSetting mAirplaneMode;
private boolean mListening;
public HotspotTile(QSHost host) {
super(host);
- mController = Dependency.get(HotspotController.class);
+ mHotspotController = Dependency.get(HotspotController.class);
+ mDataSaverController = Dependency.get(DataSaverController.class);
mAirplaneMode = new GlobalSetting(mContext, mHandler, Global.AIRPLANE_MODE_ON) {
@Override
protected void handleValueChanged(int value) {
@@ -60,7 +62,7 @@
@Override
public boolean isAvailable() {
- return mController.isHotspotSupported();
+ return mHotspotController.isHotspotSupported();
}
@Override
@@ -78,12 +80,12 @@
if (mListening == listening) return;
mListening = listening;
if (listening) {
- mController.addCallback(mCallback);
- final IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ mHotspotController.addCallback(mCallbacks);
+ mDataSaverController.addCallback(mCallbacks);
refreshState();
} else {
- mController.removeCallback(mCallback);
+ mHotspotController.removeCallback(mCallbacks);
+ mDataSaverController.removeCallback(mCallbacks);
}
mAirplaneMode.setListening(listening);
}
@@ -101,7 +103,7 @@
}
// Immediately enter transient enabling state when turning hotspot on.
refreshState(isEnabled ? null : ARG_SHOW_TRANSIENT_ENABLING);
- mController.setHotspotEnabled(!isEnabled);
+ mHotspotController.setHotspotEnabled(!isEnabled);
}
@Override
@@ -117,21 +119,24 @@
}
final int numConnectedDevices;
- final boolean isTransient = transientEnabling || mController.isHotspotTransient();
+ final boolean isTransient = transientEnabling || mHotspotController.isHotspotTransient();
+ final boolean isDataSaverEnabled;
checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_CONFIG_TETHERING);
+
if (arg instanceof CallbackInfo) {
- CallbackInfo info = (CallbackInfo) arg;
- state.value = info.enabled;
+ final CallbackInfo info = (CallbackInfo) arg;
+ state.value = transientEnabling || info.isHotspotEnabled;
numConnectedDevices = info.numConnectedDevices;
+ isDataSaverEnabled = info.isDataSaverEnabled;
} else {
- state.value = transientEnabling || mController.isHotspotEnabled();
- numConnectedDevices = mController.getNumConnectedDevices();
+ state.value = transientEnabling || mHotspotController.isHotspotEnabled();
+ numConnectedDevices = mHotspotController.getNumConnectedDevices();
+ isDataSaverEnabled = mDataSaverController.isDataSaverEnabled();
}
state.icon = mEnabledStatic;
state.label = mContext.getString(R.string.quick_settings_hotspot_label);
- state.secondaryLabel = getSecondaryLabel(state.value, isTransient, numConnectedDevices);
state.isAirplaneMode = mAirplaneMode.getValue() != 0;
state.isTransient = isTransient;
state.slash.isSlashed = !state.value && !state.isTransient;
@@ -140,16 +145,29 @@
}
state.expandedAccessibilityClassName = Switch.class.getName();
state.contentDescription = state.label;
- state.state = state.isAirplaneMode ? Tile.STATE_UNAVAILABLE
- : state.value || state.isTransient ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
+
+ final boolean isTileUnavailable = (state.isAirplaneMode || isDataSaverEnabled);
+ final boolean isTileActive = (state.value || state.isTransient);
+
+ if (isTileUnavailable) {
+ state.state = Tile.STATE_UNAVAILABLE;
+ } else {
+ state.state = isTileActive ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
+ }
+
+ state.secondaryLabel = getSecondaryLabel(
+ isTileActive, isTransient, isDataSaverEnabled, numConnectedDevices);
}
@Nullable
- private String getSecondaryLabel(
- boolean enabled, boolean isTransient, int numConnectedDevices) {
+ private String getSecondaryLabel(boolean isActive, boolean isTransient,
+ boolean isDataSaverEnabled, int numConnectedDevices) {
if (isTransient) {
return mContext.getString(R.string.quick_settings_hotspot_secondary_label_transient);
- } else if (numConnectedDevices > 0 && enabled) {
+ } else if (isDataSaverEnabled) {
+ return mContext.getString(
+ R.string.quick_settings_hotspot_secondary_label_data_saver_enabled);
+ } else if (numConnectedDevices > 0 && isActive) {
return mContext.getResources().getQuantityString(
R.plurals.quick_settings_hotspot_secondary_label_num_devices,
numConnectedDevices,
@@ -173,13 +191,23 @@
}
}
- private final class Callback implements HotspotController.Callback {
- final CallbackInfo mCallbackInfo = new CallbackInfo();
+ /**
+ * Listens to changes made to hotspot and data saver states (to toggle tile availability).
+ */
+ private final class HotspotAndDataSaverCallbacks implements HotspotController.Callback,
+ DataSaverController.Listener {
+ CallbackInfo mCallbackInfo = new CallbackInfo();
@Override
- public void onHotspotChanged(boolean enabled, int numConnectedDevices) {
- mCallbackInfo.enabled = enabled;
- mCallbackInfo.numConnectedDevices = numConnectedDevices;
+ public void onDataSaverChanged(boolean isDataSaving) {
+ mCallbackInfo.isDataSaverEnabled = isDataSaving;
+ refreshState(mCallbackInfo);
+ }
+
+ @Override
+ public void onHotspotChanged(boolean enabled, int numDevices) {
+ mCallbackInfo.isHotspotEnabled = enabled;
+ mCallbackInfo.numConnectedDevices = numDevices;
refreshState(mCallbackInfo);
}
}
@@ -189,14 +217,16 @@
* {@link #handleUpdateState(State, Object)}.
*/
protected static final class CallbackInfo {
- boolean enabled;
+ boolean isHotspotEnabled;
int numConnectedDevices;
+ boolean isDataSaverEnabled;
@Override
public String toString() {
return new StringBuilder("CallbackInfo[")
- .append("enabled=").append(enabled)
+ .append("isHotspotEnabled=").append(isHotspotEnabled)
.append(",numConnectedDevices=").append(numConnectedDevices)
+ .append(",isDataSaverEnabled=").append(isDataSaverEnabled)
.append(']').toString();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 055e72e..ac26f68 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -26,6 +26,7 @@
import android.app.ActivityOptions;
import android.app.trust.TrustManager;
import android.content.ActivityNotFoundException;
+import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
@@ -45,6 +46,8 @@
import android.widget.Toast;
+import com.android.systemui.Dependency;
+import com.android.systemui.OverviewProxyService;
import com.google.android.collect.Lists;
import com.android.internal.logging.MetricsLogger;
@@ -122,6 +125,11 @@
@Override
public void onTaskStackChangedBackground() {
+ // Skip background preloading recents in SystemUI if the overview services is bound
+ if (Dependency.get(OverviewProxyService.class).getProxy() != null) {
+ return;
+ }
+
// Check this is for the right user
if (!checkCurrentUserId(mContext, false /* debug */)) {
return;
@@ -257,6 +265,17 @@
}
});
+ private OverviewProxyService.OverviewProxyListener mOverviewProxyListener =
+ new OverviewProxyService.OverviewProxyListener() {
+ @Override
+ public void onConnectionChanged(boolean isConnected) {
+ if (!isConnected) {
+ // Clear everything when the connection to the overview service
+ Recents.getTaskLoader().onTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
+ }
+ }
+ };
+
public RecentsImpl(Context context) {
mContext = context;
mHandler = new Handler();
@@ -277,6 +296,11 @@
}
public void onBootCompleted() {
+ // Skip preloading tasks if we are already bound to the service
+ if (Dependency.get(OverviewProxyService.class).getProxy() != null) {
+ return;
+ }
+
// When we start, preload the data associated with the previous recent tasks.
// We can use a new plan since the caches will be the same.
RecentsTaskLoader loader = Recents.getTaskLoader();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index d9359a4..c348187 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -189,7 +189,7 @@
}
}
- public void onRecentsAnimationStarted() {
+ public void onQuickStepStarted() {
boolean alreadySeenRecentsOnboarding = Prefs.getBoolean(mContext,
Prefs.Key.HAS_SEEN_RECENTS_ONBOARDING, false);
if (!alreadySeenRecentsOnboarding) {
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 406eef8..f2a7adf 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -368,7 +368,9 @@
} else {
final int val = value + mMinimumBacklight;
if (stopTracking) {
- MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS, val);
+ final int metric = mAutomatic ?
+ MetricsEvent.ACTION_BRIGHTNESS_AUTO : MetricsEvent.ACTION_BRIGHTNESS;
+ MetricsLogger.action(mContext, metric, val);
}
setBrightness(val);
if (!tracking) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index bc14203..859dc39 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -58,6 +58,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.text.NumberFormat;
+import java.util.IllegalFormatConversionException;
/**
* Controls the indications and error messages shown on the Keyguard
@@ -414,11 +415,24 @@
String percentage = NumberFormat.getPercentInstance()
.format(mBatteryLevel / 100f);
if (hasChargingTime) {
+ // We now have battery percentage in these strings and it's expected that all
+ // locales will also have it in the future. For now, we still have to support the old
+ // format until all languages get the new translations.
String chargingTimeFormatted = Formatter.formatShortElapsedTimeRoundingUpToMinutes(
mContext, chargingTimeRemaining);
- return mContext.getResources().getString(chargingId, chargingTimeFormatted, percentage);
+ try {
+ return mContext.getResources().getString(chargingId, chargingTimeFormatted,
+ percentage);
+ } catch (IllegalFormatConversionException e) {
+ return mContext.getResources().getString(chargingId, chargingTimeFormatted);
+ }
} else {
- return mContext.getResources().getString(chargingId, percentage);
+ // Same as above
+ try {
+ return mContext.getResources().getString(chargingId, percentage);
+ } catch (IllegalFormatConversionException e) {
+ return mContext.getResources().getString(chargingId);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index d53cb03..22a186f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -16,6 +16,13 @@
package com.android.systemui.statusbar;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
+
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.Notification;
@@ -445,20 +452,47 @@
return Ranking.VISIBILITY_NO_OVERRIDE;
}
- public boolean shouldSuppressScreenOff(String key) {
+ public boolean shouldSuppressFullScreenIntent(String key) {
if (mRankingMap != null) {
getRanking(key, mTmpRanking);
return (mTmpRanking.getSuppressedVisualEffects()
- & NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_OFF) != 0;
+ & SUPPRESSED_EFFECT_FULL_SCREEN_INTENT) != 0;
}
return false;
}
- public boolean shouldSuppressScreenOn(String key) {
+ public boolean shouldSuppressPeek(String key) {
if (mRankingMap != null) {
getRanking(key, mTmpRanking);
return (mTmpRanking.getSuppressedVisualEffects()
- & NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_ON) != 0;
+ & SUPPRESSED_EFFECT_PEEK) != 0;
+ }
+ return false;
+ }
+
+ public boolean shouldSuppressStatusBar(String key) {
+ if (mRankingMap != null) {
+ getRanking(key, mTmpRanking);
+ return (mTmpRanking.getSuppressedVisualEffects()
+ & SUPPRESSED_EFFECT_STATUS_BAR) != 0;
+ }
+ return false;
+ }
+
+ public boolean shouldSuppressAmbient(String key) {
+ if (mRankingMap != null) {
+ getRanking(key, mTmpRanking);
+ return (mTmpRanking.getSuppressedVisualEffects()
+ & SUPPRESSED_EFFECT_AMBIENT) != 0;
+ }
+ return false;
+ }
+
+ public boolean shouldSuppressNotificationList(String key) {
+ if (mRankingMap != null) {
+ getRanking(key, mTmpRanking);
+ return (mTmpRanking.getSuppressedVisualEffects()
+ & SUPPRESSED_EFFECT_NOTIFICATION_LIST) != 0;
}
return false;
}
@@ -576,6 +610,14 @@
return true;
}
+ if (mEnvironment.isDozing() && shouldSuppressAmbient(sbn.getKey())) {
+ return true;
+ }
+
+ if (!mEnvironment.isDozing() && shouldSuppressNotificationList(sbn.getKey())) {
+ return true;
+ }
+
if (!StatusBar.ENABLE_CHILD_NOTIFICATIONS
&& mGroupManager.isChildInGroupWithSummary(sbn)) {
return true;
@@ -670,5 +712,9 @@
public boolean isNotificationForCurrentProfiles(StatusBarNotification sbn);
public String getCurrentMediaNotificationKey();
public NotificationGroupManager getGroupManager();
+ /**
+ * @return true iff the device is dozing
+ */
+ boolean isDozing();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
index 146de00..48828ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
@@ -304,11 +304,7 @@
return true;
}
- if (mPowerManager.isInteractive()) {
- return mNotificationData.shouldSuppressScreenOn(key);
- } else {
- return mNotificationData.shouldSuppressScreenOff(key);
- }
+ return mNotificationData.shouldSuppressFullScreenIntent(key);
}
private void inflateViews(NotificationData.Entry entry, ViewGroup parent) {
@@ -849,12 +845,13 @@
return false;
}
- if (!mPresenter.isDozing() && mNotificationData.shouldSuppressScreenOn(sbn.getKey())) {
+ if (!mPresenter.isDozing() && mNotificationData.shouldSuppressPeek(sbn.getKey())) {
if (DEBUG) Log.d(TAG, "No peeking: suppressed by DND: " + sbn.getKey());
return false;
}
- if (mPresenter.isDozing() && mNotificationData.shouldSuppressScreenOff(sbn.getKey())) {
+ // Peeking triggers an ambient display pulse, so disable peek is ambient is active
+ if (mPresenter.isDozing() && mNotificationData.shouldSuppressAmbient(sbn.getKey())) {
if (DEBUG) Log.d(TAG, "No peeking: suppressed by DND: " + sbn.getKey());
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index afe906c..b1ad30c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar;
+import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import android.animation.Animator;
@@ -39,6 +40,7 @@
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
+import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -73,6 +75,7 @@
private boolean mNonblockable;
private StatusBarNotification mSbn;
private AnimatorSet mExpandAnimation;
+ private boolean mIsForeground;
private CheckSaveListener mCheckSaveListener;
private OnSettingsClickListener mOnSettingsClickListener;
@@ -84,7 +87,7 @@
closeControls(v);
};
- private OnClickListener mOnStopNotifications = v -> {
+ private OnClickListener mOnStopMinNotifications = v -> {
swapContent(false);
};
@@ -150,6 +153,8 @@
mSingleNotificationChannel = notificationChannel;
mStartingUserImportance = mChosenImportance = mSingleNotificationChannel.getImportance();
mNegativeUserSentiment = negativeUserSentiment;
+ mIsForeground =
+ (mSbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
pkg, mAppUid, false /* includeDeleted */);
@@ -290,14 +295,23 @@
private void bindButtons() {
View block = findViewById(R.id.block);
- block.setOnClickListener(mOnStopNotifications);
+ block.setOnClickListener(mOnStopMinNotifications);
TextView keep = findViewById(R.id.keep);
keep.setOnClickListener(mOnKeepShowing);
findViewById(R.id.undo).setOnClickListener(mOnUndo);
+ View minimize = findViewById(R.id.minimize);
+ minimize.setOnClickListener(mOnStopMinNotifications);
if (mNonblockable) {
keep.setText(R.string.notification_done);
block.setVisibility(GONE);
+ minimize.setVisibility(GONE);
+ } else if (mIsForeground) {
+ block.setVisibility(GONE);
+ minimize.setVisibility(VISIBLE);
+ } else if (!mIsForeground) {
+ block.setVisibility(VISIBLE);
+ minimize.setVisibility(GONE);
}
// app settings link
@@ -306,7 +320,7 @@
mSbn.getId(), mSbn.getTag());
if (settingsIntent != null
&& !TextUtils.isEmpty(mSbn.getNotification().getSettingsText())) {
- settingsLinkView.setVisibility(View.VISIBLE);
+ settingsLinkView.setVisibility(VISIBLE);
settingsLinkView.setText(mContext.getString(R.string.notification_app_settings,
mSbn.getNotification().getSettingsText()));
settingsLinkView.setOnClickListener((View view) -> {
@@ -322,14 +336,21 @@
mExpandAnimation.cancel();
}
+ View prompt = findViewById(R.id.prompt);
+ ViewGroup confirmation = findViewById(R.id.confirmation);
+ TextView confirmationText = findViewById(R.id.confirmation_text);
+ View header = findViewById(R.id.header);
+
if (showPrompt) {
mChosenImportance = mStartingUserImportance;
+ } else if (mIsForeground) {
+ mChosenImportance = IMPORTANCE_MIN;
+ confirmationText.setText(R.string.notification_channel_minimized);
} else {
mChosenImportance = IMPORTANCE_NONE;
+ confirmationText.setText(R.string.notification_channel_disabled);
}
- View prompt = findViewById(R.id.prompt);
- View confirmation = findViewById(R.id.confirmation);
ObjectAnimator promptAnim = ObjectAnimator.ofFloat(prompt, View.ALPHA,
prompt.getAlpha(), showPrompt ? 1f : 0f);
promptAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
@@ -339,6 +360,7 @@
prompt.setVisibility(showPrompt ? VISIBLE : GONE);
confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
+ header.setVisibility(showPrompt ? VISIBLE : GONE);
mExpandAnimation = new AnimatorSet();
mExpandAnimation.playTogether(promptAnim, confirmAnim);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
index 5263bb4..21d3d81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
@@ -101,11 +101,6 @@
void updateNotificationViews();
/**
- * @return true iff the device is dozing
- */
- boolean isDozing();
-
- /**
* Returns the maximum number of notifications to show while locked.
*
* @param recompute whether something has changed that means we should recompute this value
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
new file mode 100644
index 0000000..5c21fd1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
+import android.provider.Settings;
+
+public class VibratorHelper {
+
+ private final Vibrator mVibrator;
+ private final Context mContext;
+ private boolean mHapticFeedbackEnabled;
+
+ final private ContentObserver mVibrationObserver = new ContentObserver(Handler.getMain()) {
+ @Override
+ public void onChange(boolean selfChange) {
+ updateHapticFeedBackEnabled();
+ }
+ };
+
+ public VibratorHelper(Context context) {
+ mContext = context;
+ mVibrator = context.getSystemService(Vibrator.class);
+
+ mContext.getContentResolver().registerContentObserver(
+ Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_ENABLED), true,
+ mVibrationObserver);
+ mVibrationObserver.onChange(false /* selfChange */);
+ }
+
+ public void vibrate(final int effectId) {
+ if (mHapticFeedbackEnabled) {
+ AsyncTask.execute(() ->
+ mVibrator.vibrate(VibrationEffect.get(effectId, false /* fallback */)));
+ }
+ }
+
+ private void updateHapticFeedBackEnabled() {
+ mHapticFeedbackEnabled = Settings.System.getIntForUser(mContext.getContentResolver(),
+ Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) != 0;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index 3ec8913..bc353f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -19,7 +19,6 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.res.Resources;
-import android.os.CountDownTimer;
import android.view.View;
import android.view.ViewStub;
import android.widget.ProgressBar;
@@ -36,16 +35,11 @@
private final View mParent;
private final UserGridView mUserGridView;
private final UserSwitcherController mUserSwitcherController;
- private final ProgressBar mProgressBar;
private final ProgressBar mSwitchingUsers;
- private final int mLoginTimeoutMs;
- private final int mAnimUpdateIntervalMs;
private final int mShortAnimDuration;
private boolean mShowing;
- private CountDownTimer mTimer;
-
public FullscreenUserSwitcher(StatusBar statusBar,
UserSwitcherController userSwitcherController,
ViewStub containerStub) {
@@ -63,26 +57,13 @@
PageIndicator pageIndicator = mContainer.findViewById(R.id.user_switcher_page_indicator);
pageIndicator.setupWithViewPager(mUserGridView);
- mProgressBar = mContainer.findViewById(R.id.countdown_progress);
Resources res = mContainer.getResources();
- mLoginTimeoutMs = res.getInteger(R.integer.car_user_switcher_timeout_ms);
- mAnimUpdateIntervalMs = res.getInteger(R.integer.car_user_switcher_anim_update_ms);
mShortAnimDuration = res.getInteger(android.R.integer.config_shortAnimTime);
mContainer.findViewById(R.id.start_driving).setOnClickListener(v -> {
- cancelTimer();
automaticallySelectUser();
});
- // Any interaction with the screen should cancel the timer.
- mContainer.setOnClickListener(v -> {
- cancelTimer();
- });
- mUserGridView.setOnTouchListener((v, e) -> {
- cancelTimer();
- return false;
- });
-
mSwitchingUsers = mParent.findViewById(R.id.switching_users);
}
@@ -127,44 +108,14 @@
}
mShowing = true;
mParent.setVisibility(View.VISIBLE);
- cancelTimer();
-
- // This would be the case if we were in the middle of a switch.
- if (mProgressBar.getVisibility() != View.VISIBLE) {
- return;
- }
-
- mTimer = new CountDownTimer(mLoginTimeoutMs, mAnimUpdateIntervalMs) {
- @Override
- public void onTick(long msUntilFinished) {
- int elapsed = mLoginTimeoutMs - (int) msUntilFinished;
- mProgressBar.setProgress((int) elapsed, true /* animate */);
- }
-
- @Override
- public void onFinish() {
- mProgressBar.setProgress(mLoginTimeoutMs, true /* animate */);
- automaticallySelectUser();
- }
- };
- mTimer.start();
}
public void hide() {
mShowing = false;
- cancelTimer();
toggleSwitchInProgress(false);
mParent.setVisibility(View.GONE);
}
- private void cancelTimer() {
- if (mTimer != null) {
- mTimer.cancel();
- mTimer = null;
- mProgressBar.setProgress(0, true /* animate */);
- }
- }
-
private void automaticallySelectUser() {
// TODO: Switch according to some policy. This implementation just tries to drop the
// keyguard for the current user.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index ca66e98..0716b37 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -55,6 +55,7 @@
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
@@ -912,4 +913,16 @@
return (secure && !canSkipBouncer) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
}
}
+
+ @Override
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ int bottom = insets.getDisplayCutout() != null
+ ? insets.getDisplayCutout().getSafeInsetBottom() : 0;
+ if (isPaddingRelative()) {
+ setPaddingRelative(getPaddingStart(), getPaddingTop(), getPaddingEnd(), bottom);
+ } else {
+ setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), bottom);
+ }
+ return insets;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index edfbd3f..010b165 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -20,6 +20,7 @@
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.MathUtils;
import android.util.Slog;
import android.util.StatsLog;
import android.view.KeyEvent;
@@ -49,7 +50,8 @@
*/
public class KeyguardBouncer {
- final static private String TAG = "KeyguardBouncer";
+ private static final String TAG = "KeyguardBouncer";
+ static final float ALPHA_EXPANSION_THRESHOLD = 0.95f;
protected final Context mContext;
protected final ViewMediatorCallback mCallback;
@@ -86,13 +88,25 @@
}
public void show(boolean resetSecuritySelection) {
+ show(resetSecuritySelection, true /* notifyFalsing */);
+ }
+
+ public void show(boolean resetSecuritySelection, boolean notifyFalsing) {
final int keyguardUserId = KeyguardUpdateMonitor.getCurrentUser();
if (keyguardUserId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser()) {
// In split system user mode, we never unlock system user.
return;
}
- mFalsingManager.onBouncerShown();
ensureView();
+
+ // On the keyguard, we want to show the bouncer when the user drags up, but it's
+ // not correct to end the falsing session. We still need to verify if those touches
+ // are valid.
+ // Later, at the end of the animation, when the bouncer is at the top of the screen,
+ // onFullyShown() will be called and FalsingManager will stop recording touches.
+ if (notifyFalsing) {
+ mFalsingManager.onBouncerShown();
+ }
if (resetSecuritySelection) {
// showPrimarySecurityScreen() updates the current security method. This is needed in
// case we are already showing and the current security method changed.
@@ -126,6 +140,28 @@
mCallback.onBouncerVisiblityChanged(true /* shown */);
}
+ /**
+ * This method must be called at the end of the bouncer animation when
+ * the translation is performed manually by the user, otherwise FalsingManager
+ * will never be notified and its internal state will be out of sync.
+ */
+ public void onFullyShown() {
+ mFalsingManager.onBouncerShown();
+ }
+
+ /**
+ * This method must be called at the end of the bouncer animation when
+ * the translation is performed manually by the user, otherwise FalsingManager
+ * will never be notified and its internal state will be out of sync.
+ */
+ public void onFullyHidden() {
+ if (!mShowingSoon) {
+ cancelShowRunnable();
+ mRoot.setVisibility(View.INVISIBLE);
+ mFalsingManager.onBouncerHidden();
+ }
+ }
+
private final Runnable mShowRunnable = new Runnable() {
@Override
public void run() {
@@ -247,6 +283,18 @@
mBouncerPromptReason = mCallback.getBouncerPromptReason();
}
+ /**
+ * Current notification panel expansion
+ * @param fraction 0 when notification panel is collapsed and 1 when expanded.
+ * @see StatusBarKeyguardViewManager#onPanelExpansionChanged
+ */
+ public void setExpansion(float fraction) {
+ if (mKeyguardView != null) {
+ mKeyguardView.setAlpha(MathUtils.map(ALPHA_EXPANSION_THRESHOLD, 1, 1, 0, fraction));
+ mKeyguardView.setTranslationY(fraction * mKeyguardView.getHeight());
+ }
+ }
+
protected void ensureView() {
// Removal of the view might be deferred to reduce unlock latency,
// in this case we need to force the removal, otherwise we'll
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 0cf26df..1bd5e33 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -79,14 +79,9 @@
private int mMaxShadeBottom;
/**
- * Margin that we should respect within the available space.
+ * Minimum distance from the status bar.
*/
- private int mContainerPadding;
-
- /**
- * Position where clock should be when the panel is collapsed.
- */
- private int mClockYTarget;
+ private int mContainerTopPadding;
/**
* @see NotificationPanelView#getMaxPanelHeight()
@@ -109,12 +104,22 @@
private float mDarkAmount;
/**
+ * If keyguard will require a password or just fade away.
+ */
+ private boolean mCurrentlySecure;
+
+ /**
+ * If notification panel view currently has a touch.
+ */
+ private boolean mTracking;
+
+ /**
* Refreshes the dimension values.
*/
public void loadDimens(Resources res) {
mClockNotificationsMargin = res.getDimensionPixelSize(
R.dimen.keyguard_clock_notifications_margin);
- mContainerPadding = res.getDimensionPixelSize(
+ mContainerTopPadding = res.getDimensionPixelSize(
R.dimen.keyguard_clock_top_margin);
mBurnInPreventionOffsetX = res.getDimensionPixelSize(
R.dimen.burn_in_prevention_offset_x);
@@ -124,8 +129,8 @@
public void setup(int minTopMargin, int maxShadeBottom, int notificationStackHeight,
float expandedHeight, float maxPanelHeight, int parentHeight, int keyguardStatusHeight,
- float dark) {
- mMinTopMargin = minTopMargin;
+ float dark, boolean secure, boolean tracking) {
+ mMinTopMargin = minTopMargin + mContainerTopPadding;
mMaxShadeBottom = maxShadeBottom;
mNotificationStackHeight = notificationStackHeight;
mExpandedHeight = expandedHeight;
@@ -133,13 +138,8 @@
mHeight = parentHeight;
mKeyguardStatusHeight = keyguardStatusHeight;
mDarkAmount = dark;
-
- // Where the clock should stop when swiping up.
- // This should be outside of the display when unlocked or
- // under then status bar when the bouncer will be shown
- mClockYTarget = -mKeyguardStatusHeight;
- // TODO: on bouncer animation follow-up CL
- // mClockYTarget = mMinTopMargin + mContainerPadding;
+ mCurrentlySecure = secure;
+ mTracking = tracking;
}
public void run(Result result) {
@@ -173,8 +173,8 @@
float y = containerCenter - mKeyguardStatusHeight * CLOCK_HEIGHT_WEIGHT
- mClockNotificationsMargin - mNotificationStackHeight / 2;
- if (y < mMinTopMargin + mContainerPadding) {
- y = mMinTopMargin + mContainerPadding;
+ if (y < mMinTopMargin) {
+ y = mMinTopMargin;
}
// Don't allow the clock base to be under half of the screen
@@ -190,18 +190,32 @@
// Dark: Align the bottom edge of the clock at about half of the screen:
final float clockYDark = getMaxClockY() + burnInPreventionOffsetY();
float clockYRegular = getExpandedClockPosition();
+ float clockYTarget = mCurrentlySecure ? mMinTopMargin : -mKeyguardStatusHeight;
// Move clock up while collapsing the shade
final float shadeExpansion = mExpandedHeight / mMaxPanelHeight;
- final float clockY = MathUtils.lerp(mClockYTarget, clockYRegular, shadeExpansion);
+ final float clockY = MathUtils.lerp(clockYTarget, clockYRegular, shadeExpansion);
return (int) MathUtils.lerp(clockY, clockYDark, mDarkAmount);
}
+ /**
+ * We might want to fade out the clock when the user is swiping up.
+ * One exception is when the bouncer will become visible, in this cause the clock
+ * should always persist.
+ *
+ * @param y Current clock Y.
+ * @return Alpha from 0 to 1.
+ */
private float getClockAlpha(int y) {
- float alphaKeyguard = Math.max(0, Math.min(1, (y - mMinTopMargin)
- / Math.max(1f, getExpandedClockPosition() - mMinTopMargin)));
- alphaKeyguard = Interpolators.ACCELERATE.getInterpolation(alphaKeyguard);
+ float alphaKeyguard;
+ if (mCurrentlySecure) {
+ alphaKeyguard = 1;
+ } else {
+ alphaKeyguard = Math.max(0, Math.min(1, (y - mMinTopMargin)
+ / Math.max(1f, getExpandedClockPosition() - mMinTopMargin)));
+ alphaKeyguard = Interpolators.ACCELERATE.getInterpolation(alphaKeyguard);
+ }
return MathUtils.lerp(alphaKeyguard, 1f, mDarkAmount);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index c5269ad..bb929dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -16,34 +16,35 @@
package com.android.systemui.statusbar.phone;
+import static com.android.systemui.ScreenDecorations.DisplayCutoutView.boundsFromDirection;
+
import android.annotation.ColorInt;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.DisplayCutout;
+import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
import android.view.ViewTreeObserver;
+import android.view.WindowInsets;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
-import com.android.internal.statusbar.StatusBarIcon;
import com.android.settingslib.Utils;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.ScreenDecorations;
import com.android.systemui.qs.QSPanel;
-import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
@@ -210,18 +211,26 @@
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
- private void updateLayoutConsideringCutout() {
+ @Override
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ if (updateLayoutConsideringCutout()) {
+ requestLayout();
+ }
+ return super.onApplyWindowInsets(insets);
+ }
+
+ private boolean updateLayoutConsideringCutout() {
DisplayCutout dc = getRootWindowInsets().getDisplayCutout();
if (dc == null) {
- updateLayoutParamsNoCutout();
+ return updateLayoutParamsNoCutout();
} else {
- updateLayoutParamsForCutout(dc);
+ return updateLayoutParamsForCutout(dc);
}
}
- private void updateLayoutParamsNoCutout() {
+ private boolean updateLayoutParamsNoCutout() {
if (mLayoutState == LAYOUT_NO_CUTOUT) {
- return;
+ return false;
}
mLayoutState = LAYOUT_NO_CUTOUT;
@@ -240,11 +249,12 @@
(LinearLayout.LayoutParams) mSystemIconsContainer.getLayoutParams();
llp.setMarginStart(getResources().getDimensionPixelSize(
R.dimen.system_icons_super_container_margin_start));
+ return true;
}
- private void updateLayoutParamsForCutout(DisplayCutout dc) {
+ private boolean updateLayoutParamsForCutout(DisplayCutout dc) {
if (mLayoutState == LAYOUT_CUTOUT) {
- return;
+ return false;
}
mLayoutState = LAYOUT_CUTOUT;
@@ -252,10 +262,13 @@
updateLayoutParamsNoCutout();
}
+ Rect bounds = new Rect();
+ boundsFromDirection(dc, Gravity.TOP, bounds);
+
mCutoutSpace.setVisibility(View.VISIBLE);
RelativeLayout.LayoutParams lp = (LayoutParams) mCutoutSpace.getLayoutParams();
- lp.width = dc.getBoundingRect().width();
- lp.height = dc.getBoundingRect().height();
+ lp.width = bounds.width();
+ lp.height = bounds.height();
lp.addRule(RelativeLayout.CENTER_IN_PARENT);
lp = (LayoutParams) mCarrierLabel.getLayoutParams();
@@ -268,6 +281,7 @@
LinearLayout.LayoutParams llp =
(LinearLayout.LayoutParams) mSystemIconsContainer.getLayoutParams();
llp.setMarginStart(0);
+ return true;
}
//TODO: Something is setting signal_cluster to MATCH_PARENT. Why?
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 9fa06f7..ce8e746 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -175,8 +175,8 @@
}
@Override
- public void onRecentsAnimationStarted() {
- mNavigationBarView.setRecentsAnimationStarted(true);
+ public void onQuickStepStarted() {
+ mNavigationBarView.onQuickStepStarted();
// Use navbar dragging as a signal to hide the rotate button
setRotateSuggestionButtonState(false);
@@ -751,6 +751,7 @@
if (shouldDisableNavbarGestures()) {
return false;
}
+ mNavigationBarView.onNavigationButtonLongPress(v);
mMetricsLogger.action(MetricsEvent.ACTION_ASSIST_LONG_PRESS);
mAssistManager.startAssist(new Bundle() /* args */);
mStatusBar.awakenDreams();
@@ -787,10 +788,12 @@
}
private boolean onLongPressBackHome(View v) {
+ mNavigationBarView.onNavigationButtonLongPress(v);
return onLongPressNavigationButtons(v, R.id.back, R.id.home);
}
private boolean onLongPressBackRecents(View v) {
+ mNavigationBarView.onNavigationButtonLongPress(v);
return onLongPressNavigationButtons(v, R.id.back, R.id.recent_apps);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
index 6a1ed51..cd000fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -19,31 +19,22 @@
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_LEFT;
import static android.view.WindowManager.DOCKED_TOP;
-import static com.android.systemui.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
-import static com.android.systemui.OverviewProxyService.TAG_OPS;
import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
-import android.graphics.Matrix;
import android.graphics.Rect;
-import android.os.RemoteException;
-import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
import com.android.systemui.Dependency;
-import com.android.systemui.OverviewProxyService;
-import com.android.systemui.OverviewProxyService.OverviewProxyListener;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
-import com.android.systemui.shared.recents.IOverviewProxy;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.tuner.TunerService;
@@ -75,25 +66,14 @@
private NavigationBarView mNavigationBarView;
private boolean mIsVertical;
- private final QuickScrubController mQuickScrubController;
+ private final QuickStepController mQuickStepController;
private final int mScrollTouchSlop;
- private final Matrix mTransformGlobalMatrix = new Matrix();
- private final Matrix mTransformLocalMatrix = new Matrix();
private final StatusBar mStatusBar;
private int mTouchDownX;
private int mTouchDownY;
private boolean mDownOnRecents;
private VelocityTracker mVelocityTracker;
- private OverviewProxyService mOverviewProxyService = Dependency.get(OverviewProxyService.class);
- private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() {
- @Override
- public void onRecentsAnimationStarted() {
- mRecentsAnimationStarted = true;
- mQuickScrubController.setRecentsAnimationStarted(true /* started */);
- }
- };
- private boolean mRecentsAnimationStarted;
private boolean mDockWindowEnabled;
private boolean mDockWindowTouchSlopExceeded;
private int mDragMode;
@@ -103,14 +83,12 @@
mStatusBar = SysUiServiceProvider.getComponent(context, StatusBar.class);
Resources r = context.getResources();
mScrollTouchSlop = r.getDimensionPixelSize(R.dimen.navigation_bar_min_swipe_distance);
- mQuickScrubController = new QuickScrubController(context);
+ mQuickStepController = new QuickStepController(context);
Dependency.get(TunerService.class).addTunable(this, KEY_DOCK_WINDOW_GESTURE);
- mOverviewProxyService.addCallback(mOverviewProxyListener);
}
public void destroy() {
Dependency.get(TunerService.class).removeTunable(this);
- mOverviewProxyService.removeCallback(mOverviewProxyListener);
}
public void setComponents(RecentsComponent recentsComponent, Divider divider,
@@ -118,65 +96,19 @@
mRecentsComponent = recentsComponent;
mDivider = divider;
mNavigationBarView = navigationBarView;
- mQuickScrubController.setComponents(mNavigationBarView);
+ mQuickStepController.setComponents(mNavigationBarView);
}
public void setBarState(boolean isVertical, boolean isRTL) {
mIsVertical = isVertical;
- mQuickScrubController.setBarState(isVertical, isRTL);
- }
-
- private boolean proxyMotionEvents(MotionEvent event) {
- final IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
- if (overviewProxy != null && mNavigationBarView.isQuickStepSwipeUpEnabled()) {
- mNavigationBarView.requestUnbufferedDispatch(event);
- event.transform(mTransformGlobalMatrix);
- try {
- if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
- overviewProxy.onPreMotionEvent(mNavigationBarView.getDownHitTarget());
- }
- overviewProxy.onMotionEvent(event);
- if (DEBUG_OVERVIEW_PROXY) {
- Log.d(TAG_OPS, "Send MotionEvent: " + event.toString());
- }
- return true;
- } catch (RemoteException e) {
- Log.e(TAG, "Callback failed", e);
- } finally {
- event.transform(mTransformLocalMatrix);
- }
- }
- return false;
+ mQuickStepController.setBarState(isVertical, isRTL);
}
public boolean onInterceptTouchEvent(MotionEvent event) {
- if (mNavigationBarView.inScreenPinning() || mStatusBar.isKeyguardShowing()
- || !mStatusBar.isPresenterFullyCollapsed()) {
+ if (!canHandleGestures()) {
return false;
}
-
- int action = event.getActionMasked();
- switch (action) {
- case MotionEvent.ACTION_DOWN: {
- mTouchDownX = (int) event.getX();
- mTouchDownY = (int) event.getY();
- mTransformGlobalMatrix.set(Matrix.IDENTITY_MATRIX);
- mTransformLocalMatrix.set(Matrix.IDENTITY_MATRIX);
- mNavigationBarView.transformMatrixToGlobal(mTransformGlobalMatrix);
- mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix);
- mRecentsAnimationStarted = false;
- mQuickScrubController.setRecentsAnimationStarted(false /* started */);
- break;
- }
- }
- boolean handledByQuickscrub = mQuickScrubController.onInterceptTouchEvent(event);
- if (!handledByQuickscrub) {
- // Proxy motion events until we start intercepting for quickscrub
- proxyMotionEvents(event);
- }
-
- boolean result = handledByQuickscrub;
- result |= mRecentsAnimationStarted;
+ boolean result = mQuickStepController.onInterceptTouchEvent(event);
if (mDockWindowEnabled) {
result |= interceptDockWindowEvent(event);
}
@@ -184,18 +116,10 @@
}
public boolean onTouchEvent(MotionEvent event) {
- if (mNavigationBarView.inScreenPinning() || mStatusBar.isKeyguardShowing()
- || !mStatusBar.isPresenterFullyCollapsed()) {
+ if (!canHandleGestures()) {
return false;
}
-
- // The same down event was just sent on intercept and therefore can be ignored here
- boolean ignoreProxyDownEvent = event.getAction() == MotionEvent.ACTION_DOWN
- && mOverviewProxyService.getProxy() != null;
- boolean result = mQuickScrubController.onTouchEvent(event)
- || ignoreProxyDownEvent
- || proxyMotionEvents(event);
- result |= mRecentsAnimationStarted;
+ boolean result = mQuickStepController.onTouchEvent(event);
if (mDockWindowEnabled) {
result |= handleDockWindowEvent(event);
}
@@ -203,17 +127,19 @@
}
public void onDraw(Canvas canvas) {
- if (mNavigationBarView.isQuickScrubEnabled()) {
- mQuickScrubController.onDraw(canvas);
- }
+ mQuickStepController.onDraw(canvas);
}
public void onLayout(boolean changed, int left, int top, int right, int bottom) {
- mQuickScrubController.onLayout(changed, left, top, right, bottom);
+ mQuickStepController.onLayout(changed, left, top, right, bottom);
}
public void onDarkIntensityChange(float intensity) {
- mQuickScrubController.onDarkIntensityChange(intensity);
+ mQuickStepController.onDarkIntensityChange(intensity);
+ }
+
+ public void onNavigationButtonLongPress(View v) {
+ mQuickStepController.onNavigationButtonLongPress(v);
}
private boolean interceptDockWindowEvent(MotionEvent event) {
@@ -342,6 +268,11 @@
mVelocityTracker = null;
}
+ private boolean canHandleGestures() {
+ return !mNavigationBarView.inScreenPinning() && !mStatusBar.isKeyguardShowing()
+ && mStatusBar.isPresenterFullyCollapsed();
+ }
+
private int calculateDragMode() {
if (mIsVertical && !mDivider.getView().isHorizontalDivision()) {
return DRAG_MODE_DIVIDER;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 056874f..fcbd37c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -39,6 +39,7 @@
import android.os.Handler;
import android.os.Message;
import android.os.SystemProperties;
+import android.os.VibrationEffect;
import android.support.annotation.ColorInt;
import android.util.AttributeSet;
import android.util.Log;
@@ -49,6 +50,7 @@
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout;
@@ -67,6 +69,7 @@
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.NavigationBarCompat;
import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.policy.DeadZone;
import com.android.systemui.statusbar.policy.KeyButtonDrawable;
import com.android.systemui.statusbar.policy.TintedKeyButtonDrawable;
@@ -148,6 +151,7 @@
private Divider mDivider;
private RecentsOnboarding mRecentsOnboarding;
private NotificationPanelView mPanelView;
+ private final VibratorHelper mVibratorHelper;
private int mRotateBtnStyle = R.style.RotateButtonCCWStart90;
@@ -243,6 +247,7 @@
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService);
+ mVibratorHelper = Dependency.get(VibratorHelper.class);
mConfiguration = new Configuration();
mConfiguration.updateFrom(context.getResources().getConfiguration());
@@ -285,18 +290,12 @@
notifyVerticalChangedListener(mVertical);
}
- public void setRecentsAnimationStarted(boolean started) {
+ public void onQuickStepStarted() {
if (mRecentsOnboarding != null) {
- mRecentsOnboarding.onRecentsAnimationStarted();
+ mRecentsOnboarding.onQuickStepStarted();
}
}
- public void onConnectionChanged(boolean isConnected) {
- updateSlippery();
- updateNavButtonIcons();
- setUpSwipeUpOnboarding(isConnected);
- }
-
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
switch (event.getActionMasked()) {
@@ -311,6 +310,9 @@
} else if (mRecentsButtonBounds.contains(x, y)) {
mDownHitTarget = HIT_TARGET_OVERVIEW;
}
+
+ // Vibrate tick whenever down occurs on navigation bar
+ mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK);
break;
}
return mGestureHelper.onInterceptTouchEvent(event);
@@ -667,6 +669,10 @@
}
}
+ public void onNavigationButtonLongPress(View v) {
+ mGestureHelper.onNavigationButtonLongPress(v);
+ }
+
public void onPanelExpandedChange(boolean expanded) {
updateSlippery();
}
@@ -1028,6 +1034,7 @@
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
+ requestApplyInsets();
reorient();
onPluginDisconnected(null); // Create default gesture helper
Dependency.get(PluginManager.class).addPluginListener(this,
@@ -1105,6 +1112,13 @@
pw.println(" }");
}
+ @Override
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ setPadding(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
+ insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
+ return super.onApplyWindowInsets(insets);
+ }
+
private static void dumpButton(PrintWriter pw, String caption, ButtonDispatcher button) {
pw.print(" " + caption + ": ");
if (button == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
index 1452e0c..e5083c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
@@ -95,8 +95,12 @@
}
private View findNearestChild(MotionEvent event) {
- return mClickableChildren.stream().map(v -> new Pair<>(distance(v, event), v))
- .min(Comparator.comparingInt(f -> f.first)).get().second;
+ return mClickableChildren
+ .stream()
+ .filter(v -> v.isAttachedToWindow())
+ .map(v -> new Pair<>(distance(v, event), v))
+ .min(Comparator.comparingInt(f -> f.first))
+ .get().second;
}
private int distance(View v, MotionEvent event) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index e77b135..e1aed7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -141,7 +141,7 @@
}
// showAmbient == show in shade but not shelf
- if (!showAmbient && notificationData.shouldSuppressScreenOn(entry.key)) {
+ if (!showAmbient && notificationData.shouldSuppressStatusBar(entry.key)) {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 9d2480b..2711d7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -238,7 +238,6 @@
private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
private boolean mNoVisibleNotifications = true;
private ValueAnimator mDarkAnimator;
- private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private boolean mUserSetupComplete;
private int mQsNotificationTopPadding;
private float mExpandOffset;
@@ -265,10 +264,8 @@
mKeyguardStatusBar = findViewById(R.id.keyguard_header);
mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
- mNotificationContainerParent = (NotificationsQuickSettingsContainer)
- findViewById(R.id.notification_container_parent);
- mNotificationStackScroller = (NotificationStackScrollLayout)
- findViewById(R.id.notification_stack_scroller);
+ mNotificationContainerParent = findViewById(R.id.notification_container_parent);
+ mNotificationStackScroller = findViewById(R.id.notification_stack_scroller);
mNotificationStackScroller.setOnHeightChangedListener(this);
mNotificationStackScroller.setOverscrollTopChangedListener(this);
mNotificationStackScroller.setOnEmptySpaceClickListener(this);
@@ -470,7 +467,9 @@
getMaxPanelHeight(),
totalHeight,
mKeyguardStatusView.getHeight(),
- mDarkAmount);
+ mDarkAmount,
+ mStatusBar.isKeyguardCurrentlySecure(),
+ mTracking);
mClockPositionAlgorithm.run(mClockPositionResult);
if (animate || mClockAnimator != null) {
startClockAnimation(mClockPositionResult.clockX, mClockPositionResult.clockY);
@@ -1710,7 +1709,16 @@
}
private void updateKeyguardBottomAreaAlpha() {
- float alpha = Math.min(getKeyguardContentsAlpha(), 1 - getQsExpansionFraction());
+ // There are two possible panel expansion behaviors:
+ // • User dragging up to unlock: we want to fade out as quick as possible
+ // (ALPHA_EXPANSION_THRESHOLD) to avoid seeing the bouncer over the bottom area.
+ // • User tapping on lock screen: bouncer won't be visible but panel expansion will
+ // change due to "unlock hint animation." In this case, fading out the bottom area
+ // would also hide the message that says "swipe to unlock," we don't want to do that.
+ float expansionAlpha = MathUtils.map(isUnlockHintRunning()
+ ? 0 : KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1f,
+ 0f, 1f, getExpandedFraction());
+ float alpha = Math.min(expansionAlpha, 1 - getQsExpansionFraction());
mKeyguardBottomArea.setAlpha(alpha);
mKeyguardBottomArea.setImportantForAccessibility(alpha == 0f
? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
@@ -1809,7 +1817,7 @@
@Override
protected void onTrackingStarted() {
- mFalsingManager.onTrackingStarted();
+ mFalsingManager.onTrackingStarted(mStatusBar.isKeyguardCurrentlySecure());
super.onTrackingStarted();
if (mQsFullyExpanded) {
mQsExpandImmediate = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index cefe972..b448967 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -27,6 +27,7 @@
public static final boolean DEBUG = false;
public static final String TAG = PanelBar.class.getSimpleName();
private static final boolean SPEW = false;
+ private boolean mBouncerShowing;
public static final void LOG(String fmt, Object... args) {
if (!DEBUG) return;
@@ -65,6 +66,7 @@
}
public void setBouncerShowing(boolean showing) {
+ mBouncerShowing = showing;
int important = showing ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
: IMPORTANT_FOR_ACCESSIBILITY_AUTO;
@@ -122,7 +124,7 @@
boolean fullyOpened = false;
if (SPEW) LOG("panelExpansionChanged: start state=%d", mState);
PanelView pv = mPanel;
- pv.setVisibility(expanded ? VISIBLE : INVISIBLE);
+ pv.setVisibility(expanded || mBouncerShowing ? VISIBLE : INVISIBLE);
// adjust any other panels that may be partially visible
if (expanded) {
if (mState == STATE_CLOSED) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 9c2a0e5..7f1e9d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -23,14 +23,8 @@
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.database.ContentObserver;
-import android.os.AsyncTask;
-import android.os.Handler;
import android.os.SystemClock;
-import android.os.UserHandle;
import android.os.VibrationEffect;
-import android.os.Vibrator;
-import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
import android.view.InputDevice;
@@ -44,16 +38,18 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.LatencyTracker;
import com.android.systemui.DejankUtils;
+import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
+import com.android.systemui.statusbar.VibratorHelper;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.function.BiConsumer;
public abstract class PanelView extends FrameLayout {
public static final boolean DEBUG = PanelBar.DEBUG;
@@ -66,9 +62,9 @@
private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
private boolean mPanelUpdateWhenAnimatorEnds;
private boolean mVibrateOnOpening;
- private boolean mVibrationEnabled;
protected boolean mLaunchingNotification;
private int mFixedDuration = NO_FIXED_DURATION;
+ private BiConsumer<Float, Boolean> mExpansionListener;
private final void logf(String fmt, Object... args) {
Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
@@ -110,13 +106,7 @@
private FlingAnimationUtils mFlingAnimationUtilsClosing;
private FlingAnimationUtils mFlingAnimationUtilsDismissing;
private FalsingManager mFalsingManager;
- private final Vibrator mVibrator;
- final private ContentObserver mVibrationObserver = new ContentObserver(Handler.getMain()) {
- @Override
- public void onChange(boolean selfChange) {
- updateHapticFeedBackEnabled();
- }
- };
+ private final VibratorHelper mVibratorHelper;
/**
* Whether an instant expand request is currently pending and we are just waiting for layout.
@@ -218,18 +208,9 @@
mFalsingManager = FalsingManager.getInstance(context);
mNotificationsDragEnabled =
getResources().getBoolean(R.bool.config_enableNotificationShadeDrag);
- mVibrator = mContext.getSystemService(Vibrator.class);
+ mVibratorHelper = Dependency.get(VibratorHelper.class);
mVibrateOnOpening = mContext.getResources().getBoolean(
R.bool.config_vibrateOnIconAnimation);
- mContext.getContentResolver().registerContentObserver(
- Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_ENABLED), true,
- mVibrationObserver);
- mVibrationObserver.onChange(false /* selfChange */);
- }
-
- public void updateHapticFeedBackEnabled() {
- mVibrationEnabled = Settings.System.getIntForUser(mContext.getContentResolver(),
- Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) != 0;
}
protected void loadDimens() {
@@ -341,7 +322,8 @@
cancelPeek();
onTrackingStarted();
}
- if (isFullyCollapsed() && !mHeadsUpManager.hasPinnedHeadsUp()) {
+ if (isFullyCollapsed() && !mHeadsUpManager.hasPinnedHeadsUp()
+ && !mStatusBar.isBouncerShowing()) {
startOpening(event);
}
break;
@@ -421,9 +403,8 @@
runPeekAnimation(INITIAL_OPENING_PEEK_DURATION, getOpeningHeight(),
false /* collapseWhenFinished */);
notifyBarPanelExpansionChanged();
- if (mVibrateOnOpening && mVibrationEnabled) {
- AsyncTask.execute(() ->
- mVibrator.vibrate(VibrationEffect.get(VibrationEffect.EFFECT_TICK, false)));
+ if (mVibrateOnOpening) {
+ mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK);
}
//TODO: keyguard opens QS a different way; log that too?
@@ -506,7 +487,8 @@
if (mUpdateFlingOnLayout) {
mUpdateFlingVelocity = vel;
}
- } else if (mPanelClosedOnDown && !mHeadsUpManager.hasPinnedHeadsUp() && !mTracking) {
+ } else if (mPanelClosedOnDown && !mHeadsUpManager.hasPinnedHeadsUp() && !mTracking
+ && !mStatusBar.isBouncerShowing()) {
long timePassed = SystemClock.uptimeMillis() - mDownTime;
if (timePassed < ViewConfiguration.getLongPressTimeout()) {
// Lets show the user that he can actually expand the panel
@@ -515,7 +497,7 @@
// We need to collapse the panel since we peeked to the small height.
postOnAnimation(mPostCollapseRunnable);
}
- } else {
+ } else if (!mStatusBar.isBouncerShowing()) {
boolean expands = onEmptySpaceClick(mInitialTouchX);
onTrackingStopped(expands);
}
@@ -1115,6 +1097,10 @@
mStatusBar.onUnlockHintStarted();
}
+ public boolean isUnlockHintRunning() {
+ return mHintAnimationRunning;
+ }
+
/**
* Phase 1: Move everything upwards.
*/
@@ -1206,6 +1192,13 @@
mBar.panelExpansionChanged(mExpandedFraction, mExpandedFraction > 0f
|| mPeekAnimator != null || mInstantExpanding || isPanelVisibleBecauseOfHeadsUp()
|| mTracking || mHeightAnimator != null);
+ if (mExpansionListener != null) {
+ mExpansionListener.accept(mExpandedFraction, mTracking);
+ }
+ }
+
+ public void setExpansionListener(BiConsumer<Float, Boolean> consumer) {
+ mExpansionListener = consumer;
}
protected abstract boolean isPanelVisibleBecauseOfHeadsUp();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 900ec0b..5076404 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -18,6 +18,8 @@
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static com.android.systemui.ScreenDecorations.DisplayCutoutView.boundsFromDirection;
+
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
@@ -25,9 +27,11 @@
import android.util.AttributeSet;
import android.util.EventLog;
import android.view.DisplayCutout;
+import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowInsets;
import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
@@ -37,7 +41,8 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
-import com.android.systemui.util.leak.RotationUtils;
+
+import java.util.Objects;
public class PhoneStatusBarView extends PanelBar {
private static final String TAG = "PhoneStatusBarView";
@@ -98,7 +103,7 @@
// Always have Battery meters in the status bar observe the dark/light modes.
Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mBattery);
if (updateOrientationAndCutout(getResources().getConfiguration().orientation)) {
- postUpdateLayoutForCutout();
+ updateLayoutForCutout();
}
}
@@ -115,10 +120,20 @@
// May trigger cutout space layout-ing
if (updateOrientationAndCutout(newConfig.orientation)) {
- postUpdateLayoutForCutout();
+ updateLayoutForCutout();
+ requestLayout();
}
}
+ @Override
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ if (updateOrientationAndCutout(mLastOrientation)) {
+ updateLayoutForCutout();
+ requestLayout();
+ }
+ return super.onApplyWindowInsets(insets);
+ }
+
/**
*
* @param newOrientation may pass NO_VALUE for no change
@@ -133,12 +148,9 @@
}
}
- if (mDisplayCutout == null) {
- DisplayCutout cutout = getRootWindowInsets().getDisplayCutout();
- if (cutout != null) {
- changed = true;
- mDisplayCutout = cutout;
- }
+ if (!Objects.equals(getRootWindowInsets().getDisplayCutout(), mDisplayCutout)) {
+ changed = true;
+ mDisplayCutout = getRootWindowInsets().getDisplayCutout();
}
return changed;
@@ -276,17 +288,6 @@
updateSafeInsets();
}
- private void postUpdateLayoutForCutout() {
- Runnable r = new Runnable() {
- @Override
- public void run() {
- updateLayoutForCutout();
- }
- };
- // Let the cutout emulation draw first
- postDelayed(r, 0);
- }
-
private void updateCutoutLocation() {
// Not all layouts have a cutout (e.g., Car)
if (mCutoutSpace == null) {
@@ -301,8 +302,12 @@
mCutoutSpace.setVisibility(View.VISIBLE);
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mCutoutSpace.getLayoutParams();
- lp.width = mDisplayCutout.getBoundingRect().width();
- lp.height = mDisplayCutout.getBoundingRect().height();
+
+ Rect bounds = new Rect();
+ boundsFromDirection(mDisplayCutout, Gravity.TOP, bounds);
+
+ lp.width = bounds.width();
+ lp.height = bounds.height();
}
private void updateSafeInsets() {
@@ -310,40 +315,13 @@
// or letterboxing from the right or left sides.
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
- if (mDisplayCutout == null || mDisplayCutout.isEmpty()) {
+ if (mDisplayCutout == null) {
lp.leftMargin = 0;
lp.rightMargin = 0;
return;
}
- int leftMargin = 0;
- int rightMargin = 0;
- switch (RotationUtils.getRotation(getContext())) {
- /*
- * Landscape: <-|
- * Seascape: |->
- */
- case RotationUtils.ROTATION_LANDSCAPE:
- leftMargin = getDisplayCutoutHeight();
- break;
- case RotationUtils.ROTATION_SEASCAPE:
- rightMargin = getDisplayCutoutHeight();
- break;
- default:
- break;
- }
-
- lp.leftMargin = leftMargin;
- lp.rightMargin = rightMargin;
- }
-
- //TODO: Find a better way
- private int getDisplayCutoutHeight() {
- if (mDisplayCutout == null || mDisplayCutout.isEmpty()) {
- return 0;
- }
-
- Rect r = mDisplayCutout.getBoundingRect();
- return r.bottom - r.top;
+ lp.leftMargin = mDisplayCutout.getSafeInsetLeft();
+ lp.rightMargin = mDisplayCutout.getSafeInsetRight();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
similarity index 65%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
index 00aff53..d79f0a1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -25,6 +25,7 @@
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.graphics.Canvas;
+import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Handler;
@@ -55,10 +56,10 @@
/**
* Class to detect gestures on the navigation bar and implement quick scrub and switch.
*/
-public class QuickScrubController extends GestureDetector.SimpleOnGestureListener implements
+public class QuickStepController extends GestureDetector.SimpleOnGestureListener implements
GestureHelper {
- private static final String TAG = "QuickScrubController";
+ private static final String TAG = "QuickStepController";
private static final int QUICK_SWITCH_FLING_VELOCITY = 0;
private static final int ANIM_DURATION_MS = 200;
private static final long LONG_PRESS_DELAY_MS = 225;
@@ -75,7 +76,8 @@
private boolean mDraggingActive;
private boolean mQuickScrubActive;
private boolean mAllowQuickSwitch;
- private boolean mRecentsAnimationStarted;
+ private boolean mAllowGestureDetection;
+ private boolean mQuickStepStarted;
private float mDownOffset;
private float mTranslation;
private int mTouchDownX;
@@ -101,6 +103,8 @@
private final ValueAnimator mButtonAnimator;
private final AnimatorSet mQuickScrubEndAnimator;
private final Context mContext;
+ private final Matrix mTransformGlobalMatrix = new Matrix();
+ private final Matrix mTransformLocalMatrix = new Matrix();
private final ArgbEvaluator mTrackColorEvaluator = new ArgbEvaluator();
private final AnimatorUpdateListener mTrackAnimatorListener = valueAnimator -> {
@@ -123,7 +127,6 @@
private AnimatorListenerAdapter mQuickScrubEndListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- mNavigationBarView.getHomeButton().setClickable(true);
mQuickScrubActive = false;
mTranslation = 0;
mQuickScrubEndAnimator.setCurrentPlayTime(mQuickScrubEndAnimator.getDuration());
@@ -165,7 +168,7 @@
}
};
- public QuickScrubController(Context context) {
+ public QuickStepController(Context context) {
mContext = context;
mScrollTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mOverviewEventSender = Dependency.get(OverviewProxyService.class);
@@ -197,31 +200,34 @@
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
- final ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
- if (!mNavigationBarView.isQuickScrubEnabled()) {
- homeButton.setDelayTouchFeedback(false);
+ if (!mNavigationBarView.isQuickScrubEnabled()
+ && !mNavigationBarView.isQuickStepSwipeUpEnabled()) {
+ mNavigationBarView.getHomeButton().setDelayTouchFeedback(false /* delay */);
return false;
}
-
+ mNavigationBarView.requestUnbufferedDispatch(event);
return handleTouchEvent(event);
}
/**
- * @return true if we want to handle touch events for quick scrub/switch and prevent proxying
- * the event to the overview service.
+ * @return true if we want to handle touch events for quick scrub/switch or if down event (that
+ * will get consumed and ignored). No events will be proxied to the overview service.
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
- return handleTouchEvent(event);
+ // The same down event was just sent on intercept and therefore can be ignored here
+ final boolean ignoreProxyDownEvent = event.getAction() == MotionEvent.ACTION_DOWN
+ && mOverviewEventSender.getProxy() != null;
+ return ignoreProxyDownEvent || handleTouchEvent(event);
}
private boolean handleTouchEvent(MotionEvent event) {
- final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy();
final ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
if (mGestureDetector.onTouchEvent(event)) {
// If the fling has been handled on UP, then skip proxying the UP
return true;
}
+ final boolean homePressed = mNavigationBarView.getDownHitTarget() == HIT_TARGET_HOME;
int action = event.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
@@ -232,89 +238,99 @@
mQuickScrubEndAnimator.end();
}
mHomeButtonView = homeButton.getCurrentView();
- if (mNavigationBarView.isQuickScrubEnabled()
- && mNavigationBarView.getDownHitTarget() == HIT_TARGET_HOME) {
- mTouchDownX = x;
- mTouchDownY = y;
- homeButton.setDelayTouchFeedback(true);
+ homeButton.setDelayTouchFeedback(true /* delay */);
+ mTouchDownX = x;
+ mTouchDownY = y;
+ if (homePressed) {
mHandler.postDelayed(mLongPressRunnable, LONG_PRESS_DELAY_MS);
- } else {
- homeButton.setDelayTouchFeedback(false);
- mTouchDownX = mTouchDownY = -1;
}
+ mTransformGlobalMatrix.set(Matrix.IDENTITY_MATRIX);
+ mTransformLocalMatrix.set(Matrix.IDENTITY_MATRIX);
+ mNavigationBarView.transformMatrixToGlobal(mTransformGlobalMatrix);
+ mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix);
+ mQuickStepStarted = false;
mAllowQuickSwitch = true;
+ mAllowGestureDetection = true;
break;
}
case MotionEvent.ACTION_MOVE: {
- if (mTouchDownX != -1) {
- int x = (int) event.getX();
- int y = (int) event.getY();
- int xDiff = Math.abs(x - mTouchDownX);
- int yDiff = Math.abs(y - mTouchDownY);
- boolean exceededTouchSlopX = xDiff > mScrollTouchSlop && xDiff > yDiff;
- boolean exceededTouchSlopY = yDiff > mScrollTouchSlop && yDiff > xDiff;
- boolean exceededTouchSlop, exceededPerpendicularTouchSlop;
- int pos, touchDown, offset, trackSize;
+ if (mQuickStepStarted || !mAllowGestureDetection){
+ break;
+ }
+ int x = (int) event.getX();
+ int y = (int) event.getY();
+ int xDiff = Math.abs(x - mTouchDownX);
+ int yDiff = Math.abs(y - mTouchDownY);
+ boolean exceededTouchSlopX = xDiff > mScrollTouchSlop && xDiff > yDiff;
+ boolean exceededTouchSlopY = yDiff > mScrollTouchSlop && yDiff > xDiff;
+ boolean exceededTouchSlop, exceededPerpendicularTouchSlop;
+ int pos, touchDown, offset, trackSize;
- if (mIsVertical) {
- exceededTouchSlop = exceededTouchSlopY;
- exceededPerpendicularTouchSlop = exceededTouchSlopX;
- pos = y;
- touchDown = mTouchDownY;
- offset = pos - mTrackRect.top;
- trackSize = mTrackRect.height();
- } else {
- exceededTouchSlop = exceededTouchSlopX;
- exceededPerpendicularTouchSlop = exceededTouchSlopY;
- pos = x;
- touchDown = mTouchDownX;
- offset = pos - mTrackRect.left;
- trackSize = mTrackRect.width();
+ if (mIsVertical) {
+ exceededTouchSlop = exceededTouchSlopY;
+ exceededPerpendicularTouchSlop = exceededTouchSlopX;
+ pos = y;
+ touchDown = mTouchDownY;
+ offset = pos - mTrackRect.top;
+ trackSize = mTrackRect.height();
+ } else {
+ exceededTouchSlop = exceededTouchSlopX;
+ exceededPerpendicularTouchSlop = exceededTouchSlopY;
+ pos = x;
+ touchDown = mTouchDownX;
+ offset = pos - mTrackRect.left;
+ trackSize = mTrackRect.width();
+ }
+ // Decide to start quickstep if dragging away from the navigation bar, otherwise in
+ // the parallel direction, decide to start quickscrub. Only one may run.
+ if (!mDraggingActive && !mQuickScrubActive && exceededPerpendicularTouchSlop) {
+ if (mNavigationBarView.isQuickStepSwipeUpEnabled()) {
+ startQuickStep(event);
}
- // Do not start scrubbing when dragging in the perpendicular direction if we
- // haven't already started quickscrub
- if (!mDraggingActive && !mQuickScrubActive && exceededPerpendicularTouchSlop) {
- mHandler.removeCallbacksAndMessages(null);
- return false;
- }
- if (!mDragPositive) {
- offset -= mIsVertical ? mTrackRect.height() : mTrackRect.width();
- }
+ break;
+ }
- // Control the button movement
- if (!mDraggingActive && exceededTouchSlop && !mRecentsAnimationStarted) {
- boolean allowDrag = !mDragPositive
- ? offset < 0 && pos < touchDown : offset >= 0 && pos > touchDown;
- if (allowDrag) {
- mDownOffset = offset;
- homeButton.setClickable(false);
- mDraggingActive = true;
- }
+ // Do not handle quick scrub/switch if disabled or hit target is not home button
+ if (!homePressed || !mNavigationBarView.isQuickScrubEnabled()) {
+ break;
+ }
+
+ if (!mDragPositive) {
+ offset -= mIsVertical ? mTrackRect.height() : mTrackRect.width();
+ }
+
+ // Control the button movement
+ if (!mDraggingActive && exceededTouchSlop) {
+ boolean allowDrag = !mDragPositive
+ ? offset < 0 && pos < touchDown : offset >= 0 && pos > touchDown;
+ if (allowDrag) {
+ mDownOffset = offset;
+ homeButton.abortCurrentGesture();
+ mDraggingActive = true;
}
- if (mDraggingActive && (mDragPositive && offset >= 0
- || !mDragPositive && offset <= 0)) {
- float scrubFraction =
- Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1);
- mTranslation = !mDragPositive
- ? Utilities.clamp(offset - mDownOffset, -trackSize, 0)
- : Utilities.clamp(offset - mDownOffset, 0, trackSize);
- if (mQuickScrubActive) {
- try {
- mOverviewEventSender.getProxy().onQuickScrubProgress(scrubFraction);
- if (DEBUG_OVERVIEW_PROXY) {
- Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to send progress of quick scrub.", e);
+ }
+ if (mDraggingActive && (mDragPositive && offset >= 0
+ || !mDragPositive && offset <= 0)) {
+ float scrubFraction = Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1);
+ mTranslation = !mDragPositive
+ ? Utilities.clamp(offset - mDownOffset, -trackSize, 0)
+ : Utilities.clamp(offset - mDownOffset, 0, trackSize);
+ if (mQuickScrubActive) {
+ try {
+ mOverviewEventSender.getProxy().onQuickScrubProgress(scrubFraction);
+ if (DEBUG_OVERVIEW_PROXY) {
+ Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction);
}
- } else {
- mTranslation /= SWITCH_STICKINESS;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to send progress of quick scrub.", e);
}
- if (mIsVertical) {
- mHomeButtonView.setTranslationY(mTranslation);
- } else {
- mHomeButtonView.setTranslationX(mTranslation);
- }
+ } else {
+ mTranslation /= SWITCH_STICKINESS;
+ }
+ if (mIsVertical) {
+ mHomeButtonView.setTranslationY(mTranslation);
+ } else {
+ mHomeButtonView.setTranslationX(mTranslation);
}
}
break;
@@ -324,11 +340,20 @@
endQuickScrub(true /* animate */);
break;
}
- return mDraggingActive || mQuickScrubActive;
+
+ // Proxy motion events to launcher if not handled by quick scrub/switch
+ boolean handled = mDraggingActive || mQuickScrubActive;
+ if (!handled && mAllowGestureDetection) {
+ proxyMotionEvents(event);
+ }
+ return handled || mQuickStepStarted;
}
@Override
public void onDraw(Canvas canvas) {
+ if (mNavigationBarView.isQuickScrubEnabled()) {
+ return;
+ }
int color = (int) mTrackColorEvaluator.evaluate(mDarkIntensity, mLightTrackColor,
mDarkTrackColor);
mTrackPaint.setColor(color);
@@ -381,6 +406,31 @@
}
}
+ @Override
+ public void onNavigationButtonLongPress(View v) {
+ mAllowGestureDetection = false;
+ mHandler.removeCallbacksAndMessages(null);
+ }
+
+ private void startQuickStep(MotionEvent event) {
+ mQuickStepStarted = true;
+ event.transform(mTransformGlobalMatrix);
+ try {
+ mOverviewEventSender.getProxy().onQuickStep(event);
+ if (DEBUG_OVERVIEW_PROXY) {
+ Log.d(TAG_OPS, "Quick Step Start");
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to send quick step started.", e);
+ } finally {
+ event.transform(mTransformLocalMatrix);
+ }
+ mOverviewEventSender.notifyQuickStepStarted();
+ mNavigationBarView.getHomeButton().abortCurrentGesture();
+ cancelQuickSwitch();
+ mHandler.removeCallbacksAndMessages(null);
+ }
+
private void startQuickScrub() {
if (!mQuickScrubActive && mDraggingActive) {
mQuickScrubActive = true;
@@ -396,9 +446,6 @@
} catch (RemoteException e) {
Log.e(TAG, "Failed to send start of quick scrub.", e);
}
- } else {
- // After long press do not allow quick scrub/switch
- mTouchDownX = -1;
}
}
@@ -421,11 +468,24 @@
mDraggingActive = false;
}
- public void setRecentsAnimationStarted(boolean started) {
- mRecentsAnimationStarted = started;
- if (started) {
- cancelQuickSwitch();
+ private boolean proxyMotionEvents(MotionEvent event) {
+ final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy();
+ event.transform(mTransformGlobalMatrix);
+ try {
+ if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ overviewProxy.onPreMotionEvent(mNavigationBarView.getDownHitTarget());
+ }
+ overviewProxy.onMotionEvent(event);
+ if (DEBUG_OVERVIEW_PROXY) {
+ Log.d(TAG_OPS, "Send MotionEvent: " + event.toString());
+ }
+ return true;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Callback failed", e);
+ } finally {
+ event.transform(mTransformLocalMatrix);
}
+ return false;
}
public void cancelQuickSwitch() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index e59a6b5..f8b4e07 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -35,7 +35,6 @@
import android.view.ViewTreeObserver;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
-import android.view.animation.PathInterpolator;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.colorextraction.ColorExtractor;
@@ -97,14 +96,6 @@
* The most common scrim, the one under the keyguard.
*/
protected static final float SCRIM_BEHIND_ALPHA_KEYGUARD = GRADIENT_SCRIM_ALPHA;
- /**
- * We fade out the bottom scrim when the bouncer is visible.
- */
- protected static final float SCRIM_BEHIND_ALPHA_UNLOCKING = 0.2f;
- /**
- * Opacity of the scrim behind the bouncer (the one doing actual background protection.)
- */
- protected static final float SCRIM_IN_FRONT_ALPHA_LOCKED = GRADIENT_SCRIM_ALPHA_BUSY;
static final int TAG_KEY_ANIM = R.id.scrim;
private static final int TAG_START_ALPHA = R.id.scrim_alpha_start;
@@ -130,12 +121,12 @@
protected float mScrimBehindAlpha;
protected float mScrimBehindAlphaResValue;
protected float mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD;
- protected float mScrimBehindAlphaUnlocking = SCRIM_BEHIND_ALPHA_UNLOCKING;
// Assuming the shade is expanded during initialization
private float mExpansionFraction = 1f;
private boolean mDarkenWhileDragging;
+ private boolean mExpansionAffectsAlpha = true;
protected boolean mAnimateChange;
private boolean mUpdatePending;
private boolean mTracking;
@@ -177,6 +168,7 @@
mScrimVisibleListener = scrimVisibleListener;
mContext = scrimBehind.getContext();
mUnlockMethodCache = UnlockMethodCache.getInstance(mContext);
+ mDarkenWhileDragging = !mUnlockMethodCache.canSkipBouncer();
mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
mLightBarController = lightBarController;
mScrimBehindAlphaResValue = mContext.getResources().getFloat(R.dimen.scrim_behind_alpha);
@@ -300,10 +292,8 @@
return mState;
}
- protected void setScrimBehindValues(float scrimBehindAlphaKeyguard,
- float scrimBehindAlphaUnlocking) {
+ protected void setScrimBehindValues(float scrimBehindAlphaKeyguard) {
mScrimBehindAlphaKeyguard = scrimBehindAlphaKeyguard;
- mScrimBehindAlphaUnlocking = scrimBehindAlphaUnlocking;
ScrimState[] states = ScrimState.values();
for (int i = 0; i < states.length; i++) {
states[i].setScrimBehindAlphaKeyguard(scrimBehindAlphaKeyguard);
@@ -392,6 +382,10 @@
}
private void applyExpansionToAlpha() {
+ if (!mExpansionAffectsAlpha) {
+ return;
+ }
+
if (mState == ScrimState.UNLOCKED) {
// Darken scrim as you pull down the shade when unlocked
float behindFraction = getInterpolatedFraction();
@@ -404,9 +398,9 @@
float interpolatedFract = getInterpolatedFraction();
float alphaBehind = mState.getBehindAlpha(mNotificationDensity);
if (mDarkenWhileDragging) {
- mCurrentBehindAlpha = MathUtils.lerp(mScrimBehindAlphaUnlocking, alphaBehind,
+ mCurrentBehindAlpha = MathUtils.lerp(GRADIENT_SCRIM_ALPHA_BUSY, alphaBehind,
interpolatedFract);
- mCurrentInFrontAlpha = (1f - interpolatedFract) * SCRIM_IN_FRONT_ALPHA_LOCKED;
+ mCurrentInFrontAlpha = 0;
} else {
mCurrentBehindAlpha = MathUtils.lerp(0 /* start */, alphaBehind,
interpolatedFract);
@@ -455,7 +449,8 @@
if (mNeedsDrawableColorUpdate) {
mNeedsDrawableColorUpdate = false;
final GradientColors currentScrimColors;
- if (mState == ScrimState.KEYGUARD || mState == ScrimState.BOUNCER) {
+ if (mState == ScrimState.KEYGUARD || mState == ScrimState.BOUNCER_OCCLUDED
+ || mState == ScrimState.BOUNCER) {
// Always animate color changes if we're seeing the keyguard
mScrimInFront.setColors(mLockColors, true /* animated */);
mScrimBehind.setColors(mLockColors, true /* animated */);
@@ -922,6 +917,10 @@
mScreenOn = false;
}
+ public void setExpansionAffectsAlpha(boolean expansionAffectsAlpha) {
+ mExpansionAffectsAlpha = expansionAffectsAlpha;
+ }
+
public interface Callback {
default void onStart() {
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index 053c5a3..58100ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -66,20 +66,31 @@
},
/**
- * Showing password challenge.
+ * Showing password challenge on the keyguard.
*/
BOUNCER(1) {
@Override
public void prepare(ScrimState previousState) {
- mCurrentBehindAlpha = ScrimController.SCRIM_BEHIND_ALPHA_UNLOCKING;
- mCurrentInFrontAlpha = ScrimController.SCRIM_IN_FRONT_ALPHA_LOCKED;
+ mCurrentBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY;
+ mCurrentInFrontAlpha = 0f;
+ }
+ },
+
+ /**
+ * Showing password challenge on top of a FLAG_SHOW_WHEN_LOCKED activity.
+ */
+ BOUNCER_OCCLUDED(2) {
+ @Override
+ public void prepare(ScrimState previousState) {
+ mCurrentBehindAlpha = 0;
+ mCurrentInFrontAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY;
}
},
/**
* Changing screen brightness from quick settings.
*/
- BRIGHTNESS_MIRROR(2) {
+ BRIGHTNESS_MIRROR(3) {
@Override
public void prepare(ScrimState previousState) {
mCurrentBehindAlpha = 0;
@@ -90,7 +101,7 @@
/**
* Always on display or screen off.
*/
- AOD(3) {
+ AOD(4) {
@Override
public void prepare(ScrimState previousState) {
final boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn();
@@ -110,7 +121,7 @@
/**
* When phone wakes up because you received a notification.
*/
- PULSING(4) {
+ PULSING(5) {
@Override
public void prepare(ScrimState previousState) {
mCurrentInFrontAlpha = 0;
@@ -125,7 +136,7 @@
/**
* Unlocked on top of an app (launcher or any other activity.)
*/
- UNLOCKED(5) {
+ UNLOCKED(6) {
@Override
public void prepare(ScrimState previousState) {
mCurrentBehindAlpha = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index d3fbe27..e4f142a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1296,7 +1296,7 @@
mDozeScrimController, keyguardViewMediator,
mScrimController, this, UnlockMethodCache.getInstance(mContext));
mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
- getBouncerContainer(), mFingerprintUnlockController);
+ getBouncerContainer(), mNotificationPanel, mFingerprintUnlockController);
mKeyguardIndicationController
.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
mFingerprintUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
@@ -3688,6 +3688,7 @@
public void finishKeyguardFadingAway() {
mKeyguardFadingAway = false;
mKeyguardMonitor.notifyKeyguardDoneFading();
+ mScrimController.setExpansionAffectsAlpha(true);
}
// TODO: Move this to NotificationLockscreenUserManager.
@@ -4603,6 +4604,7 @@
if (mAmbientIndicationContainer instanceof DozeReceiver) {
((DozeReceiver) mAmbientIndicationContainer).setDozing(mDozing);
}
+ mEntryManager.updateNotifications();
updateDozingState();
updateReportRejectedTouchVisibility();
Trace.endSection();
@@ -4617,8 +4619,14 @@
final boolean wakeAndUnlocking = mFingerprintUnlockController.getMode()
== FingerprintUnlockController.MODE_WAKE_AND_UNLOCK;
+ // Do not animate the scrim expansion when it's triggered by the fingerprint sensor.
+ mScrimController.setExpansionAffectsAlpha(mFingerprintUnlockController.getMode()
+ != FingerprintUnlockController.MODE_UNLOCK);
+
if (mBouncerShowing) {
- mScrimController.transitionTo(ScrimState.BOUNCER);
+ final boolean qsExpanded = mQSPanel != null && mQSPanel.isExpanded();
+ mScrimController.transitionTo(mIsOccluded || qsExpanded ?
+ ScrimState.BOUNCER_OCCLUDED : ScrimState.BOUNCER);
} else if (mLaunchCameraOnScreenTurningOn || isInLaunchTransition()) {
mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
} else if (mBrightnessMirrorVisible) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index a009d80..8d536d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -31,10 +31,10 @@
import android.view.ViewRootImpl;
import android.view.WindowManagerGlobal;
+import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.internal.util.LatencyTracker;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.DejankUtils;
import com.android.systemui.Dependency;
@@ -75,6 +75,7 @@
protected LockPatternUtils mLockPatternUtils;
protected ViewMediatorCallback mViewMediatorCallback;
protected StatusBar mStatusBar;
+ private NotificationPanelView mNotificationPanelView;
private FingerprintUnlockController mFingerprintUnlockController;
private ViewGroup mContainer;
@@ -88,6 +89,7 @@
protected boolean mFirstUpdate = true;
protected boolean mLastShowing;
protected boolean mLastOccluded;
+ private boolean mLastTracking;
private boolean mLastBouncerShowing;
private boolean mLastBouncerDismissible;
protected boolean mLastRemoteInputActive;
@@ -124,6 +126,7 @@
public void registerStatusBar(StatusBar statusBar,
ViewGroup container,
+ NotificationPanelView notificationPanelView,
FingerprintUnlockController fingerprintUnlockController,
DismissCallbackRegistry dismissCallbackRegistry) {
mStatusBar = statusBar;
@@ -131,6 +134,32 @@
mFingerprintUnlockController = fingerprintUnlockController;
mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
mViewMediatorCallback, mLockPatternUtils, container, dismissCallbackRegistry);
+ mNotificationPanelView = notificationPanelView;
+ notificationPanelView.setExpansionListener(this::onPanelExpansionChanged);
+ }
+
+ private void onPanelExpansionChanged(float expansion, boolean tracking) {
+ // We don't want to translate the bounce when the keyguard is occluded, because we're in
+ // a FLAG_SHOW_WHEN_LOCKED activity and need to conserve the original animation.
+ // We also don't want to show the bouncer when the user quickly taps on the display.
+ final boolean noLongerTracking = mLastTracking != tracking && !tracking;
+ if (mOccluded || mNotificationPanelView.isUnlockHintRunning()) {
+ mBouncer.setExpansion(0);
+ } else if (mShowing && mStatusBar.isKeyguardCurrentlySecure() && !mDozing) {
+ mBouncer.setExpansion(expansion);
+ if (expansion == 1) {
+ mBouncer.onFullyHidden();
+ updateStates();
+ } else if (!mBouncer.isShowing()) {
+ mBouncer.show(true /* resetSecuritySelection */, false /* notifyFalsing */);
+ } else if (noLongerTracking) {
+ // Notify that falsing manager should stop its session when user stops touching,
+ // even before the animation ends, to guarantee that we're not recording sensitive
+ // data.
+ mBouncer.onFullyShown();
+ }
+ }
+ mLastTracking = tracking;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index aec05cd..e5fefd3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -27,12 +27,9 @@
import android.metrics.LogMaker;
import android.os.AsyncTask;
import android.os.Bundle;
-import android.os.RemoteException;
import android.os.SystemClock;
import android.os.VibrationEffect;
-import android.os.Vibrator;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.TypedValue;
import android.view.HapticFeedbackConstants;
import android.view.InputDevice;
@@ -53,6 +50,7 @@
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.statusbar.VibratorHelper;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
@@ -75,7 +73,7 @@
private OnClickListener mOnClickListener;
private final KeyButtonRipple mRipple;
private final OverviewProxyService mOverviewProxyService;
- private final Vibrator mVibrator;
+ private final VibratorHelper mVibratorHelper;
private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
private final Runnable mCheckLongPress = new Runnable() {
@@ -128,7 +126,7 @@
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
mRipple = new KeyButtonRipple(context, this);
- mVibrator = mContext.getSystemService(Vibrator.class);
+ mVibratorHelper = Dependency.get(VibratorHelper.class);
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
setBackground(mRipple);
}
@@ -216,6 +214,9 @@
mGestureAborted = false;
}
if (mGestureAborted) {
+ if (mIsPressed) {
+ setPressed(false);
+ }
return false;
}
@@ -223,8 +224,10 @@
case MotionEvent.ACTION_DOWN:
mDownTime = SystemClock.uptimeMillis();
mLongClicked = false;
- mTouchDownX = (int) ev.getX();
- mTouchDownY = (int) ev.getY();
+
+ // Use raw X and Y to detect gestures in case a parent changes the x and y values
+ mTouchDownX = (int) ev.getRawX();
+ mTouchDownY = (int) ev.getRawY();
if (mCode != 0) {
sendEvent(KeyEvent.ACTION_DOWN, 0, mDownTime);
} else {
@@ -240,8 +243,8 @@
postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());
break;
case MotionEvent.ACTION_MOVE:
- x = (int)ev.getX();
- y = (int)ev.getY();
+ x = (int)ev.getRawX();
+ y = (int)ev.getRawY();
boolean exceededTouchSlopX = Math.abs(x - mTouchDownX) > mTouchSlop;
boolean exceededTouchSlopY = Math.abs(y - mTouchDownY) > mTouchSlop;
if (exceededTouchSlopX || exceededTouchSlopY) {
@@ -263,14 +266,17 @@
break;
case MotionEvent.ACTION_UP:
final boolean doIt = mIsPressed && !mLongClicked;
+ final boolean doHapticFeedback = (SystemClock.uptimeMillis() - mDownTime) > 150;
if (isProxyConnected) {
if (doIt) {
// Animate the ripple in on touch up with setPressed and then out later
setPressed(true);
- performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
+ if (doHapticFeedback) {
+ mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK);
+ }
playSoundEffect(SoundEffectConstants.CLICK);
}
- } else if ((SystemClock.uptimeMillis() - mDownTime) > 150 && !mLongClicked) {
+ } else if (doHapticFeedback && !mLongClicked) {
// Always send a release ourselves because it doesn't seem to be sent elsewhere
// and it feels weird to sometimes get a release haptic and other times not.
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY_RELEASE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index d3f74ef..a046675 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -205,13 +205,15 @@
}
MobileIconGroup hGroup = TelephonyIcons.THREE_G;
+ MobileIconGroup hPlusGroup = TelephonyIcons.THREE_G;
if (mConfig.hspaDataDistinguishable) {
hGroup = TelephonyIcons.H;
+ hPlusGroup = TelephonyIcons.H_PLUS;
}
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSDPA, hGroup);
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSUPA, hGroup);
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPA, hGroup);
- mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hGroup);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hPlusGroup);
if (mConfig.show4gForLte) {
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.FOUR_G);
@@ -278,6 +280,9 @@
String contentDescription = getStringIfExists(getContentDescription());
String dataContentDescription = getStringIfExists(icons.mDataContentDescription);
+ if (mCurrentState.inetCondition == 0) {
+ dataContentDescription = mContext.getString(R.string.data_connection_no_internet);
+ }
final boolean dataDisabled = mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED
&& mCurrentState.userSetup;
@@ -576,14 +581,13 @@
public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
- int discContentDesc, int dataContentDesc, int dataType, boolean isWide,
- int qsDataType) {
+ int discContentDesc, int dataContentDesc, int dataType, boolean isWide) {
super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState,
qsDiscState, discContentDesc);
mDataContentDescription = dataContentDesc;
mDataType = dataType;
mIsWide = isWide;
- mQsDataType = qsDataType;
+ mQsDataType = dataType; // TODO: remove this field
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 5363742..2258fa2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -884,6 +884,7 @@
datatype.equals("e") ? TelephonyIcons.E :
datatype.equals("g") ? TelephonyIcons.G :
datatype.equals("h") ? TelephonyIcons.H :
+ datatype.equals("h+") ? TelephonyIcons.H_PLUS :
datatype.equals("lte") ? TelephonyIcons.LTE :
datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS :
datatype.equals("dis") ? TelephonyIcons.DATA_DISABLED :
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 09a1e44..7e6fe02 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -21,28 +21,18 @@
class TelephonyIcons {
//***** Data connection icons
-
- static final int QS_DATA_G = R.drawable.ic_qs_signal_g;
- static final int QS_DATA_3G = R.drawable.ic_qs_signal_3g;
- static final int QS_DATA_E = R.drawable.ic_qs_signal_e;
- static final int QS_DATA_H = R.drawable.ic_qs_signal_h;
- static final int QS_DATA_1X = R.drawable.ic_qs_signal_1x;
- static final int QS_DATA_4G = R.drawable.ic_qs_signal_4g;
- static final int QS_DATA_4G_PLUS = R.drawable.ic_qs_signal_4g_plus;
- static final int QS_DATA_LTE = R.drawable.ic_qs_signal_lte;
- static final int QS_DATA_LTE_PLUS = R.drawable.ic_qs_signal_lte_plus;
-
static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode;
- static final int ICON_LTE = R.drawable.stat_sys_data_fully_connected_lte;
- static final int ICON_LTE_PLUS = R.drawable.stat_sys_data_fully_connected_lte_plus;
- static final int ICON_G = R.drawable.stat_sys_data_fully_connected_g;
- static final int ICON_E = R.drawable.stat_sys_data_fully_connected_e;
- static final int ICON_H = R.drawable.stat_sys_data_fully_connected_h;
- static final int ICON_3G = R.drawable.stat_sys_data_fully_connected_3g;
- static final int ICON_4G = R.drawable.stat_sys_data_fully_connected_4g;
- static final int ICON_4G_PLUS = R.drawable.stat_sys_data_fully_connected_4g_plus;
- static final int ICON_1X = R.drawable.stat_sys_data_fully_connected_1x;
+ static final int ICON_LTE = R.drawable.ic_lte_mobiledata;
+ static final int ICON_LTE_PLUS = R.drawable.ic_lte_plus_mobiledata;
+ static final int ICON_G = R.drawable.ic_g_mobiledata;
+ static final int ICON_E = R.drawable.ic_e_mobiledata;
+ static final int ICON_H = R.drawable.ic_h_mobiledata;
+ static final int ICON_H_PLUS = R.drawable.ic_h_plus_mobiledata;
+ static final int ICON_3G = R.drawable.ic_3g_mobiledata;
+ static final int ICON_4G = R.drawable.ic_4g_mobiledata;
+ static final int ICON_4G_PLUS = R.drawable.ic_4g_plus_mobiledata;
+ static final int ICON_1X = R.drawable.ic_1x_mobiledata;
static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup(
"CARRIER_NETWORK_CHANGE",
@@ -53,11 +43,9 @@
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
- R.string.accessibility_carrier_network_change_mode,
+ R.string.carrier_network_change_mode,
0,
- false,
- 0
- );
+ false);
static final MobileIconGroup THREE_G = new MobileIconGroup(
"3G",
@@ -68,11 +56,9 @@
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
- R.string.accessibility_data_connection_3g,
+ R.string.data_connection_3g,
TelephonyIcons.ICON_3G,
- true,
- TelephonyIcons.QS_DATA_3G
- );
+ true);
static final MobileIconGroup WFC = new MobileIconGroup(
"WFC",
@@ -83,8 +69,7 @@
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
- 0, 0, false, 0
- );
+ 0, 0, false);
static final MobileIconGroup UNKNOWN = new MobileIconGroup(
"Unknown",
@@ -95,8 +80,7 @@
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
- 0, 0, false, 0
- );
+ 0, 0, false);
static final MobileIconGroup E = new MobileIconGroup(
"E",
@@ -107,11 +91,9 @@
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
- R.string.accessibility_data_connection_edge,
+ R.string.data_connection_edge,
TelephonyIcons.ICON_E,
- false,
- TelephonyIcons.QS_DATA_E
- );
+ false);
static final MobileIconGroup ONE_X = new MobileIconGroup(
"1X",
@@ -122,11 +104,9 @@
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
- R.string.accessibility_data_connection_cdma,
+ R.string.data_connection_cdma,
TelephonyIcons.ICON_1X,
- true,
- TelephonyIcons.QS_DATA_1X
- );
+ true);
static final MobileIconGroup G = new MobileIconGroup(
"G",
@@ -137,11 +117,9 @@
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
- R.string.accessibility_data_connection_gprs,
+ R.string.data_connection_gprs,
TelephonyIcons.ICON_G,
- false,
- TelephonyIcons.QS_DATA_G
- );
+ false);
static final MobileIconGroup H = new MobileIconGroup(
"H",
@@ -152,11 +130,22 @@
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
- R.string.accessibility_data_connection_3_5g,
+ R.string.data_connection_3_5g,
TelephonyIcons.ICON_H,
- false,
- TelephonyIcons.QS_DATA_H
- );
+ false);
+
+ static final MobileIconGroup H_PLUS = new MobileIconGroup(
+ "H+",
+ null,
+ null,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+ 0, 0,
+ 0,
+ 0,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+ R.string.data_connection_3_5g_plus,
+ TelephonyIcons.ICON_H_PLUS,
+ false);
static final MobileIconGroup FOUR_G = new MobileIconGroup(
"4G",
@@ -167,11 +156,9 @@
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
- R.string.accessibility_data_connection_4g,
+ R.string.data_connection_4g,
TelephonyIcons.ICON_4G,
- true,
- TelephonyIcons.QS_DATA_4G
- );
+ true);
static final MobileIconGroup FOUR_G_PLUS = new MobileIconGroup(
"4G+",
@@ -182,11 +169,9 @@
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
- R.string.accessibility_data_connection_4g_plus,
+ R.string.data_connection_4g_plus,
TelephonyIcons.ICON_4G_PLUS,
- true,
- TelephonyIcons.QS_DATA_4G_PLUS
- );
+ true);
static final MobileIconGroup LTE = new MobileIconGroup(
"LTE",
@@ -197,11 +182,9 @@
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
- R.string.accessibility_data_connection_lte,
+ R.string.data_connection_lte,
TelephonyIcons.ICON_LTE,
- true,
- TelephonyIcons.QS_DATA_LTE
- );
+ true);
static final MobileIconGroup LTE_PLUS = new MobileIconGroup(
"LTE+",
@@ -212,11 +195,9 @@
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
- R.string.accessibility_data_connection_lte_plus,
+ R.string.data_connection_lte_plus,
TelephonyIcons.ICON_LTE_PLUS,
- true,
- TelephonyIcons.QS_DATA_LTE_PLUS
- );
+ true);
static final MobileIconGroup DATA_DISABLED = new MobileIconGroup(
"DataDisabled",
@@ -227,10 +208,8 @@
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
- R.string.accessibility_cell_data_off,
+ R.string.cell_data_off,
0,
- false,
- 0
- );
+ false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index 2819624..b4c3eca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -84,8 +84,7 @@
boolean ssidPresent = wifiVisible && mCurrentState.ssid != null;
String contentDescription = getStringIfExists(getContentDescription());
if (mCurrentState.inetCondition == 0) {
- contentDescription +=
- ("," + mContext.getString(R.string.accessibility_quick_settings_no_internet));
+ contentDescription += ("," + mContext.getString(R.string.data_connection_no_internet));
}
IconState statusIcon = new IconState(wifiVisible, getCurrentIconId(), contentDescription);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 716b58841..22bf983 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -23,6 +23,8 @@
import static android.media.AudioManager.RINGER_MODE_SILENT;
import static android.media.AudioManager.RINGER_MODE_VIBRATE;
import static android.media.AudioManager.STREAM_ACCESSIBILITY;
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
import static com.android.systemui.volume.Events.DISMISS_REASON_SETTINGS_CLICKED;
@@ -81,6 +83,7 @@
import com.android.systemui.plugins.VolumeDialogController.State;
import com.android.systemui.plugins.VolumeDialogController.StreamState;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -102,6 +105,7 @@
private final Context mContext;
private final H mHandler = new H();
private final VolumeDialogController mController;
+ private final DeviceProvisionedController mDeviceProvisionedController;
private Window mWindow;
private CustomDialog mDialog;
@@ -109,6 +113,7 @@
private ViewGroup mDialogRowsView;
private ViewGroup mRinger;
private ImageButton mRingerIcon;
+ private View mSettingsView;
private ImageButton mSettingsIcon;
private ImageView mZenIcon;
private final List<VolumeRow> mRows = new ArrayList<>();
@@ -139,6 +144,7 @@
mAccessibilityMgr = Dependency.get(AccessibilityManagerWrapper.class);
mActiveSliderTint = ColorStateList.valueOf(Utils.getColorAccent(mContext));
mInactiveSliderTint = loadColorStateList(R.color.volume_slider_inactive);
+ mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
}
public void init(int windowType, Callback callback) {
@@ -207,13 +213,12 @@
rescheduleTimeoutH();
return true;
});
- VolumeUiLayout uiLayout = VolumeUiLayout.get(mDialogView);
- uiLayout.updateRotation();
mDialogRowsView = mDialog.findViewById(R.id.volume_dialog_rows);
mRinger = mDialog.findViewById(R.id.ringer);
mRingerIcon = mRinger.findViewById(R.id.ringer_icon);
mZenIcon = mRinger.findViewById(R.id.dnd_icon);
+ mSettingsView = mDialog.findViewById(R.id.settings_container);
mSettingsIcon = mDialog.findViewById(R.id.settings);
if (mRows.isEmpty()) {
@@ -389,6 +394,8 @@
}
public void initSettingsH() {
+ mSettingsView.setVisibility(
+ mDeviceProvisionedController.isDeviceProvisioned() ? VISIBLE : GONE);
mSettingsIcon.setOnClickListener(v -> {
Intent intent = new Intent(Settings.ACTION_SOUND_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -609,7 +616,7 @@
* @param enable whether to enable volume row views and hide dnd icon
*/
private void enableVolumeRowViewsH(VolumeRow row, boolean enable) {
- row.dndIcon.setVisibility(enable ? View.GONE : View.VISIBLE);
+ row.dndIcon.setVisibility(enable ? GONE : VISIBLE);
}
/**
@@ -619,7 +626,7 @@
*/
private void enableRingerViewsH(boolean enable) {
mRingerIcon.setEnabled(enable);
- mZenIcon.setVisibility(enable ? View.GONE : View.VISIBLE);
+ mZenIcon.setVisibility(enable ? GONE : VISIBLE);
}
private void trimObsoleteH() {
@@ -799,7 +806,7 @@
}
final int progress = row.slider.getProgress();
final int level = getImpliedLevel(row.slider, progress);
- final boolean rowVisible = row.view.getVisibility() == View.VISIBLE;
+ final boolean rowVisible = row.view.getVisibility() == VISIBLE;
final boolean inGracePeriod = (SystemClock.uptimeMillis() - row.userAttempt)
< USER_ATTEMPT_GRACE_PERIOD;
mHandler.removeMessages(H.RECHECK, row);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java
deleted file mode 100644
index 0a3a2ab..0000000
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.volume;
-
-import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.DisplayCutout;
-import android.view.View;
-import android.view.ViewOutlineProvider;
-import android.view.ViewTreeObserver;
-import android.widget.FrameLayout;
-
-import com.android.systemui.R;
-import com.android.systemui.util.leak.RotationUtils;
-
-public class VolumeUiLayout extends FrameLayout {
-
- private View mChild;
- private int mRotation = ROTATION_NONE;
- @Nullable
- private DisplayCutout mDisplayCutout;
-
- public VolumeUiLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- mDisplayCutout = null;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- if (mChild == null) {
- if (getChildCount() != 0) {
- mChild = getChildAt(0);
- updateRotation();
- } else {
- return;
- }
- }
- }
-
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- updateRotation();
- }
-
- private void setDisplayCutout() {
- if (mDisplayCutout == null && getRootWindowInsets() != null) {
- DisplayCutout cutout = getRootWindowInsets().getDisplayCutout();
- if (cutout != null) {
- mDisplayCutout = cutout;
- }
- }
- }
-
- public void updateRotation() {
- setDisplayCutout();
- if (mChild == null) {
- if (getChildCount() != 0) {
- mChild = getChildAt(0);
- }
- }
- int rotation = RotationUtils.getRotation(getContext());
- if (rotation != mRotation) {
- updateSafeInsets(rotation);
- mRotation = rotation;
- }
- }
-
- private void updateSafeInsets(int rotation) {
- // Depending on our rotation, we may have to work around letterboxing from the right
- // side from the navigation bar or a cutout.
-
- MarginLayoutParams lp = (MarginLayoutParams) mChild.getLayoutParams();
-
- int margin = (int) getResources().getDimension(R.dimen.volume_dialog_base_margin);
- switch (rotation) {
- /*
- * Landscape: <-|. Have to deal with the nav bar
- * Seascape: |->. Have to deal with the cutout
- */
- case RotationUtils.ROTATION_LANDSCAPE:
- margin += getNavBarHeight();
- break;
- case RotationUtils.ROTATION_SEASCAPE:
- margin += getDisplayCutoutHeight();
- break;
- default:
- break;
- }
-
- lp.rightMargin = margin;
- mChild.setLayoutParams(lp);
- }
-
- private int getNavBarHeight() {
- return (int) getResources().getDimension(R.dimen.navigation_bar_size);
- }
-
- //TODO: Find a better way
- private int getDisplayCutoutHeight() {
- if (mDisplayCutout == null || mDisplayCutout.isEmpty()) {
- return 0;
- }
-
- Rect r = mDisplayCutout.getBoundingRect();
- return r.bottom - r.top;
- }
-
- @Override
- public ViewOutlineProvider getOutlineProvider() {
- return super.getOutlineProvider();
- }
-
- public static VolumeUiLayout get(View v) {
- if (v instanceof VolumeUiLayout) return (VolumeUiLayout) v;
- if (v.getParent() instanceof View) {
- return get((View) v.getParent());
- }
- return null;
- }
-}
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 b8d9b19..01664b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -18,6 +18,8 @@
import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_MIN;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME;
import static android.view.View.GONE;
@@ -147,6 +149,7 @@
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
final TextView textView = mNotificationInfo.findViewById(R.id.pkgname);
assertTrue(textView.getText().toString().contains("App Name"));
+ assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
}
@Test
@@ -213,6 +216,27 @@
}
@Test
+ public void testBindNotification_BlockButton() throws Exception {
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
+ final View block = mNotificationInfo.findViewById(R.id.block);
+ final View minimize = mNotificationInfo.findViewById(R.id.minimize);
+ assertEquals(VISIBLE, block.getVisibility());
+ assertEquals(GONE, minimize.getVisibility());
+ }
+
+ @Test
+ public void testBindNotification_MinButton() throws Exception {
+ mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
+ final View block = mNotificationInfo.findViewById(R.id.block);
+ final View minimize = mNotificationInfo.findViewById(R.id.minimize);
+ assertEquals(GONE, block.getVisibility());
+ assertEquals(VISIBLE, minimize.getVisibility());
+ }
+
+ @Test
public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -324,6 +348,18 @@
}
@Test
+ public void testDoesNotUpdateNotificationChannelAfterImportanceChangedMin()
+ throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
+
+ mNotificationInfo.findViewById(R.id.minimize).performClick();
+ verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+ anyString(), eq(TEST_UID), any());
+ }
+
+ @Test
public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged()
throws Exception {
int originalImportance = mNotificationChannel.getImportance();
@@ -377,6 +413,39 @@
anyString(), eq(TEST_UID), updated.capture());
assertTrue((updated.getValue().getUserLockedFields()
& USER_LOCKED_IMPORTANCE) != 0);
+ assertEquals(IMPORTANCE_NONE, updated.getValue().getImportance());
+ }
+
+ @Test
+ public void testNonBlockableAppDoesNotBecomeMin() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null,
+ null, Collections.singleton(TEST_PACKAGE_NAME));
+ mNotificationInfo.findViewById(R.id.minimize).performClick();
+ waitForUndoButton();
+ verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+ anyString(), eq(TEST_UID), any());
+ }
+
+ @Test
+ public void testMinChangedCallsUpdateNotificationChannel() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
+
+ mNotificationInfo.findViewById(R.id.minimize).performClick();
+ waitForUndoButton();
+ mNotificationInfo.handleCloseControls(true, false);
+
+ ArgumentCaptor<NotificationChannel> updated =
+ ArgumentCaptor.forClass(NotificationChannel.class);
+ verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+ anyString(), eq(TEST_UID), updated.capture());
+ assertTrue((updated.getValue().getUserLockedFields()
+ & USER_LOCKED_IMPORTANCE) != 0);
+ assertEquals(IMPORTANCE_MIN, updated.getValue().getImportance());
}
@Test
@@ -416,6 +485,40 @@
}
@Test
+ public void testMinUndoDoesNotMinNotificationChannel() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
+
+ mNotificationInfo.findViewById(R.id.minimize).performClick();
+ waitForUndoButton();
+ mNotificationInfo.findViewById(R.id.undo).performClick();
+ waitForStopButton();
+ mNotificationInfo.handleCloseControls(true, false);
+
+ ArgumentCaptor<NotificationChannel> updated =
+ ArgumentCaptor.forClass(NotificationChannel.class);
+ verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+ anyString(), eq(TEST_UID), updated.capture());
+ assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
+ assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
+ }
+
+ @Test
+ public void testCloseControlsDoesNotUpdateiMinIfSaveIsFalse() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null,
+ Collections.singleton(TEST_PACKAGE_NAME));
+
+ mNotificationInfo.findViewById(R.id.minimize).performClick();
+ waitForUndoButton();
+ mNotificationInfo.handleCloseControls(false, false);
+ verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+ eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
+ }
+
+ @Test
public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -557,4 +660,57 @@
public void testWillBeRemovedReturnsFalseBeforeBind() throws Exception {
assertFalse(mNotificationInfo.willBeRemoved());
}
+
+ @Test
+ public void testUndoText_min() throws Exception {
+ mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null,
+ Collections.singleton(TEST_PACKAGE_NAME));
+
+ mNotificationInfo.findViewById(R.id.minimize).performClick();
+ waitForUndoButton();
+ TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
+ assertTrue(confirmationText.getText().toString().contains("minimized"));
+ }
+
+ @Test
+ public void testUndoText_block() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null,
+ Collections.singleton(TEST_PACKAGE_NAME));
+
+ mNotificationInfo.findViewById(R.id.block).performClick();
+ waitForUndoButton();
+ TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
+ assertTrue(confirmationText.getText().toString().contains("won't see"));
+ }
+
+ @Test
+ public void testNoHeaderOnConfirmation() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null,
+ Collections.singleton(TEST_PACKAGE_NAME));
+
+ mNotificationInfo.findViewById(R.id.block).performClick();
+ waitForUndoButton();
+ assertEquals(GONE, mNotificationInfo.findViewById(R.id.header).getVisibility());
+ }
+
+ @Test
+ public void testHeaderOnUndo() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null,
+ Collections.singleton(TEST_PACKAGE_NAME));
+
+ mNotificationInfo.findViewById(R.id.block).performClick();
+ waitForUndoButton();
+ mNotificationInfo.findViewById(R.id.undo).performClick();
+ waitForStopButton();
+ assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
index a80b045..36fd499 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
@@ -19,6 +19,7 @@
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import android.os.Handler;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -27,12 +28,14 @@
import com.android.systemui.Dependency;
import com.android.systemui.Prefs;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.qs.AutoAddTracker;
import com.android.systemui.qs.QSTileHost;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@@ -40,16 +43,15 @@
public class AutoTileManagerTest extends SysuiTestCase {
@Mock private QSTileHost mQsTileHost;
+ @Mock private AutoAddTracker mAutoAddTracker;
private AutoTileManager mAutoTileManager;
@Before
public void setUp() throws Exception {
- mDependency.injectTestDependency(Dependency.BG_LOOPER,
- TestableLooper.get(this).getLooper());
- Prefs.putBoolean(mContext, Prefs.Key.QS_NIGHTDISPLAY_ADDED, false);
- mQsTileHost = Mockito.mock(QSTileHost.class);
- mAutoTileManager = new AutoTileManager(mContext, mQsTileHost);
+ MockitoAnnotations.initMocks(this);
+ mAutoTileManager = new AutoTileManager(mContext, mAutoAddTracker, mQsTileHost,
+ new Handler(TestableLooper.get(this).getLooper()));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java
index 500d620..667a508 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java
@@ -88,6 +88,25 @@
ev.recycle();
}
+
+ @Test
+ public void testNearestView_DetachedViewsExcluded() {
+ View left = mockViewAt(0, 0, 10, 10);
+ when(left.isAttachedToWindow()).thenReturn(false);
+ View right = mockViewAt(20, 0, 10, 10);
+
+ mNearestTouchFrame.addView(left);
+ mNearestTouchFrame.addView(right);
+ mNearestTouchFrame.onMeasure(0, 0);
+
+ // Would go to left view if attached, but goes to right instead as left should be detached.
+ MotionEvent ev = MotionEvent.obtain(0, 0, 0,
+ 12 /* x */, 5 /* y */, 0);
+ mNearestTouchFrame.onTouchEvent(ev);
+ verify(right).onTouchEvent(eq(ev));
+ ev.recycle();
+ }
+
@Test
public void testHorizontalSelection_Left() {
View left = mockViewAt(0, 0, 10, 10);
@@ -161,6 +180,7 @@
return null;
}).when(v).getLocationInWindow(any());
when(v.isClickable()).thenReturn(true);
+ when(v.isAttachedToWindow()).thenReturn(true);
// Stupid final methods.
v.setLeft(0);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index 3ed2fe1..6fbc0d7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -170,12 +170,22 @@
}
@Test
- public void transitionToBouncer() {
+ public void transitionToKeyguardBouncer() {
mScrimController.transitionTo(ScrimState.BOUNCER);
mScrimController.finishAnimationsImmediately();
// Front scrim should be transparent
// Back scrim should be visible without tint
- assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
+ assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
+ assertScrimTint(mScrimBehind, false /* tinted */);
+ }
+
+ @Test
+ public void transitionToBouncer() {
+ mScrimController.transitionTo(ScrimState.BOUNCER_OCCLUDED);
+ mScrimController.finishAnimationsImmediately();
+ // Front scrim should be transparent
+ // Back scrim should be visible without tint
+ assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
assertScrimTint(mScrimBehind, false /* tinted */);
}
@@ -196,6 +206,25 @@
}
@Test
+ public void panelExpansionAffectsAlpha() {
+ mScrimController.setPanelExpansion(0f);
+ mScrimController.setPanelExpansion(0.5f);
+ mScrimController.transitionTo(ScrimState.UNLOCKED);
+ mScrimController.finishAnimationsImmediately();
+
+ final float scrimAlpha = mScrimBehind.getViewAlpha();
+ mScrimController.setExpansionAffectsAlpha(false);
+ mScrimController.setPanelExpansion(0.8f);
+ Assert.assertEquals("Scrim opacity shouldn't change when setExpansionAffectsAlpha "
+ + "is false", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
+
+ mScrimController.setExpansionAffectsAlpha(true);
+ mScrimController.setPanelExpansion(0.1f);
+ Assert.assertNotEquals("Scrim opacity should change when setExpansionAffectsAlpha "
+ + "is true", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
+ }
+
+ @Test
public void transitionToUnlockedFromAod() {
// Simulate unlock with fingerprint
mScrimController.transitionTo(ScrimState.AOD);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index ff545f0..14baaeb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -346,7 +346,7 @@
public void testShouldPeek_nonSuppressedGroupSummary() {
when(mPowerManager.isScreenOn()).thenReturn(true);
when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
- when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(false);
+ when(mNotificationData.shouldSuppressStatusBar(any())).thenReturn(false);
when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
when(mSystemServicesProxy.isDreaming()).thenReturn(false);
when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
@@ -367,7 +367,7 @@
public void testShouldPeek_suppressedGroupSummary() {
when(mPowerManager.isScreenOn()).thenReturn(true);
when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
- when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(false);
+ when(mNotificationData.shouldSuppressStatusBar(any())).thenReturn(false);
when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
when(mSystemServicesProxy.isDreaming()).thenReturn(false);
when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
@@ -385,16 +385,32 @@
}
@Test
- public void testShouldPeek_suppressedScreenOn_dozing() {
+ public void testShouldPeek_suppressedPeek() {
when(mPowerManager.isScreenOn()).thenReturn(true);
when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
when(mSystemServicesProxy.isDreaming()).thenReturn(false);
when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
- mStatusBar.mDozing = true;
- when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(true);
- when(mNotificationData.shouldSuppressScreenOff(any())).thenReturn(false);
+ when(mNotificationData.shouldSuppressPeek(any())).thenReturn(true);
+
+ Notification n = new Notification.Builder(getContext(), "a").build();
+ StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
+ UserHandle.of(0), null, 0);
+ NotificationData.Entry entry = new NotificationData.Entry(sbn);
+
+ assertFalse(mEntryManager.shouldPeek(entry, sbn));
+ }
+
+ @Test
+ public void testShouldPeek_noSuppressedPeek() {
+ when(mPowerManager.isScreenOn()).thenReturn(true);
+ when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
+ when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
+ when(mSystemServicesProxy.isDreaming()).thenReturn(false);
+ when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
+
+ when(mNotificationData.shouldSuppressPeek(any())).thenReturn(false);
Notification n = new Notification.Builder(getContext(), "a").build();
StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
@@ -405,63 +421,6 @@
}
@Test
- public void testShouldPeek_suppressedScreenOn_noDoze() {
- when(mPowerManager.isScreenOn()).thenReturn(true);
- when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
- when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
- when(mSystemServicesProxy.isDreaming()).thenReturn(false);
- when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
-
- mStatusBar.mDozing = false;
- when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(true);
- when(mNotificationData.shouldSuppressScreenOff(any())).thenReturn(false);
-
- Notification n = new Notification.Builder(getContext(), "a").build();
- StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
- UserHandle.of(0), null, 0);
- NotificationData.Entry entry = new NotificationData.Entry(sbn);
- assertFalse(mEntryManager.shouldPeek(entry, sbn));
- }
- @Test
- public void testShouldPeek_suppressedScreenOff_dozing() {
- when(mPowerManager.isScreenOn()).thenReturn(true);
- when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
- when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
- when(mSystemServicesProxy.isDreaming()).thenReturn(false);
- when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
-
- mStatusBar.mDozing = true;
- when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(false);
- when(mNotificationData.shouldSuppressScreenOff(any())).thenReturn(true);
-
- Notification n = new Notification.Builder(getContext(), "a").build();
- StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
- UserHandle.of(0), null, 0);
- NotificationData.Entry entry = new NotificationData.Entry(sbn);
- assertFalse(mEntryManager.shouldPeek(entry, sbn));
- }
-
- @Test
- public void testShouldPeek_suppressedScreenOff_noDoze() {
- when(mPowerManager.isScreenOn()).thenReturn(true);
- when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
- when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
- when(mSystemServicesProxy.isDreaming()).thenReturn(false);
- when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
-
- mStatusBar.mDozing = false;
- when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(false);
- when(mNotificationData.shouldSuppressScreenOff(any())).thenReturn(true);
-
- Notification n = new Notification.Builder(getContext(), "a").build();
- StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
- UserHandle.of(0), null, 0);
- NotificationData.Entry entry = new NotificationData.Entry(sbn);
- assertTrue(mEntryManager.shouldPeek(entry, sbn));
- }
-
-
- @Test
public void testLogHidden() {
try {
mStatusBar.handleVisibleToUserChanged(false);
@@ -574,6 +533,7 @@
public void testFingerprintNotification_UpdatesScrims() {
mStatusBar.mStatusBarWindowManager = mock(StatusBarWindowManager.class);
mStatusBar.mDozeScrimController = mock(DozeScrimController.class);
+ mStatusBar.mNotificationIconAreaController = mock(NotificationIconAreaController.class);
mStatusBar.notifyFpAuthModeChanged();
verify(mScrimController).transitionTo(any(), any());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
index e3558d4..2afb48c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
@@ -111,8 +111,8 @@
boolean out = true;
String typeDescription = "Test 1";
String description = "Test 2";
- int type = R.drawable.stat_sys_data_fully_connected_1x;
- int qsType = R.drawable.ic_qs_signal_1x;
+ int type = TelephonyIcons.ICON_1X;
+ int qsType = TelephonyIcons.ICON_1X;
boolean wide = true;
int subId = 5;
boolean roaming = true;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 27cd9a0..714ad1f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -70,7 +70,7 @@
protected static final int DEFAULT_SIGNAL_STRENGTH = DEFAULT_LEVEL;
protected static final int DEFAULT_QS_SIGNAL_STRENGTH = DEFAULT_LEVEL;
protected static final int DEFAULT_ICON = TelephonyIcons.ICON_3G;
- protected static final int DEFAULT_QS_ICON = TelephonyIcons.QS_DATA_3G;
+ protected static final int DEFAULT_QS_ICON = TelephonyIcons.ICON_3G;
protected NetworkControllerImpl mNetworkController;
protected MobileSignalController mMobileSignalController;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index cf3620d..365a9b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -6,7 +6,6 @@
import android.net.NetworkCapabilities;
import android.os.Looper;
-import android.support.test.runner.AndroidJUnit4;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
@@ -15,7 +14,6 @@
import com.android.settingslib.net.DataUsageController;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -28,8 +26,7 @@
public void test3gDataIcon() {
setupDefaultSignal();
- verifyDataIndicators(TelephonyIcons.ICON_3G,
- TelephonyIcons.QS_DATA_3G);
+ verifyDataIndicators(TelephonyIcons.ICON_3G);
}
@Test
@@ -38,8 +35,7 @@
updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
TelephonyManager.NETWORK_TYPE_GSM);
- verifyDataIndicators(TelephonyIcons.ICON_G,
- TelephonyIcons.QS_DATA_G);
+ verifyDataIndicators(TelephonyIcons.ICON_G);
}
@Test
@@ -48,8 +44,7 @@
updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
TelephonyManager.NETWORK_TYPE_CDMA);
- verifyDataIndicators(TelephonyIcons.ICON_1X,
- TelephonyIcons.QS_DATA_1X);
+ verifyDataIndicators(TelephonyIcons.ICON_1X);
}
@Test
@@ -58,8 +53,7 @@
updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
TelephonyManager.NETWORK_TYPE_EDGE);
- verifyDataIndicators(TelephonyIcons.ICON_E,
- TelephonyIcons.QS_DATA_E);
+ verifyDataIndicators(TelephonyIcons.ICON_E);
}
@Test
@@ -68,8 +62,7 @@
updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
TelephonyManager.NETWORK_TYPE_LTE);
- verifyDataIndicators(TelephonyIcons.ICON_LTE,
- TelephonyIcons.QS_DATA_LTE);
+ verifyDataIndicators(TelephonyIcons.ICON_LTE);
}
@Test
@@ -78,17 +71,27 @@
updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
TelephonyManager.NETWORK_TYPE_HSPA);
- verifyDataIndicators(TelephonyIcons.ICON_H,
- TelephonyIcons.QS_DATA_H);
+ verifyDataIndicators(TelephonyIcons.ICON_H);
}
+
+ @Test
+ public void testHspaPlusDataIcon() {
+ setupDefaultSignal();
+ updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.NETWORK_TYPE_HSPAP);
+
+ verifyDataIndicators(TelephonyIcons.ICON_H_PLUS);
+ }
+
+
@Test
public void testWfcNoDataIcon() {
setupDefaultSignal();
updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
TelephonyManager.NETWORK_TYPE_IWLAN);
- verifyDataIndicators(0, 0);
+ verifyDataIndicators(0);
}
@Test
@@ -106,8 +109,7 @@
updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
TelephonyManager.NETWORK_TYPE_LTE);
- verifyDataIndicators(TelephonyIcons.ICON_4G,
- TelephonyIcons.QS_DATA_4G);
+ verifyDataIndicators(TelephonyIcons.ICON_4G);
}
@Test
@@ -150,7 +152,7 @@
TestableLooper.get(this).processAllMessages();
// Don't show the X until the device is setup.
- verifyDataIndicators(0, 0);
+ verifyDataIndicators(0);
}
@Test
@@ -165,8 +167,7 @@
mConfig.alwaysShowDataRatIcon = true;
mNetworkController.handleConfigurationChanged();
- verifyDataIndicators(TelephonyIcons.ICON_G,
- TelephonyIcons.QS_DATA_G);
+ verifyDataIndicators(TelephonyIcons.ICON_G);
}
@Test
@@ -182,8 +183,7 @@
// the after work.
mNetworkController.handleConfigurationChanged();
- verifyDataIndicators(TelephonyIcons.ICON_4G,
- TelephonyIcons.QS_DATA_4G);
+ verifyDataIndicators(TelephonyIcons.ICON_4G);
}
@Test
@@ -192,14 +192,12 @@
updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
TelephonyManager.NETWORK_TYPE_LTE);
- verifyDataIndicators(TelephonyIcons.ICON_LTE,
- TelephonyIcons.QS_DATA_LTE);
+ verifyDataIndicators(TelephonyIcons.ICON_LTE);
when(mServiceState.getDataNetworkType())
.thenReturn(TelephonyManager.NETWORK_TYPE_HSPA);
updateServiceState();
- verifyDataIndicators(TelephonyIcons.ICON_H,
- TelephonyIcons.QS_DATA_H);
+ verifyDataIndicators(TelephonyIcons.ICON_H);
}
@Test
@@ -219,9 +217,9 @@
DEFAULT_QS_SIGNAL_STRENGTH, DEFAULT_QS_ICON, in, out);
}
- private void verifyDataIndicators(int dataIcon, int qsDataIcon) {
+ private void verifyDataIndicators(int dataIcon) {
verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, dataIcon,
- true, DEFAULT_QS_SIGNAL_STRENGTH, qsDataIcon, false,
+ true, DEFAULT_QS_SIGNAL_STRENGTH, dataIcon, false,
false);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 550f4a7..33aa417 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -223,7 +223,7 @@
verifyLastQsMobileDataIndicators(true,
testStrength,
- TelephonyIcons.QS_DATA_1X, false, false);
+ TelephonyIcons.ICON_1X, false, false);
}
}
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.mk b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.mk
new file mode 100644
index 0000000..d83b30a
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := DisplayCutoutEmulationDouble
+LOCAL_CERTIFICATE := platform
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := DisplayCutoutEmulationDoubleOverlay
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_RRO_PACKAGE)
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/AndroidManifest.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/AndroidManifest.xml
new file mode 100644
index 0000000..5d3385d
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<!--
+ ~ Copyright (C) 2018 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.internal.display.cutout.emulation.double"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <overlay android:targetPackage="android"
+ android:category="com.android.internal.display_cutout_emulation"
+ android:priority="1"/>
+
+ <application android:label="@string/display_cutout_emulation_overlay" android:hasCode="false"/>
+</manifest>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml
new file mode 100644
index 0000000..ca261f9
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml
@@ -0,0 +1,67 @@
+<!--
+ ~ Copyright (C) 2018 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.
+ -->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- The bounding path of the cutout region of the main built-in display.
+ Must either be empty if there is no cutout region, or a string that is parsable by
+ {@link android.util.PathParser}.
+
+ The path is assumed to be specified in display coordinates with pixel units and in
+ the display's native orientation, with the origin of the coordinate system at the
+ center top of the display.
+
+ To facilitate writing device-independent emulation overlays, the marker `@dp` can be
+ appended after the path string to interpret coordinates in dp instead of px units.
+ Note that a physical cutout should be configured in pixels for the best results.
+ -->
+ <string translatable="false" name="config_mainBuiltInDisplayCutout">
+ M 0,0
+ L -72, 0
+ L -69.9940446283, 20.0595537175
+ C -69.1582133885, 28.4178661152 -65.2, 32.0 -56.8, 32.0
+ L 56.8, 32.0
+ C 65.2, 32.0 69.1582133885, 28.4178661152 69.9940446283, 20.0595537175
+ L 72, 0
+ Z
+ @bottom
+ M 0,0
+ L -72, 0
+ L -69.9940446283, -20.0595537175
+ C -69.1582133885, -28.4178661152 -65.2, -32.0 -56.8, -32.0
+ L 56.8, -32.0
+ C 65.2, -32.0 69.1582133885, -28.4178661152 69.9940446283, -20.0595537175
+ L 72, 0
+ Z
+ @dp
+ </string>
+
+ <!-- Whether the display cutout region of the main built-in display should be forced to
+ black in software (to avoid aliasing or emulate a cutout that is not physically existent).
+ -->
+ <bool name="config_fillMainBuiltInDisplayCutout">true</bool>
+
+ <!-- Height of the status bar -->
+ <dimen name="status_bar_height_portrait">48dp</dimen>
+ <dimen name="status_bar_height_landscape">28dp</dimen>
+ <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
+ <dimen name="quick_qs_offset_height">48dp</dimen>
+ <!-- Total height of QQS (quick_qs_offset_height + 128) -->
+ <dimen name="quick_qs_total_height">176dp</dimen>
+
+</resources>
+
+
diff --git a/packages/SystemUI/res/values-h650dp/dimens.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml
similarity index 66%
copy from packages/SystemUI/res/values-h650dp/dimens.xml
copy to packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml
index 8a00953..68c2dcb 100644
--- a/packages/SystemUI/res/values-h650dp/dimens.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml
@@ -1,5 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2014 The Android Open Source Project
+ ~ Copyright (C) 2018 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.
@@ -11,9 +12,11 @@
~ 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
+ ~ limitations under the License.
-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-<resources>
- <dimen name="keyguard_clock_notifications_margin">32dp</dimen>
-</resources>
\ No newline at end of file
+ <string name="display_cutout_emulation_overlay">Double display cutout</string>
+
+</resources>
+
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml
index ddac106..41a2940 100644
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml
+++ b/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml
@@ -7,5 +7,6 @@
<item name="android:colorAccent">@*android:color/accent_device_default_dark</item>
<item name="android:colorControlNormal">?android:attr/textColorPrimary</item>
<item name="android:colorBackgroundFloating">@*android:color/material_grey_900</item>
+ <item name="android:panelColorBackground">@*android:color/material_grey_800</item>
</style>
</resources>
\ No newline at end of file
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index e962c0b..d89cc96 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -5363,7 +5363,6 @@
// OS: P
ACTION_PANEL_VIEW_EXPAND = 1328;
-
// FIELD: Rotation of the device
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: P
@@ -5453,6 +5452,57 @@
// OS: P
ACTION_OPS_GUTS_SETTINGS = 1346;
+ // ACTION: Settings > Battery settings > Battery tip > App restriction tip
+ // OS: P
+ ACTION_APP_RESTRICTION_TIP = 1347;
+
+ // ACTION: Settings > Battery settings > Battery tip > High usage tip
+ // OS: P
+ ACTION_HIGH_USAGE_TIP = 1348;
+
+ // ACTION: Settings > Battery settings > Battery tip > Summary tip
+ // OS: P
+ ACTION_SUMMARY_TIP = 1349;
+
+ // ACTION: Settings > Battery settings > Battery tip > Smart battery tip
+ // OS: P
+ ACTION_SMART_BATTERY_TIP = 1350;
+
+ // ACTION: Settings > Battery settings > Battery tip > Early warning tip
+ // OS: P
+ ACTION_EARLY_WARNING_TIP = 1351;
+
+ // ACTION: Settings > Battery settings > Battery tip > Low battery tip
+ // OS: P
+ ACTION_LOW_BATTERY_TIP = 1352;
+
+ // ACTION: Settings > Battery settings > Battery tip > App restriction list shown
+ // OS: P
+ ACTION_APP_RESTRICTION_TIP_LIST = 1353;
+
+ // ACTION: Settings > Battery settings > Battery tip > High usage list shown
+ // OS: P
+ ACTION_HIGH_USAGE_TIP_LIST = 1354;
+
+ // OPEN: Settings > Date & time > Select time zone -> Region
+ // CATEGORY: SETTINGS
+ // OS: P
+ SETTINGS_ZONE_PICKER_REGION = 1355;
+
+ // OPEN: Settings > Date & time > Select time zone -> Time Zone
+ // CATEGORY: SETTINGS
+ // OS: P
+ SETTINGS_ZONE_PICKER_TIME_ZONE = 1356;
+
+ // OPEN: Settings > Date & time > Select time zone -> Select UTC Offset
+ // CATEGORY: SETTINGS
+ // OS: P
+ SETTINGS_ZONE_PICKER_FIXED_OFFSET = 1357;
+
+ // Action: notification shade > manage notifications
+ // OS: P
+ ACTION_MANAGE_NOTIFICATIONS = 1358;
+
// ---- End P Constants, all P constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/proto/src/task_snapshot.proto b/proto/src/task_snapshot.proto
index c9d5c27..490a59e 100644
--- a/proto/src/task_snapshot.proto
+++ b/proto/src/task_snapshot.proto
@@ -27,4 +27,5 @@
int32 inset_top = 3;
int32 inset_right = 4;
int32 inset_bottom = 5;
+ bool is_real_snapshot = 6;
}
\ No newline at end of file
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index b0b9586..ecd47e8 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -3129,6 +3129,11 @@
boolean activeWindowGone = true;
final int windowCount = windows.size();
+
+ // We'll clear accessibility focus if the window with focus is no longer visible to
+ // accessibility services
+ boolean shouldClearAccessibilityFocus =
+ mAccessibilityFocusedWindowId != INVALID_WINDOW_ID;
if (windowCount > 0) {
for (int i = 0; i < windowCount; i++) {
WindowInfo windowInfo = windows.get(i);
@@ -3166,6 +3171,7 @@
}
if (window.getId() == mAccessibilityFocusedWindowId) {
window.setAccessibilityFocused(true);
+ shouldClearAccessibilityFocus = false;
}
}
}
@@ -3176,6 +3182,10 @@
for (int i = oldWindowCount - 1; i >= 0; i--) {
oldWindowList.remove(i).recycle();
}
+
+ if (shouldClearAccessibilityFocus) {
+ clearAccessibilityFocus(mAccessibilityFocusedWindowId);
+ }
}
private void sendEventsForChangedWindowsLocked(List<AccessibilityWindowInfo> oldWindows,
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 266b2d7..a5339e0 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -59,9 +59,7 @@
import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.LocalLog;
-import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -73,6 +71,7 @@
import android.view.autofill.IAutoFillManagerClient;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.IResultReceiver;
@@ -88,8 +87,8 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
-import java.util.Set;
/**
* Entry point service for autofill management.
@@ -105,6 +104,13 @@
static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions";
private static final char COMPAT_PACKAGE_DELIMITER = ':';
+ private static final char COMPAT_PACKAGE_URL_IDS_DELIMITER = ',';
+ private static final char COMPAT_PACKAGE_URL_IDS_BLOCK_BEGIN = '[';
+ private static final char COMPAT_PACKAGE_URL_IDS_BLOCK_END = ']';
+
+ // TODO(b/74445943): temporary work around until P Development Preview 3 is branched
+ private static final List<String> DEFAULT_BUTTONS = Arrays.asList("url_bar",
+ "location_bar_edit_text");
private final Context mContext;
private final AutoFillUI mUi;
@@ -326,7 +332,7 @@
if (service == null) {
service = new AutofillManagerServiceImpl(mContext, mLock, mRequestsHistory,
mUiLatencyHistory, mWtfHistory, resolvedUserId, mUi,
- mDisabledUsers.get(resolvedUserId));
+ mAutofillCompatState, mDisabledUsers.get(resolvedUserId));
mServicesCache.put(userId, service);
addCompatibilityModeRequestsLocked(service, userId);
}
@@ -544,23 +550,24 @@
private void addCompatibilityModeRequestsLocked(@NonNull AutofillManagerServiceImpl service
, int userId) {
mAutofillCompatState.reset();
- final ArrayMap<String, Pair<Long, String>> compatPackages =
+ final ArrayMap<String, Long> compatPackages =
service.getCompatibilityPackagesLocked();
if (compatPackages == null || compatPackages.isEmpty()) {
return;
}
- final Set<String> whiteListedPackages = getWhitelistedCompatModePackages();
+
+ final Map<String, String[]> whiteListedPackages = getWhitelistedCompatModePackages();
final int compatPackageCount = compatPackages.size();
for (int i = 0; i < compatPackageCount; i++) {
final String packageName = compatPackages.keyAt(i);
- if (whiteListedPackages == null || !whiteListedPackages.contains(packageName)) {
+ if (whiteListedPackages == null || !whiteListedPackages.containsKey(packageName)) {
Slog.w(TAG, "Ignoring not whitelisted compat package " + packageName);
continue;
}
- final Long maxVersionCode = compatPackages.valueAt(i).first;
+ final Long maxVersionCode = compatPackages.valueAt(i);
if (maxVersionCode != null) {
mAutofillCompatState.addCompatibilityModeRequest(packageName,
- maxVersionCode, userId);
+ maxVersionCode, whiteListedPackages.get(packageName), userId);
}
}
}
@@ -571,16 +578,60 @@
Settings.Global.AUTOFILL_COMPAT_ALLOWED_PACKAGES);
}
- private @Nullable Set<String> getWhitelistedCompatModePackages() {
- final String compatPackagesSetting = getWhitelistedCompatModePackagesFromSettings();
- if (TextUtils.isEmpty(compatPackagesSetting)) {
+ @Nullable
+ private Map<String, String[]> getWhitelistedCompatModePackages() {
+ return getWhitelistedCompatModePackages(getWhitelistedCompatModePackagesFromSettings());
+ }
+
+ @Nullable
+ @VisibleForTesting
+ static Map<String, String[]> getWhitelistedCompatModePackages(String setting) {
+ if (TextUtils.isEmpty(setting)) {
return null;
}
- final Set<String> compatPackages = new ArraySet<>();
+
+ final ArrayMap<String, String[]> compatPackages = new ArrayMap<>();
final SimpleStringSplitter splitter = new SimpleStringSplitter(COMPAT_PACKAGE_DELIMITER);
- splitter.setString(compatPackagesSetting);
+ splitter.setString(setting);
while (splitter.hasNext()) {
- compatPackages.add(splitter.next());
+ final String packageBlock = splitter.next();
+ final int urlBlockIndex = packageBlock.indexOf(COMPAT_PACKAGE_URL_IDS_BLOCK_BEGIN);
+ final String packageName;
+ final List<String> urlBarIds;
+ if (urlBlockIndex == -1) {
+ packageName = packageBlock;
+ urlBarIds = DEFAULT_BUTTONS; // TODO(b/74445943): back to null
+ } else {
+ if (packageBlock.charAt(packageBlock.length() - 1)
+ != COMPAT_PACKAGE_URL_IDS_BLOCK_END) {
+ Slog.w(TAG, "Ignoring entry '" + packageBlock + "' on '" + setting
+ + "'because it does not end on '" + COMPAT_PACKAGE_URL_IDS_BLOCK_END +
+ "'");
+ continue;
+ }
+ packageName = packageBlock.substring(0, urlBlockIndex);
+ urlBarIds = new ArrayList<>();
+ final String urlBarIdsBlock =
+ packageBlock.substring(urlBlockIndex + 1, packageBlock.length() - 1);
+ if (sVerbose) {
+ Slog.v(TAG, "pkg:" + packageName + ": block:" + packageBlock + ": urls:"
+ + urlBarIds + ": block:" + urlBarIdsBlock + ":");
+ }
+ final SimpleStringSplitter splitter2 =
+ new SimpleStringSplitter(COMPAT_PACKAGE_URL_IDS_DELIMITER);
+ splitter2.setString(urlBarIdsBlock);
+ while (splitter2.hasNext()) {
+ final String urlBarId = splitter2.next();
+ urlBarIds.add(urlBarId);
+ }
+ }
+ if (urlBarIds == null) {
+ compatPackages.put(packageName, null);
+ } else {
+ final String[] urlBarIdsArray = new String[urlBarIds.size()];
+ urlBarIds.toArray(urlBarIdsArray);
+ compatPackages.put(packageName, urlBarIdsArray);
+ }
}
return compatPackages;
}
@@ -598,13 +649,41 @@
return mAutofillCompatState.isCompatibilityModeRequested(
packageName, versionCode, userId);
}
+
}
- private static final class AutofillCompatState {
+ /**
+ * Compatibility mode metadata per package.
+ */
+ private static final class PackageCompatState {
+ private final long maxVersionCode;
+ private final String[] urlBarResourceIds;
+
+ PackageCompatState(long maxVersionCode, String[] urlBarResourceIds) {
+ this.maxVersionCode = maxVersionCode;
+ this.urlBarResourceIds = urlBarResourceIds;
+ }
+
+ @Override
+ public String toString() {
+ return "PackageCompatState: [maxVersionCode=" + maxVersionCode
+ + ", urlBarResourceIds=" + Arrays.toString(urlBarResourceIds) + "]";
+ }
+ }
+
+ /**
+ * Compatibility mode metadata associated with all services.
+ *
+ * <p>This object is defined here instead of on each {@link AutofillManagerServiceImpl} because
+ * it cannot hold a lock on the main lock when
+ * {@link AutofillCompatState#isCompatibilityModeRequested(String, long, int)} is called by
+ * external services.
+ */
+ static final class AutofillCompatState {
private final Object mLock = new Object();
@GuardedBy("mLock")
- private SparseArray<ArrayMap<String, Long>> mUserSpecs;
+ private SparseArray<ArrayMap<String, PackageCompatState>> mUserSpecs;
boolean isCompatibilityModeRequested(@NonNull String packageName,
long versionCode, @UserIdInt int userId) {
@@ -612,30 +691,49 @@
if (mUserSpecs == null) {
return false;
}
- final ArrayMap<String, Long> userSpec = mUserSpecs.get(userId);
+ final ArrayMap<String, PackageCompatState> userSpec = mUserSpecs.get(userId);
if (userSpec == null) {
return false;
}
- final Long maxVersionCode = userSpec.get(packageName);
- if (maxVersionCode == null) {
+ final PackageCompatState metadata = userSpec.get(packageName);
+ if (metadata == null) {
return false;
}
- return versionCode <= maxVersionCode;
+ return versionCode <= metadata.maxVersionCode;
+ }
+ }
+
+ @Nullable
+ String[] getUrlBarResourceIds(@NonNull String packageName, @UserIdInt int userId) {
+ synchronized (mLock) {
+ if (mUserSpecs == null) {
+ return null;
+ }
+ final ArrayMap<String, PackageCompatState> userSpec = mUserSpecs.get(userId);
+ if (userSpec == null) {
+ return null;
+ }
+ final PackageCompatState metadata = userSpec.get(packageName);
+ if (metadata == null) {
+ return null;
+ }
+ return metadata.urlBarResourceIds;
}
}
void addCompatibilityModeRequest(@NonNull String packageName,
- long versionCode, @UserIdInt int userId) {
+ long versionCode, @Nullable String[] urlBarResourceIds, @UserIdInt int userId) {
synchronized (mLock) {
if (mUserSpecs == null) {
mUserSpecs = new SparseArray<>();
}
- ArrayMap<String, Long> userSpec = mUserSpecs.get(userId);
+ ArrayMap<String, PackageCompatState> userSpec = mUserSpecs.get(userId);
if (userSpec == null) {
userSpec = new ArrayMap<>();
mUserSpecs.put(userId, userSpec);
}
- userSpec.put(packageName, versionCode);
+ userSpec.put(packageName,
+ new PackageCompatState(versionCode, urlBarResourceIds));
}
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 8622dbe..54ea3ba 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -64,7 +64,6 @@
import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.LocalLog;
-import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
@@ -78,12 +77,12 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.server.LocalServices;
+import com.android.server.autofill.AutofillManagerService.AutofillCompatState;
import com.android.server.autofill.ui.AutoFillUI;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
import java.util.Random;
/**
@@ -164,12 +163,15 @@
@GuardedBy("mLock")
private FillEventHistory mEventHistory;
+ /** Shared instance, doesn't need to be logged */
+ private final AutofillCompatState mAutofillCompatState;
+
/** When was {@link PruneTask} last executed? */
private long mLastPrune = 0;
AutofillManagerServiceImpl(Context context, Object lock, LocalLog requestsHistory,
LocalLog uiLatencyHistory, LocalLog wtfHistory, int userId, AutoFillUI ui,
- boolean disabled) {
+ AutofillCompatState autofillCompatState, boolean disabled) {
mContext = context;
mLock = lock;
mRequestsHistory = requestsHistory;
@@ -178,6 +180,7 @@
mUserId = userId;
mUi = ui;
mFieldClassificationStrategy = new FieldClassificationStrategy(context, userId);
+ mAutofillCompatState = autofillCompatState;
updateLocked(disabled);
}
@@ -208,14 +211,9 @@
}
- @GuardedBy("mLock")
@Nullable
- String getUrlBarResourceIdForCompatModeLocked(@NonNull String packageName) {
- if (mInfo == null) {
- Slog.w(TAG, "getUrlBarResourceIdForCompatModeLocked(): no mInfo");
- return null;
- }
- return mInfo.getUrlBarResourceId(packageName);
+ String[] getUrlBarResourceIdsForCompatMode(@NonNull String packageName) {
+ return mAutofillCompatState.getUrlBarResourceIds(packageName, mUserId);
}
@Nullable
@@ -893,7 +891,7 @@
pw.print(prefix); pw.print("Field classification enabled: ");
pw.println(isFieldClassificationEnabledLocked());
pw.print(prefix); pw.print("Compat pkgs: ");
- final ArrayMap<String, Pair<Long, String>> compatPkgs = getCompatibilityPackagesLocked();
+ final ArrayMap<String, Long> compatPkgs = getCompatibilityPackagesLocked();
if (compatPkgs == null) {
pw.println("N/A");
} else {
@@ -1022,7 +1020,7 @@
}
@GuardedBy("mLock")
- @Nullable ArrayMap<String, Pair<Long, String>> getCompatibilityPackagesLocked() {
+ @Nullable ArrayMap<String, Long> getCompatibilityPackagesLocked() {
if (mInfo != null) {
return mInfo.getCompatibilityPackages();
}
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 232dfdc..5c41f3f 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -30,6 +30,7 @@
import android.view.autofill.AutofillValue;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.util.ArrayUtils;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -168,21 +169,24 @@
/**
* Sanitize the {@code webDomain} property of the URL bar node on compat mode.
+ *
+ * @param structure Assist structure
+ * @param urlBarIds list of ids; only the first id found will be sanitized.
*/
public static void sanitizeUrlBar(@NonNull AssistStructure structure,
- @NonNull String urlBarId) {
+ @NonNull String[] urlBarIds) {
final ViewNode urlBarNode = findViewNode(structure, (node) -> {
- return urlBarId.equals(node.getIdEntry());
+ return ArrayUtils.contains(urlBarIds, node.getIdEntry());
});
if (urlBarNode != null) {
final String domain = urlBarNode.getText().toString();
if (domain.isEmpty()) {
- if (sDebug) Slog.d(TAG, "sanitizeUrlBar(): empty on " + urlBarId);
+ if (sDebug) Slog.d(TAG, "sanitizeUrlBar(): empty on " + urlBarNode.getIdEntry());
return;
}
urlBarNode.setWebDomain(domain);
if (sDebug) {
- Slog.d(TAG, "sanitizeUrlBar(): id=" + urlBarId + ", domain="
+ Slog.d(TAG, "sanitizeUrlBar(): id=" + urlBarNode.getIdEntry() + ", domain="
+ urlBarNode.getWebDomain());
}
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 4abf0f8..26598a2 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -274,11 +274,13 @@
}
if (mCompatMode) {
// Sanitize URL bar, if needed
- final String urlBarId = mService.getUrlBarResourceIdForCompatModeLocked(
+ final String[] urlBarIds = mService.getUrlBarResourceIdsForCompatMode(
mComponentName.getPackageName());
- if (sDebug) Slog.d(TAG, "url_bar in compat mode: " + urlBarId);
- if (urlBarId != null) {
- Helper.sanitizeUrlBar(structure, urlBarId);
+ if (sDebug) {
+ Slog.d(TAG, "url_bars in compat mode: " + Arrays.toString(urlBarIds));
+ }
+ if (urlBarIds != null) {
+ Helper.sanitizeUrlBar(structure, urlBarIds);
}
}
structure.sanitizeForParceling(true);
diff --git a/services/backup/java/com/android/server/backup/BackupManagerConstants.java b/services/backup/java/com/android/server/backup/BackupManagerConstants.java
index 99160c2..dd6e6ab 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerConstants.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerConstants.java
@@ -18,53 +18,76 @@
import android.app.AlarmManager;
import android.content.ContentResolver;
-import android.database.ContentObserver;
-import android.net.Uri;
import android.os.Handler;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.KeyValueListParser;
+import android.util.KeyValueSettingObserver;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
/**
* Class to access backup manager constants.
*
- * The backup manager constants are encoded as a key value list separated by commas
- * and stored as a Settings.Secure.
+ * <p>The backup manager constants are encoded as a key value list separated by commas and stored as
+ * a Settings.Secure.
*/
-class BackupManagerConstants extends ContentObserver {
+class BackupManagerConstants extends KeyValueSettingObserver {
private static final String TAG = "BackupManagerConstants";
+ private static final String SETTING = Settings.Secure.BACKUP_MANAGER_CONSTANTS;
// Key names stored in the secure settings value.
- private static final String KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS =
+ @VisibleForTesting
+ public static final String KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS =
"key_value_backup_interval_milliseconds";
- private static final String KEY_VALUE_BACKUP_FUZZ_MILLISECONDS =
+
+ @VisibleForTesting
+ public static final String KEY_VALUE_BACKUP_FUZZ_MILLISECONDS =
"key_value_backup_fuzz_milliseconds";
- private static final String KEY_VALUE_BACKUP_REQUIRE_CHARGING =
+
+ @VisibleForTesting
+ public static final String KEY_VALUE_BACKUP_REQUIRE_CHARGING =
"key_value_backup_require_charging";
- private static final String KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE =
+
+ @VisibleForTesting
+ public static final String KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE =
"key_value_backup_required_network_type";
- private static final String FULL_BACKUP_INTERVAL_MILLISECONDS =
+
+ @VisibleForTesting
+ public static final String FULL_BACKUP_INTERVAL_MILLISECONDS =
"full_backup_interval_milliseconds";
- private static final String FULL_BACKUP_REQUIRE_CHARGING =
- "full_backup_require_charging";
- private static final String FULL_BACKUP_REQUIRED_NETWORK_TYPE =
+
+ @VisibleForTesting
+ public static final String FULL_BACKUP_REQUIRE_CHARGING = "full_backup_require_charging";
+
+ @VisibleForTesting
+ public static final String FULL_BACKUP_REQUIRED_NETWORK_TYPE =
"full_backup_required_network_type";
- private static final String BACKUP_FINISHED_NOTIFICATION_RECEIVERS =
+
+ @VisibleForTesting
+ public static final String BACKUP_FINISHED_NOTIFICATION_RECEIVERS =
"backup_finished_notification_receivers";
// Hard coded default values.
- private static final long DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS =
+ @VisibleForTesting
+ public static final long DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS =
4 * AlarmManager.INTERVAL_HOUR;
- private static final long DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS =
- 10 * 60 * 1000;
- private static final boolean DEFAULT_KEY_VALUE_BACKUP_REQUIRE_CHARGING = true;
- private static final int DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE = 1;
- private static final long DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS =
+
+ @VisibleForTesting
+ public static final long DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS = 10 * 60 * 1000;
+
+ @VisibleForTesting public static final boolean DEFAULT_KEY_VALUE_BACKUP_REQUIRE_CHARGING = true;
+ @VisibleForTesting public static final int DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE = 1;
+
+ @VisibleForTesting
+ public static final long DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS =
24 * AlarmManager.INTERVAL_HOUR;
- private static final boolean DEFAULT_FULL_BACKUP_REQUIRE_CHARGING = true;
- private static final int DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE = 2;
- private static final String DEFAULT_BACKUP_FINISHED_NOTIFICATION_RECEIVERS = "";
+
+ @VisibleForTesting public static final boolean DEFAULT_FULL_BACKUP_REQUIRE_CHARGING = true;
+ @VisibleForTesting public static final int DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE = 2;
+
+ @VisibleForTesting
+ public static final String DEFAULT_BACKUP_FINISHED_NOTIFICATION_RECEIVERS = "";
// Backup manager constants.
private long mKeyValueBackupIntervalMilliseconds;
@@ -76,49 +99,46 @@
private int mFullBackupRequiredNetworkType;
private String[] mBackupFinishedNotificationReceivers;
- private ContentResolver mResolver;
- private final KeyValueListParser mParser = new KeyValueListParser(',');
-
public BackupManagerConstants(Handler handler, ContentResolver resolver) {
- super(handler);
- mResolver = resolver;
- updateSettings();
- mResolver.registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.BACKUP_MANAGER_CONSTANTS), false, this);
+ super(handler, resolver, Settings.Secure.getUriFor(SETTING));
}
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- updateSettings();
+ public String getSettingValue(ContentResolver resolver) {
+ return Settings.Secure.getString(resolver, SETTING);
}
- private synchronized void updateSettings() {
- try {
- mParser.setString(Settings.Secure.getString(mResolver,
- Settings.Secure.BACKUP_MANAGER_CONSTANTS));
- } catch (IllegalArgumentException e) {
- // Failed to parse the settings string. Use defaults.
- Slog.e(TAG, "Bad backup manager constants: " + e.getMessage());
- }
-
- mKeyValueBackupIntervalMilliseconds = mParser.getLong(
- KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS,
- DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS);
- mKeyValueBackupFuzzMilliseconds = mParser.getLong(KEY_VALUE_BACKUP_FUZZ_MILLISECONDS,
- DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS);
- mKeyValueBackupRequireCharging = mParser.getBoolean(KEY_VALUE_BACKUP_REQUIRE_CHARGING,
- DEFAULT_KEY_VALUE_BACKUP_REQUIRE_CHARGING);
- mKeyValueBackupRequiredNetworkType = mParser.getInt(KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE,
- DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE);
- mFullBackupIntervalMilliseconds = mParser.getLong(FULL_BACKUP_INTERVAL_MILLISECONDS,
- DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS);
- mFullBackupRequireCharging = mParser.getBoolean(FULL_BACKUP_REQUIRE_CHARGING,
- DEFAULT_FULL_BACKUP_REQUIRE_CHARGING);
- mFullBackupRequiredNetworkType = mParser.getInt(FULL_BACKUP_REQUIRED_NETWORK_TYPE,
- DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE);
- String backupFinishedNotificationReceivers = mParser.getString(
- BACKUP_FINISHED_NOTIFICATION_RECEIVERS,
- DEFAULT_BACKUP_FINISHED_NOTIFICATION_RECEIVERS);
+ public synchronized void update(KeyValueListParser parser) {
+ mKeyValueBackupIntervalMilliseconds =
+ parser.getLong(
+ KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS,
+ DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS);
+ mKeyValueBackupFuzzMilliseconds =
+ parser.getLong(
+ KEY_VALUE_BACKUP_FUZZ_MILLISECONDS,
+ DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS);
+ mKeyValueBackupRequireCharging =
+ parser.getBoolean(
+ KEY_VALUE_BACKUP_REQUIRE_CHARGING,
+ DEFAULT_KEY_VALUE_BACKUP_REQUIRE_CHARGING);
+ mKeyValueBackupRequiredNetworkType =
+ parser.getInt(
+ KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE,
+ DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE);
+ mFullBackupIntervalMilliseconds =
+ parser.getLong(
+ FULL_BACKUP_INTERVAL_MILLISECONDS,
+ DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS);
+ mFullBackupRequireCharging =
+ parser.getBoolean(
+ FULL_BACKUP_REQUIRE_CHARGING, DEFAULT_FULL_BACKUP_REQUIRE_CHARGING);
+ mFullBackupRequiredNetworkType =
+ parser.getInt(
+ FULL_BACKUP_REQUIRED_NETWORK_TYPE,
+ DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE);
+ String backupFinishedNotificationReceivers =
+ parser.getString(
+ BACKUP_FINISHED_NOTIFICATION_RECEIVERS,
+ DEFAULT_BACKUP_FINISHED_NOTIFICATION_RECEIVERS);
if (backupFinishedNotificationReceivers.isEmpty()) {
mBackupFinishedNotificationReceivers = new String[] {};
} else {
@@ -132,40 +152,50 @@
// a reference of this object.
public synchronized long getKeyValueBackupIntervalMilliseconds() {
if (BackupManagerService.DEBUG_SCHEDULING) {
- Slog.v(TAG, "getKeyValueBackupIntervalMilliseconds(...) returns "
- + mKeyValueBackupIntervalMilliseconds);
+ Slog.v(
+ TAG,
+ "getKeyValueBackupIntervalMilliseconds(...) returns "
+ + mKeyValueBackupIntervalMilliseconds);
}
return mKeyValueBackupIntervalMilliseconds;
}
public synchronized long getKeyValueBackupFuzzMilliseconds() {
if (BackupManagerService.DEBUG_SCHEDULING) {
- Slog.v(TAG, "getKeyValueBackupFuzzMilliseconds(...) returns "
- + mKeyValueBackupFuzzMilliseconds);
+ Slog.v(
+ TAG,
+ "getKeyValueBackupFuzzMilliseconds(...) returns "
+ + mKeyValueBackupFuzzMilliseconds);
}
return mKeyValueBackupFuzzMilliseconds;
}
public synchronized boolean getKeyValueBackupRequireCharging() {
if (BackupManagerService.DEBUG_SCHEDULING) {
- Slog.v(TAG, "getKeyValueBackupRequireCharging(...) returns "
- + mKeyValueBackupRequireCharging);
+ Slog.v(
+ TAG,
+ "getKeyValueBackupRequireCharging(...) returns "
+ + mKeyValueBackupRequireCharging);
}
return mKeyValueBackupRequireCharging;
}
public synchronized int getKeyValueBackupRequiredNetworkType() {
if (BackupManagerService.DEBUG_SCHEDULING) {
- Slog.v(TAG, "getKeyValueBackupRequiredNetworkType(...) returns "
- + mKeyValueBackupRequiredNetworkType);
+ Slog.v(
+ TAG,
+ "getKeyValueBackupRequiredNetworkType(...) returns "
+ + mKeyValueBackupRequiredNetworkType);
}
return mKeyValueBackupRequiredNetworkType;
}
public synchronized long getFullBackupIntervalMilliseconds() {
if (BackupManagerService.DEBUG_SCHEDULING) {
- Slog.v(TAG, "getFullBackupIntervalMilliseconds(...) returns "
- + mFullBackupIntervalMilliseconds);
+ Slog.v(
+ TAG,
+ "getFullBackupIntervalMilliseconds(...) returns "
+ + mFullBackupIntervalMilliseconds);
}
return mFullBackupIntervalMilliseconds;
}
@@ -179,19 +209,21 @@
public synchronized int getFullBackupRequiredNetworkType() {
if (BackupManagerService.DEBUG_SCHEDULING) {
- Slog.v(TAG, "getFullBackupRequiredNetworkType(...) returns "
- + mFullBackupRequiredNetworkType);
+ Slog.v(
+ TAG,
+ "getFullBackupRequiredNetworkType(...) returns "
+ + mFullBackupRequiredNetworkType);
}
return mFullBackupRequiredNetworkType;
}
- /**
- * Returns an array of package names that should be notified whenever a backup finishes.
- */
+ /** Returns an array of package names that should be notified whenever a backup finishes. */
public synchronized String[] getBackupFinishedNotificationReceivers() {
if (BackupManagerService.DEBUG_SCHEDULING) {
- Slog.v(TAG, "getBackupFinishedNotificationReceivers(...) returns "
- + TextUtils.join(", ", mBackupFinishedNotificationReceivers));
+ Slog.v(
+ TAG,
+ "getBackupFinishedNotificationReceivers(...) returns "
+ + TextUtils.join(", ", mBackupFinishedNotificationReceivers));
}
return mBackupFinishedNotificationReceivers;
}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 369df54..b6e2dca 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -851,6 +851,10 @@
mJournal = null; // will be created on first use
mConstants = new BackupManagerConstants(mBackupHandler, mContext.getContentResolver());
+ // We are observing changes to the constants throughout the lifecycle of BMS. This is
+ // because we reference the constants in multiple areas of BMS, which otherwise would
+ // require frequent starting and stopping.
+ mConstants.start();
// Set up the various sorts of package tracking we do
mFullBackupScheduleFile = new File(mBaseStateDir, "fb-schedule");
@@ -3525,7 +3529,10 @@
dumpAgents(pw);
return;
} else if ("transportclients".equals(arg.toLowerCase())) {
- mTransportManager.dump(pw);
+ mTransportManager.dumpTransportClients(pw);
+ return;
+ } else if ("transportstats".equals(arg.toLowerCase())) {
+ mTransportManager.dumpTransportStats(pw);
return;
}
}
@@ -3590,7 +3597,7 @@
}
}
- mTransportManager.dump(pw);
+ mTransportManager.dumpTransportClients(pw);
pw.println("Pending init: " + mPendingInits.size());
for (String s : mPendingInits) {
diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java
index c87d298..6a1bf17 100644
--- a/services/backup/java/com/android/server/backup/TransportManager.java
+++ b/services/backup/java/com/android/server/backup/TransportManager.java
@@ -44,6 +44,7 @@
import com.android.server.backup.transport.TransportConnectionListener;
import com.android.server.backup.transport.TransportNotAvailableException;
import com.android.server.backup.transport.TransportNotRegisteredException;
+import com.android.server.backup.transport.TransportStats;
import java.io.PrintWriter;
import java.util.List;
@@ -64,6 +65,7 @@
private final PackageManager mPackageManager;
private final Set<ComponentName> mTransportWhitelist;
private final TransportClientManager mTransportClientManager;
+ private final TransportStats mTransportStats;
private OnTransportRegisteredListener mOnTransportRegisteredListener = (c, n) -> {};
/**
@@ -85,7 +87,12 @@
private volatile String mCurrentTransportName;
TransportManager(Context context, Set<ComponentName> whitelist, String selectedTransport) {
- this(context, whitelist, selectedTransport, new TransportClientManager(context));
+ mContext = context;
+ mPackageManager = context.getPackageManager();
+ mTransportWhitelist = Preconditions.checkNotNull(whitelist);
+ mCurrentTransportName = selectedTransport;
+ mTransportStats = new TransportStats();
+ mTransportClientManager = new TransportClientManager(context, mTransportStats);
}
@VisibleForTesting
@@ -98,6 +105,7 @@
mPackageManager = context.getPackageManager();
mTransportWhitelist = Preconditions.checkNotNull(whitelist);
mCurrentTransportName = selectedTransport;
+ mTransportStats = new TransportStats();
mTransportClientManager = transportClientManager;
}
@@ -640,10 +648,14 @@
!Thread.holdsLock(mTransportLock), "Can't call transport with transport lock held");
}
- public void dump(PrintWriter pw) {
+ public void dumpTransportClients(PrintWriter pw) {
mTransportClientManager.dump(pw);
}
+ public void dumpTransportStats(PrintWriter pw) {
+ mTransportStats.dump(pw);
+ }
+
private static Predicate<ComponentName> fromPackageFilter(String packageName) {
return transportComponent -> packageName.equals(transportComponent.getPackageName());
}
diff --git a/services/backup/java/com/android/server/backup/transport/TransportClient.java b/services/backup/java/com/android/server/backup/transport/TransportClient.java
index 1a2ca92..fa881a9 100644
--- a/services/backup/java/com/android/server/backup/transport/TransportClient.java
+++ b/services/backup/java/com/android/server/backup/transport/TransportClient.java
@@ -29,6 +29,7 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.text.format.DateFormat;
import android.util.ArrayMap;
@@ -51,6 +52,7 @@
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@@ -78,6 +80,7 @@
private static final int LOG_BUFFER_SIZE = 5;
private final Context mContext;
+ private final TransportStats mTransportStats;
private final Intent mBindIntent;
private final ServiceConnection mConnection;
private final String mIdentifier;
@@ -104,12 +107,14 @@
TransportClient(
Context context,
+ TransportStats transportStats,
Intent bindIntent,
ComponentName transportComponent,
String identifier,
String caller) {
this(
context,
+ transportStats,
bindIntent,
transportComponent,
identifier,
@@ -120,12 +125,14 @@
@VisibleForTesting
TransportClient(
Context context,
+ TransportStats transportStats,
Intent bindIntent,
ComponentName transportComponent,
String identifier,
String caller,
Handler listenerHandler) {
mContext = context;
+ mTransportStats = transportStats;
mTransportComponent = transportComponent;
mBindIntent = bindIntent;
mIdentifier = identifier;
@@ -321,11 +328,16 @@
(requestedTransport, transportClient) ->
transportFuture.complete(requestedTransport);
+ long requestTime = SystemClock.elapsedRealtime();
log(Priority.DEBUG, caller, "Sync connect: calling async");
connectAsync(requestListener, caller);
try {
- return transportFuture.get();
+ transport = transportFuture.get();
+ long time = SystemClock.elapsedRealtime() - requestTime;
+ mTransportStats.registerConnectionTime(mTransportComponent, time);
+ log(Priority.DEBUG, caller, String.format(Locale.US, "Connect took %d ms", time));
+ return transport;
} catch (InterruptedException | ExecutionException e) {
String error = e.getClass().getSimpleName();
log(Priority.ERROR, caller, error + " while waiting for transport: " + e.getMessage());
diff --git a/services/backup/java/com/android/server/backup/transport/TransportClientManager.java b/services/backup/java/com/android/server/backup/transport/TransportClientManager.java
index 96e7d2f..f4e3928 100644
--- a/services/backup/java/com/android/server/backup/transport/TransportClientManager.java
+++ b/services/backup/java/com/android/server/backup/transport/TransportClientManager.java
@@ -37,12 +37,14 @@
private static final String TAG = "TransportClientManager";
private final Context mContext;
+ private final TransportStats mTransportStats;
private final Object mTransportClientsLock = new Object();
private int mTransportClientsCreated = 0;
private Map<TransportClient, String> mTransportClientsCallerMap = new WeakHashMap<>();
- public TransportClientManager(Context context) {
+ public TransportClientManager(Context context, TransportStats transportStats) {
mContext = context;
+ mTransportStats = transportStats;
}
/**
@@ -88,6 +90,7 @@
TransportClient transportClient =
new TransportClient(
mContext,
+ mTransportStats,
bindIntent,
transportComponent,
Integer.toString(mTransportClientsCreated),
diff --git a/services/backup/java/com/android/server/backup/transport/TransportStats.java b/services/backup/java/com/android/server/backup/transport/TransportStats.java
new file mode 100644
index 0000000..bd84782
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/transport/TransportStats.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.transport;
+
+import android.annotation.Nullable;
+import android.content.ComponentName;
+
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Optional;
+
+/** Responsible for aggregating {@link TransportClient} relevant times. */
+public class TransportStats {
+ private final Object mStatsLock = new Object();
+ private final Map<ComponentName, Stats> mTransportStats = new HashMap<>();
+
+ void registerConnectionTime(ComponentName transportComponent, long timeMs) {
+ synchronized (mStatsLock) {
+ Stats stats = mTransportStats.get(transportComponent);
+ if (stats == null) {
+ stats = new Stats();
+ mTransportStats.put(transportComponent, stats);
+ }
+ stats.register(timeMs);
+ }
+ }
+
+ /** Returns {@link Stats} for transport whose host service is {@code transportComponent}. */
+ @Nullable
+ public Stats getStatsForTransport(ComponentName transportComponent) {
+ synchronized (mStatsLock) {
+ Stats stats = mTransportStats.get(transportComponent);
+ if (stats == null) {
+ return null;
+ }
+ return new Stats(stats);
+ }
+ }
+
+ public void dump(PrintWriter pw) {
+ synchronized (mStatsLock) {
+ Optional<Stats> aggregatedStats =
+ mTransportStats.values().stream().reduce(Stats::merge);
+ if (aggregatedStats.isPresent()) {
+ dumpStats(pw, "", aggregatedStats.get());
+ }
+ if (!mTransportStats.isEmpty()) {
+ pw.println("Per transport:");
+ for (ComponentName transportComponent : mTransportStats.keySet()) {
+ Stats stats = mTransportStats.get(transportComponent);
+ pw.println(" " + transportComponent.flattenToShortString());
+ dumpStats(pw, " ", stats);
+ }
+ }
+ }
+ }
+
+ private static void dumpStats(PrintWriter pw, String prefix, Stats stats) {
+ pw.println(
+ String.format(
+ Locale.US, "%sAverage connection time: %.2f ms", prefix, stats.average));
+ pw.println(String.format(Locale.US, "%sMax connection time: %d ms", prefix, stats.max));
+ pw.println(String.format(Locale.US, "%sMin connection time: %d ms", prefix, stats.min));
+ pw.println(String.format(Locale.US, "%sNumber of connections: %d ", prefix, stats.n));
+ }
+
+ public static final class Stats {
+ public static Stats merge(Stats a, Stats b) {
+ return new Stats(
+ a.n + b.n,
+ (a.average * a.n + b.average * b.n) / (a.n + b.n),
+ Math.max(a.max, b.max),
+ Math.min(a.min, b.min));
+ }
+
+ public int n;
+ public double average;
+ public long max;
+ public long min;
+
+ public Stats() {
+ n = 0;
+ average = 0;
+ max = 0;
+ min = Long.MAX_VALUE;
+ }
+
+ private Stats(int n, double average, long max, long min) {
+ this.n = n;
+ this.average = average;
+ this.max = max;
+ this.min = min;
+ }
+
+ private Stats(Stats original) {
+ this(original.n, original.average, original.max, original.min);
+ }
+
+ private void register(long sample) {
+ average = (average * n + sample) / (n + 1);
+ n++;
+ max = Math.max(max, sample);
+ min = Math.min(min, sample);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 15f3a23..ecf80ba 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -610,7 +610,7 @@
@Override
public void setUidMode(int code, int uid, int mode) {
if (Binder.getCallingPid() != Process.myPid()) {
- mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
+ mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
Binder.getCallingPid(), Binder.getCallingUid(), null);
}
verifyIncomingOp(code);
@@ -714,7 +714,7 @@
@Override
public void setMode(int code, int uid, String packageName, int mode) {
if (Binder.getCallingPid() != Process.myPid()) {
- mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
+ mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
Binder.getCallingPid(), Binder.getCallingUid(), null);
}
verifyIncomingOp(code);
@@ -832,7 +832,7 @@
public void resetAllModes(int reqUserId, String reqPackageName) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
- mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
+ mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
callingPid, callingUid, null);
reqUserId = ActivityManager.handleIncomingUser(callingPid, callingUid, reqUserId,
true, true, "resetAllModes", null);
@@ -1087,6 +1087,8 @@
String[] exceptionPackages) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
+ mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
+ Binder.getCallingPid(), Binder.getCallingUid(), null);
synchronized (this) {
SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code);
if (usageRestrictions == null) {
@@ -2330,7 +2332,7 @@
}
case "write-settings": {
shell.mInternal.mContext.enforcePermission(
- android.Manifest.permission.UPDATE_APP_OPS_STATS,
+ android.Manifest.permission.MANAGE_APP_OPS_MODES,
Binder.getCallingPid(), Binder.getCallingUid(), null);
long token = Binder.clearCallingIdentity();
try {
@@ -2346,7 +2348,7 @@
}
case "read-settings": {
shell.mInternal.mContext.enforcePermission(
- android.Manifest.permission.UPDATE_APP_OPS_STATS,
+ android.Manifest.permission.MANAGE_APP_OPS_MODES,
Binder.getCallingPid(), Binder.getCallingUid(), null);
long token = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/AppStateTracker.java b/services/core/java/com/android/server/AppStateTracker.java
index a6b71b7..16be680 100644
--- a/services/core/java/com/android/server/AppStateTracker.java
+++ b/services/core/java/com/android/server/AppStateTracker.java
@@ -258,7 +258,7 @@
*/
private void onRunAnyAppOpsChanged(AppStateTracker sender,
int uid, @NonNull String packageName) {
- updateJobsForUidPackage(uid, packageName);
+ updateJobsForUidPackage(uid, packageName, sender.isUidActive(uid));
if (!sender.areAlarmsRestricted(uid, packageName, /*allowWhileIdle=*/ false)) {
unblockAlarmsForUidPackage(uid, packageName);
@@ -279,9 +279,11 @@
* This is called when the active/idle state changed for a UID.
*/
private void onUidActiveStateChanged(AppStateTracker sender, int uid) {
- updateJobsForUid(uid);
+ final boolean isActive = sender.isUidActive(uid);
- if (sender.isUidActive(uid)) {
+ updateJobsForUid(uid, isActive);
+
+ if (isActive) {
unblockAlarmsForUid(uid);
}
}
@@ -346,14 +348,14 @@
* Called when the job restrictions for a UID might have changed, so the job
* scheduler should re-evaluate all restrictions for all jobs.
*/
- public void updateJobsForUid(int uid) {
+ public void updateJobsForUid(int uid, boolean isNowActive) {
}
/**
* Called when the job restrictions for a UID - package might have changed, so the job
* scheduler should re-evaluate all restrictions for all jobs.
*/
- public void updateJobsForUidPackage(int uid, String packageName) {
+ public void updateJobsForUidPackage(int uid, String packageName, boolean isNowActive) {
}
/**
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 8265262..d31a605 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -20,6 +20,7 @@
import android.database.ContentObserver;
import android.os.BatteryStats;
+import android.os.Bundle;
import android.os.PowerManager;
import android.os.ResultReceiver;
import android.os.ShellCallback;
@@ -35,7 +36,6 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
import android.hidl.manager.V1_0.IServiceManager;
import android.hidl.manager.V1_0.IServiceNotification;
import android.hardware.health.V1_0.HealthInfo;
@@ -73,6 +73,8 @@
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.NoSuchElementException;
@@ -117,6 +119,8 @@
private static final int BATTERY_SCALE = 100; // battery capacity is a percentage
private static final long HEALTH_HAL_WAIT_MS = 1000;
+ private static final long BATTERY_LEVEL_CHANGE_THROTTLE_MS = 60_000;
+ private static final int MAX_BATTERY_LEVELS_QUEUE_SIZE = 100;
// Used locally for determining when to make a last ditch effort to log
// discharge stats before the device dies.
@@ -178,7 +182,8 @@
private HealthServiceWrapper mHealthServiceWrapper;
private HealthHalCallback mHealthHalCallback;
private BatteryPropertiesRegistrar mBatteryPropertiesRegistrar;
- private HandlerThread mHandlerThread;
+ private ArrayDeque<Bundle> mBatteryLevelsEventQueue;
+ private long mLastBatteryLevelChangedSentMs;
public BatteryService(Context context) {
super(context);
@@ -198,6 +203,8 @@
mShutdownBatteryTemperature = mContext.getResources().getInteger(
com.android.internal.R.integer.config_shutdownBatteryTemperature);
+ mBatteryLevelsEventQueue = new ArrayDeque<>();
+
// watch for invalid charger messages if the invalid_charger switch exists
if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {
UEventObserver invalidChargerObserver = new UEventObserver() {
@@ -585,7 +592,11 @@
// We are doing this after sending the above broadcasts, so anything processing
// them will get the new sequence number at that point. (See for example how testing
// of JobScheduler's BatteryController works.)
- sendIntentLocked();
+ sendBatteryChangedIntentLocked();
+ if (mLastBatteryLevel != mHealthInfo.batteryLevel) {
+ sendBatteryLevelChangedIntentLocked();
+ }
+
// Update the battery LED
mLed.updateLightsLocked();
@@ -610,7 +621,7 @@
}
}
- private void sendIntentLocked() {
+ private void sendBatteryChangedIntentLocked() {
// Pack up the values and broadcast them to everyone
final Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
@@ -639,12 +650,51 @@
+ ", info:" + mHealthInfo.toString());
}
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL);
- }
- });
+ mHandler.post(() -> ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL));
+ }
+
+ private void sendBatteryLevelChangedIntentLocked() {
+ Bundle event = new Bundle();
+ long now = SystemClock.elapsedRealtime();
+ event.putInt(BatteryManager.EXTRA_SEQUENCE, mSequence);
+ event.putInt(BatteryManager.EXTRA_STATUS, mHealthInfo.batteryStatus);
+ event.putInt(BatteryManager.EXTRA_HEALTH, mHealthInfo.batteryHealth);
+ event.putBoolean(BatteryManager.EXTRA_PRESENT, mHealthInfo.batteryPresent);
+ event.putInt(BatteryManager.EXTRA_LEVEL, mHealthInfo.batteryLevel);
+ event.putBoolean(BatteryManager.EXTRA_BATTERY_LOW, mSentLowBatteryBroadcast);
+ event.putInt(BatteryManager.EXTRA_SCALE, BATTERY_SCALE);
+ event.putInt(BatteryManager.EXTRA_PLUGGED, mPlugType);
+ event.putInt(BatteryManager.EXTRA_VOLTAGE, mHealthInfo.batteryVoltage);
+ event.putLong(BatteryManager.EXTRA_EVENT_TIMESTAMP, now);
+
+ boolean queueWasEmpty = mBatteryLevelsEventQueue.isEmpty();
+ mBatteryLevelsEventQueue.add(event);
+ // Make sure queue is bounded and doesn't exceed intent payload limits
+ if (mBatteryLevelsEventQueue.size() > MAX_BATTERY_LEVELS_QUEUE_SIZE) {
+ mBatteryLevelsEventQueue.removeFirst();
+ }
+
+ if (queueWasEmpty) {
+ // send now if last event was before throttle interval, otherwise delay
+ long delay = now - mLastBatteryLevelChangedSentMs > BATTERY_LEVEL_CHANGE_THROTTLE_MS
+ ? 0 : mLastBatteryLevelChangedSentMs + BATTERY_LEVEL_CHANGE_THROTTLE_MS - now;
+ mHandler.postDelayed(this::sendEnqueuedBatteryLevelChangedEvents, delay);
+ }
+ }
+
+ private void sendEnqueuedBatteryLevelChangedEvents() {
+ ArrayList<Bundle> events;
+ synchronized (mLock) {
+ events = new ArrayList<>(mBatteryLevelsEventQueue);
+ mBatteryLevelsEventQueue.clear();
+ }
+ final Intent intent = new Intent(Intent.ACTION_BATTERY_LEVEL_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+ intent.putParcelableArrayListExtra(BatteryManager.EXTRA_EVENTS, events);
+
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+ android.Manifest.permission.BATTERY_STATS);
+ mLastBatteryLevelChangedSentMs = SystemClock.elapsedRealtime();
}
private void logBatteryStatsLocked() {
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 55ad8cc..02b1380 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -21,6 +21,7 @@
import android.app.AppGlobals;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothProtoEnums;
import android.bluetooth.IBluetooth;
import android.bluetooth.IBluetoothCallback;
import android.bluetooth.IBluetoothGatt;
@@ -87,14 +88,6 @@
private static final int ACTIVE_LOG_MAX_SIZE = 20;
private static final int CRASH_LOG_MAX_SIZE = 100;
- private static final String REASON_AIRPLANE_MODE = "airplane mode";
- private static final String REASON_DISALLOWED = "disallowed by system";
- private static final String REASON_RESTARTED = "automatic restart";
- private static final String REASON_START_CRASH = "turn-on crash";
- private static final String REASON_SYSTEM_BOOT = "system boot";
- private static final String REASON_UNEXPECTED = "unexpected crash";
- private static final String REASON_USER_SWITCH = "user switch";
- private static final String REASON_RESTORE_USER_SETTING = "restore user setting";
private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
//Maximum msec to wait for service restart
@@ -163,7 +156,7 @@
private boolean mQuietEnable = false;
private boolean mEnable;
- private CharSequence timeToLog(long timestamp) {
+ private static CharSequence timeToLog(long timestamp) {
return android.text.format.DateFormat.format("MM-dd HH:mm:ss", timestamp);
}
@@ -171,29 +164,27 @@
* Used for tracking apps that enabled / disabled Bluetooth.
*/
private class ActiveLog {
+ private int mReason;
private String mPackageName;
private boolean mEnable;
private long mTimestamp;
- ActiveLog(String packageName, boolean enable, long timestamp) {
+ ActiveLog(int reason, String packageName, boolean enable, long timestamp) {
+ mReason = reason;
mPackageName = packageName;
mEnable = enable;
mTimestamp = timestamp;
}
- public long getTime() {
- return mTimestamp;
- }
-
public String toString() {
- return timeToLog(mTimestamp) + (mEnable ? " Enabled " : " Disabled ") + " by "
- + mPackageName;
+ return timeToLog(mTimestamp) + (mEnable ? " Enabled " : " Disabled ")
+ + " due to " + getEnableDisableReasonString(mReason) + " by " + mPackageName;
}
}
- private LinkedList<ActiveLog> mActiveLogs;
- private LinkedList<Long> mCrashTimestamps;
+ private final LinkedList<ActiveLog> mActiveLogs = new LinkedList<>();
+ private final LinkedList<Long> mCrashTimestamps = new LinkedList<>();
private int mCrashes;
private long mLastEnabledTime;
@@ -213,8 +204,7 @@
// Save a ProfileServiceConnections object for each of the bound
// bluetooth profile services
- private final Map<Integer, ProfileServiceConnections> mProfileServices =
- new HashMap<Integer, ProfileServiceConnections>();
+ private final Map<Integer, ProfileServiceConnections> mProfileServices = new HashMap<>();
private final boolean mPermissionReviewRequired;
@@ -246,7 +236,8 @@
if (userId == UserHandle.USER_SYSTEM && newRestrictions.getBoolean(
UserManager.DISALLOW_BLUETOOTH)) {
updateOppLauncherComponentState(userId, true); // Sharing disallowed
- sendDisableMsg(REASON_DISALLOWED);
+ sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED,
+ mContext.getPackageName());
} else {
updateOppLauncherComponentState(userId, newRestrictions.getBoolean(
UserManager.DISALLOW_BLUETOOTH_SHARING));
@@ -303,10 +294,13 @@
mBluetoothLock.readLock().unlock();
}
} else if (st == BluetoothAdapter.STATE_ON) {
- sendDisableMsg(REASON_AIRPLANE_MODE);
+ sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
+ mContext.getPackageName());
}
} else if (mEnableExternal) {
- sendEnableMsg(mQuietEnableExternal, REASON_AIRPLANE_MODE);
+ sendEnableMsg(mQuietEnableExternal,
+ BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
+ mContext.getPackageName());
}
}
}
@@ -369,8 +363,6 @@
mPermissionReviewRequired = context.getResources()
.getBoolean(com.android.internal.R.bool.config_permissionReviewRequired);
- mActiveLogs = new LinkedList<ActiveLog>();
- mCrashTimestamps = new LinkedList<Long>();
mCrashes = 0;
mBluetooth = null;
mBluetoothBinder = null;
@@ -671,8 +663,8 @@
return false;
}
try {
- return (Settings.Global.getInt(mContentResolver,
- Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE)) != 0;
+ return Settings.Global.getInt(mContentResolver,
+ Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE) != 0;
} catch (SettingNotFoundException e) {
}
return false;
@@ -867,7 +859,8 @@
synchronized (mReceiver) {
mQuietEnableExternal = true;
mEnableExternal = true;
- sendEnableMsg(true, packageName);
+ sendEnableMsg(true,
+ BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
}
return true;
}
@@ -907,7 +900,8 @@
mQuietEnableExternal = false;
mEnableExternal = true;
// waive WRITE_SECURE_SETTINGS permission check
- sendEnableMsg(false, packageName);
+ sendEnableMsg(false,
+ BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
}
if (DBG) {
Slog.d(TAG, "enable returning");
@@ -943,7 +937,8 @@
persistBluetoothSetting(BLUETOOTH_OFF);
}
mEnableExternal = false;
- sendDisableMsg(packageName);
+ sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
+ packageName);
}
return true;
}
@@ -1127,7 +1122,9 @@
if (DBG) {
Slog.d(TAG, "Auto-enabling Bluetooth.");
}
- sendEnableMsg(mQuietEnableExternal, REASON_SYSTEM_BOOT);
+ sendEnableMsg(mQuietEnableExternal,
+ BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT,
+ mContext.getPackageName());
} else if (!isNameAndAddressSet()) {
if (DBG) {
Slog.d(TAG, "Getting adapter name and address");
@@ -1569,20 +1566,25 @@
break;
case MESSAGE_RESTORE_USER_SETTING:
- try {
- if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) {
- if (DBG) {
- Slog.d(TAG, "Restore Bluetooth state to disabled");
- }
- disable(REASON_RESTORE_USER_SETTING, true);
- } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) {
- if (DBG) {
- Slog.d(TAG, "Restore Bluetooth state to enabled");
- }
- enable(REASON_RESTORE_USER_SETTING);
+ if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) {
+ if (DBG) {
+ Slog.d(TAG, "Restore Bluetooth state to disabled");
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to change Bluetooth On setting", e);
+ persistBluetoothSetting(BLUETOOTH_OFF);
+ mEnableExternal = false;
+ sendDisableMsg(
+ BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING,
+ mContext.getPackageName());
+ } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) {
+ if (DBG) {
+ Slog.d(TAG, "Restore Bluetooth state to enabled");
+ }
+ mQuietEnableExternal = false;
+ mEnableExternal = true;
+ // waive WRITE_SECURE_SETTINGS permission check
+ sendEnableMsg(false,
+ BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING,
+ mContext.getPackageName());
}
break;
@@ -1609,7 +1611,7 @@
break;
}
case MESSAGE_ADD_PROXY_DELAYED: {
- ProfileServiceConnections psc = mProfileServices.get(new Integer(msg.arg1));
+ ProfileServiceConnections psc = mProfileServices.get(msg.arg1);
if (psc == null) {
break;
}
@@ -1758,7 +1760,8 @@
// log the unexpected crash
addCrashLog();
- addActiveLog(REASON_UNEXPECTED, false);
+ addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH,
+ mContext.getPackageName(), false);
if (mEnable) {
mEnable = false;
// Send a Bluetooth Restart message
@@ -1792,7 +1795,8 @@
it doesnt change when IBluetooth
service restarts */
mEnable = true;
- addActiveLog(REASON_RESTARTED, true);
+ addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED,
+ mContext.getPackageName(), true);
handleEnable(mQuietEnable);
break;
}
@@ -1848,7 +1852,8 @@
unbindAllBluetoothProfileServices();
// disable
- addActiveLog(REASON_USER_SWITCH, false);
+ addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH,
+ mContext.getPackageName(), false);
handleDisable();
// Pbap service need receive STATE_TURNING_OFF intent to close
bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
@@ -1886,7 +1891,8 @@
mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
mState = BluetoothAdapter.STATE_OFF;
// enable
- addActiveLog(REASON_USER_SWITCH, true);
+ addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH,
+ mContext.getPackageName(), true);
// mEnable flag could have been reset on disableBLE. Reenable it.
mEnable = true;
handleEnable(mQuietEnable);
@@ -2153,23 +2159,24 @@
return false;
}
- private void sendDisableMsg(String packageName) {
+ private void sendDisableMsg(int reason, String packageName) {
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE));
- addActiveLog(packageName, false);
+ addActiveLog(reason, packageName, false);
}
- private void sendEnableMsg(boolean quietMode, String packageName) {
+ private void sendEnableMsg(boolean quietMode, int reason, String packageName) {
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0));
- addActiveLog(packageName, true);
+ addActiveLog(reason, packageName, true);
mLastEnabledTime = SystemClock.elapsedRealtime();
}
- private void addActiveLog(String packageName, boolean enable) {
+ private void addActiveLog(int reason, String packageName, boolean enable) {
synchronized (mActiveLogs) {
if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) {
mActiveLogs.remove();
}
- mActiveLogs.add(new ActiveLog(packageName, enable, System.currentTimeMillis()));
+ mActiveLogs.add(
+ new ActiveLog(reason, packageName, enable, System.currentTimeMillis()));
}
}
@@ -2200,7 +2207,8 @@
SystemClock.sleep(500);
// disable
- addActiveLog(REASON_START_CRASH, false);
+ addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR,
+ mContext.getPackageName(), false);
handleDisable();
waitForOnOff(false, true);
@@ -2344,4 +2352,29 @@
writer.println(errorMsg);
}
}
+
+ private static String getEnableDisableReasonString(int reason) {
+ switch (reason) {
+ case BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST:
+ return "APPLICATION_REQUEST";
+ case BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE:
+ return "AIRPLANE_MODE";
+ case BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED:
+ return "DISALLOWED";
+ case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED:
+ return "RESTARTED";
+ case BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR:
+ return "START_ERROR";
+ case BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT:
+ return "SYSTEM_BOOT";
+ case BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH:
+ return "CRASH";
+ case BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH:
+ return "USER_SWITCH";
+ case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING:
+ return "RESTORE_USER_SETTING";
+ case BluetoothProtoEnums.ENABLE_DISABLE_REASON_UNSPECIFIED:
+ default: return "UNKNOWN[" + reason + "]";
+ }
+ }
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 79297aa..30d31b8 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1705,6 +1705,7 @@
ni != null ? ni.getState().toString() : "?");
} catch (RemoteException e) {
}
+ intent.addFlags(Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
}
try {
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL, options);
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 0502117..45c9a71 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -35,6 +35,8 @@
# Power save state has changed. See BatterySaverController.java for the details.
2739 battery_saver_mode (prevOffOrOn|1|5),(nowOffOrOn|1|5),(interactive|1|5),(features|3|5)
27390 battery_saving_stats (batterySaver|1|5),(interactive|1|5),(doze|1|5),(delta_duration|2|3),(delta_battery_drain|1|1),(delta_battery_drain_percent|1|6),(total_duration|2|3),(total_battery_drain|1|1),(total_battery_drain_percent|1|6)
+# Note when the user activity timeout has been overriden by ActivityManagerService
+27391 user_activity_timeout_override (override|2|3)
#
# Leave IDs through 2740 for more power logs (2730 used by battery_discharge above)
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 70ca161..5b57c14 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -92,7 +92,6 @@
import android.content.res.TypedArray;
import android.database.ContentObserver;
import android.graphics.drawable.Drawable;
-import android.hardware.input.InputManagerInternal;
import android.inputmethodservice.InputMethodService;
import android.net.Uri;
import android.os.Binder;
@@ -2490,16 +2489,6 @@
}
}
- private void notifyInputMethodSubtypeChanged(final int userId,
- @Nullable final InputMethodInfo inputMethodInfo,
- @Nullable final InputMethodSubtype subtype) {
- final InputManagerInternal inputManagerInternal =
- LocalServices.getService(InputManagerInternal.class);
- if (inputManagerInternal != null) {
- inputManagerInternal.onInputMethodSubtypeChanged(userId, inputMethodInfo, subtype);
- }
- }
-
/* package */ void setInputMethodLocked(String id, int subtypeId) {
InputMethodInfo info = mMethodMap.get(id);
if (info == null) {
@@ -2534,10 +2523,8 @@
mCurMethod.changeInputMethodSubtype(newSubtype);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call changeInputMethodSubtype");
- return;
}
}
- notifyInputMethodSubtypeChanged(mSettings.getCurrentUserId(), info, newSubtype);
}
return;
}
@@ -2563,9 +2550,6 @@
} finally {
Binder.restoreCallingIdentity(ident);
}
-
- notifyInputMethodSubtypeChanged(mSettings.getCurrentUserId(), info,
- getCurrentInputMethodSubtypeLocked());
}
@Override
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 3927ebd..62e82a0 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -394,8 +394,10 @@
+ " callback.asBinder=" + callback.asBinder());
}
+ // TODO(b/70041899): Find a way to make this work for carrier-privileged callers.
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mContext, callingPackage, "addOnSubscriptionsChangedListener")) {
+ mContext, SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage,
+ "addOnSubscriptionsChangedListener")) {
return;
}
@@ -686,8 +688,9 @@
private boolean canReadPhoneState(String callingPackage, String message) {
try {
+ // TODO(b/70041899): Find a way to make this work for carrier-privileged callers.
return TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mContext, callingPackage, message);
+ mContext, SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage, message);
} catch (SecurityException e) {
return false;
}
@@ -1735,8 +1738,9 @@
}
if ((events & ENFORCE_PHONE_STATE_PERMISSION_MASK) != 0) {
- if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mContext, callingPackage, message)) {
+ // TODO(b/70041899): Find a way to make this work for carrier-privileged callers.
+ if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext,
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage, message)) {
return false;
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 62d91a8..96633da 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5150,35 +5150,39 @@
public void startRecentsActivity(Intent intent, IAssistDataReceiver assistDataReceiver,
IRecentsAnimationRunner recentsAnimationRunner) {
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "startRecentsActivity()");
+ final int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
try {
+ final int recentsUid;
+ final String recentsPackage;
+ final List<IBinder> topVisibleActivities;
synchronized (this) {
- final int recentsUid = mRecentTasks.getRecentsComponentUid();
final ComponentName recentsComponent = mRecentTasks.getRecentsComponent();
- final String recentsPackage = recentsComponent.getPackageName();
-
- // If provided, kick off the request for the assist data in the background before
- // starting the activity
- if (assistDataReceiver != null) {
- final AppOpsManager appOpsManager = (AppOpsManager)
- mContext.getSystemService(Context.APP_OPS_SERVICE);
- final AssistDataReceiverProxy proxy = new AssistDataReceiverProxy(
- assistDataReceiver, recentsPackage);
- final AssistDataRequester requester = new AssistDataRequester(mContext, this,
- mWindowManager, appOpsManager, proxy, this,
- OP_ASSIST_STRUCTURE, OP_NONE);
- requester.requestAssistData(mStackSupervisor.getTopVisibleActivities(),
- true /* fetchData */, false /* fetchScreenshots */,
- true /* allowFetchData */, false /* alloweFetchScreenshots */,
- recentsUid, recentsPackage);
- }
+ recentsPackage = recentsComponent.getPackageName();
+ recentsUid = mRecentTasks.getRecentsComponentUid();
+ topVisibleActivities = mStackSupervisor.getTopVisibleActivities();
// Start a new recents animation
final RecentsAnimation anim = new RecentsAnimation(this, mStackSupervisor,
- mActivityStartController, mWindowManager, mUserController);
+ mActivityStartController, mWindowManager, mUserController, callingPid);
anim.startRecentsActivity(intent, recentsAnimationRunner, recentsComponent,
recentsUid);
}
+
+ // If provided, kick off the request for the assist data in the background. Do not hold
+ // the AM lock as this will just proxy directly to the assist data receiver provided.
+ if (assistDataReceiver != null) {
+ final AppOpsManager appOpsManager = (AppOpsManager)
+ mContext.getSystemService(Context.APP_OPS_SERVICE);
+ final AssistDataReceiverProxy proxy = new AssistDataReceiverProxy(
+ assistDataReceiver, recentsPackage);
+ final AssistDataRequester requester = new AssistDataRequester(mContext, this,
+ mWindowManager, appOpsManager, proxy, this, OP_ASSIST_STRUCTURE, OP_NONE);
+ requester.requestAssistData(topVisibleActivities,
+ true /* fetchData */, false /* fetchScreenshots */,
+ true /* allowFetchData */, false /* allowFetchScreenshots */,
+ recentsUid, recentsPackage);
+ }
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -5397,11 +5401,12 @@
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
+ final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(bOptions);
final long origId = Binder.clearCallingIdentity();
try {
synchronized (this) {
return mStackSupervisor.startActivityFromRecents(callingPid, callingUid, taskId,
- SafeActivityOptions.fromBundle(bOptions));
+ safeOptions);
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -14338,6 +14343,28 @@
}
}
+ void setRunningRemoteAnimation(int pid, boolean runningRemoteAnimation) {
+ synchronized (ActivityManagerService.this) {
+ final ProcessRecord pr;
+ synchronized (mPidsSelfLocked) {
+ pr = mPidsSelfLocked.get(pid);
+ if (pr == null) {
+ Slog.w(TAG, "setRunningRemoteAnimation called on unknown pid: " + pid);
+ return;
+ }
+ }
+ if (pr.runningRemoteAnimation == runningRemoteAnimation) {
+ return;
+ }
+ pr.runningRemoteAnimation = runningRemoteAnimation;
+ if (DEBUG_OOM_ADJ) {
+ Slog.i(TAG, "Setting runningRemoteAnimation=" + pr.runningRemoteAnimation
+ + " for pid=" + pid);
+ }
+ updateOomAdjLocked(pr, true);
+ }
+ }
+
public final void enterSafeMode() {
synchronized(this) {
// It only makes sense to do this before the system is ready
@@ -22748,6 +22775,12 @@
foregroundActivities = true;
procState = PROCESS_STATE_CUR_TOP;
if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making top: " + app);
+ } else if (app.runningRemoteAnimation) {
+ adj = ProcessList.VISIBLE_APP_ADJ;
+ schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
+ app.adjType = "running-remote-anim";
+ procState = PROCESS_STATE_CUR_TOP;
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making running remote anim: " + app);
} else if (app.instr != null) {
// Don't want to kill running instrumentation.
adj = ProcessList.FOREGROUND_APP_ADJ;
@@ -22823,7 +22856,9 @@
app.adjType = "vis-activity";
if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to vis-activity: " + app);
}
- schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+ if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) {
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+ }
app.cached = false;
app.empty = false;
foregroundActivities = true;
@@ -22846,7 +22881,9 @@
app.adjType = "pause-activity";
if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to pause-activity: " + app);
}
- schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+ if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) {
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+ }
app.cached = false;
app.empty = false;
foregroundActivities = true;
@@ -25987,6 +26024,11 @@
}
}
+ @Override
+ public void setRunningRemoteAnimation(int pid, boolean runningRemoteAnimation) {
+ ActivityManagerService.this.setRunningRemoteAnimation(pid, runningRemoteAnimation);
+ }
+
/**
* Called after the network policy rules are updated by
* {@link com.android.server.net.NetworkPolicyManagerService} for a specific {@param uid}
@@ -26536,6 +26578,7 @@
throws RemoteException {
enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
"registerRemoteAnimations");
+ definition.setCallingPid(Binder.getCallingPid());
synchronized (this) {
final ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r == null) {
@@ -26555,6 +26598,7 @@
RemoteAnimationAdapter adapter) throws RemoteException {
enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
"registerRemoteAnimationForNextActivityStart");
+ adapter.setCallingPid(Binder.getCallingPid());
synchronized (this) {
final long origId = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 59f027a..8c49472 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1621,12 +1621,6 @@
return;
}
- if (isState(DESTROYED) || (state != DESTROYED && isState(DESTROYING))) {
- // We cannot move backwards from destroyed and destroying states.
- throw new IllegalArgumentException("cannot move back states once destroying"
- + "current:" + mState + " requested:" + state);
- }
-
final ActivityState prev = mState;
mState = state;
@@ -1641,23 +1635,6 @@
if (parent != null) {
parent.onActivityStateChanged(this, state, reason);
}
-
- if (isState(DESTROYING, DESTROYED)) {
- makeFinishingLocked();
-
- // When moving to the destroyed state, immediately destroy the activity in the
- // associated stack. Most paths for finishing an activity will handle an activity's path
- // to destroy through mechanisms such as ActivityStackSupervisor#mFinishingActivities.
- // However, moving to the destroyed state directly (as in the case of an app dying) and
- // marking it as finished will lead to cleanup steps that will prevent later handling
- // from happening.
- if (isState(DESTROYED)) {
- final ActivityStack stack = getStack();
- if (stack != null) {
- stack.activityDestroyedLocked(this, reason);
- }
- }
- }
}
ActivityState getState() {
@@ -1750,8 +1727,11 @@
// this when there is an activity waiting to become translucent as the extra binder
// calls will lead to noticeable jank. A later call to
// ActivityStack#ensureActivitiesVisibleLocked will bring the activity to the proper
- // paused state.
- if (isState(STOPPED, STOPPING) && stack.mTranslucentActivityWaiting == null) {
+ // paused state. We also avoid doing this for the activity the stack supervisor
+ // considers the resumed activity, as normal means will bring the activity from STOPPED
+ // to RESUMED. Adding PAUSING in this scenario will lead to double lifecycles.
+ if (isState(STOPPED, STOPPING) && stack.mTranslucentActivityWaiting == null
+ && mStackSupervisor.getResumedActivityLocked() != this) {
// Capture reason before state change
final String reason = getLifecycleDescription("makeVisibleIfNeeded");
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 7749bd7..4742575 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -2284,22 +2284,22 @@
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options);
+
+ // When resuming the top activity, it may be necessary to pause the top activity (for
+ // example, returning to the lock screen. We suppress the normal pause logic in
+ // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
+ // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here
+ // to ensure any necessary pause logic occurs. In the case where the Activity will be
+ // shown regardless of the lock screen, the call to
+ // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped.
+ final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
+ if (next == null || !next.canTurnScreenOn()) {
+ checkReadyForSleep();
+ }
} finally {
mStackSupervisor.inResumeTopActivity = false;
}
- // When resuming the top activity, it may be necessary to pause the top activity (for
- // example, returning to the lock screen. We suppress the normal pause logic in
- // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the end.
- // We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here to ensure
- // any necessary pause logic occurs. In the case where the Activity will be shown regardless
- // of the lock screen, the call to {@link ActivityStackSupervisor#checkReadyForSleepLocked}
- // is skipped.
- final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
- if (next == null || !next.canTurnScreenOn()) {
- checkReadyForSleep();
- }
-
return result;
}
@@ -2707,9 +2707,12 @@
if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to "
+ lastState + ": " + next);
next.setState(lastState, "resumeTopActivityInnerLocked");
- if (lastStack != null) {
+
+ // lastResumedActivity being non-null implies there is a lastStack present.
+ if (lastResumedActivity != null) {
lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
}
+
Slog.i(TAG, "Restarting because process died: " + next);
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
@@ -2854,7 +2857,7 @@
true /* includingParents */);
}
- final void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
+ void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
boolean newTask, boolean keepCurTransition, ActivityOptions options) {
TaskRecord rTask = r.getTask();
final int taskId = rTask.taskId;
@@ -3422,8 +3425,8 @@
* @param allowFocusSelf Is the focus allowed to remain on the same stack.
*/
private boolean adjustFocusToNextFocusableStack(String reason, boolean allowFocusSelf) {
- final ActivityStack stack = mStackSupervisor.getNextFocusableStackLocked(
- allowFocusSelf ? null : this);
+ final ActivityStack stack =
+ mStackSupervisor.getNextFocusableStackLocked(this, !allowFocusSelf);
final String myReason = reason + " adjustFocusToNextFocusableStack";
if (stack == null) {
return false;
@@ -3811,14 +3814,6 @@
final ActivityState prevState = r.getState();
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + r);
- // We are already destroying / have already destroyed the activity. Do not continue to
- // modify it. Note that we do not use ActivityRecord#finishing here as finishing is not
- // indicative of destruction (though destruction is indicative of finishing) as finishing
- // can be delayed below.
- if (r.isState(DESTROYING, DESTROYED)) {
- return null;
- }
-
r.setState(FINISHING, "finishCurrentActivityLocked");
final boolean finishingActivityInNonFocusedStack
= r.getStack() != mStackSupervisor.getFocusedStack()
@@ -4037,26 +4032,16 @@
* state to destroy so only the cleanup here is needed.
*
* Note: Call before #removeActivityFromHistoryLocked.
- *
- * @param r The {@link ActivityRecord} to cleanup.
- * @param cleanServices Whether services bound to the {@link ActivityRecord} should also be
- * cleaned up.
- * @param destroy Whether the {@link ActivityRecord} should be destroyed.
- * @param clearProcess Whether the client process should be cleared.
*/
- private void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean destroy,
- boolean clearProcess) {
+ private void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState) {
onActivityRemovedFromStack(r);
r.deferRelaunchUntilPaused = false;
r.frozenBeforeDestroy = false;
- if (destroy) {
+ if (setState) {
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + r + " (cleaning up)");
r.setState(DESTROYED, "cleanupActivityLocked");
- }
-
- if (clearProcess) {
if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + r);
r.app = null;
}
@@ -4271,7 +4256,7 @@
+ ", app=" + (r.app != null ? r.app.processName : "(null)"));
if (r.isState(DESTROYING, DESTROYED)) {
- if (DEBUG_STATES) Slog.v(TAG_STATES, "activity " + r + " already finishing."
+ if (DEBUG_STATES) Slog.v(TAG_STATES, "activity " + r + " already destroying."
+ "skipping request with reason:" + reason);
return false;
}
@@ -4282,8 +4267,7 @@
boolean removedFromHistory = false;
- cleanUpActivityLocked(r, false /* cleanServices */, false /* destroy */,
- false /*clearProcess*/);
+ cleanUpActivityLocked(r, false, false);
final boolean hadApp = r.app != null;
@@ -4380,6 +4364,10 @@
}
}
+ /**
+ * This method is to only be called from the client via binder when the activity is destroyed
+ * AND finished.
+ */
final void activityDestroyedLocked(ActivityRecord record, String reason) {
if (record != null) {
mHandler.removeMessages(DESTROY_TIMEOUT_MSG, record);
@@ -4389,8 +4377,7 @@
if (isInStackLocked(record) != null) {
if (record.isState(DESTROYING, DESTROYED)) {
- cleanUpActivityLocked(record, true /* cleanServices */, false /* destroy */,
- false /*clearProcess*/);
+ cleanUpActivityLocked(record, true, false);
removeActivityFromHistoryLocked(record, reason);
}
}
@@ -4499,8 +4486,7 @@
r.icicle = null;
}
}
- cleanUpActivityLocked(r, true /* cleanServices */, remove /* destroy */,
- true /*clearProcess*/);
+ cleanUpActivityLocked(r, true, true);
if (remove) {
removeActivityFromHistoryLocked(r, "appDied");
}
@@ -4511,11 +4497,11 @@
return hasVisibleActivities;
}
- private void updateTransitLocked(int transit, ActivityOptions options) {
+ private void updateTransitLocked(int transit, ActivityRecord starting,
+ ActivityOptions options) {
if (options != null) {
- ActivityRecord r = topRunningActivityLocked();
- if (r != null && !r.isState(RESUMED)) {
- r.updateOptionsLocked(options);
+ if (starting != null && !starting.isState(RESUMED)) {
+ starting.updateOptionsLocked(options);
} else {
ActivityOptions.abort(options);
}
@@ -4552,8 +4538,9 @@
}
}
- final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options,
- AppTimeTracker timeTracker, String reason) {
+ final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord starting,
+ boolean noAnimation, ActivityOptions options, AppTimeTracker timeTracker,
+ String reason) {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
final ActivityStack topStack = getDisplay().getTopStack();
@@ -4565,7 +4552,7 @@
if (noAnimation) {
ActivityOptions.abort(options);
} else {
- updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
+ updateTransitLocked(TRANSIT_TASK_TO_FRONT, starting, options);
}
return;
}
@@ -4603,7 +4590,7 @@
}
ActivityOptions.abort(options);
} else {
- updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
+ updateTransitLocked(TRANSIT_TASK_TO_FRONT, starting, options);
}
// If a new task is moved to the front, then mark the existing top activity as supporting
// picture-in-picture while paused only if the task would not be considered an oerlay on top
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 0216439..efc0d7d 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -679,7 +679,7 @@
void setFocusStackUnchecked(String reason, ActivityStack focusCandidate) {
if (!focusCandidate.isFocusable()) {
// The focus candidate isn't focusable. Move focus to the top stack that is focusable.
- focusCandidate = getNextFocusableStackLocked(focusCandidate);
+ focusCandidate = getNextFocusableStackLocked(focusCandidate, false /* ignoreCurrent */);
}
if (focusCandidate != mFocusedStack) {
@@ -2196,7 +2196,7 @@
}
final ActivityRecord r = task.getTopActivity();
- currentStack.moveTaskToFrontLocked(task, false /* noAnimation */, options,
+ currentStack.moveTaskToFrontLocked(task, r, false /* noAnimation */, options,
r == null ? null : r.appTimeTracker, reason);
if (DEBUG_STACK) Slog.d(TAG_STACK,
@@ -2429,27 +2429,50 @@
* Get next focusable stack in the system. This will search across displays and stacks
* in last-focused order for a focusable and visible stack, different from the target stack.
*
- * @param currentFocus The stack that previously had focus and thus needs to be ignored when
- * searching for next candidate.
+ * @param currentFocus The stack that previously had focus.
+ * @param ignoreCurrent If we should ignore {@param currentFocus} when searching for next
+ * candidate.
* @return Next focusable {@link ActivityStack}, null if not found.
*/
- ActivityStack getNextFocusableStackLocked(ActivityStack currentFocus) {
+ ActivityStack getNextFocusableStackLocked(ActivityStack currentFocus, boolean ignoreCurrent) {
mWindowManager.getDisplaysInFocusOrder(mTmpOrderedDisplayIds);
+ final int currentWindowingMode = currentFocus != null
+ ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
+ ActivityStack candidate = null;
for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) {
final int displayId = mTmpOrderedDisplayIds.get(i);
// If a display is registered in WM, it must also be available in AM.
final ActivityDisplay display = getActivityDisplayOrCreateLocked(displayId);
for (int j = display.getChildCount() - 1; j >= 0; --j) {
final ActivityStack stack = display.getChildAt(j);
- if (stack != currentFocus && stack.isFocusable()
- && stack.shouldBeVisible(null)) {
- return stack;
+ if (ignoreCurrent && stack == currentFocus) {
+ continue;
}
+ if (!stack.isFocusable() || !stack.shouldBeVisible(null)) {
+ continue;
+ }
+
+ if (currentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
+ && candidate == null && stack.inSplitScreenPrimaryWindowingMode()) {
+ // If the currently focused stack is in split-screen secondary we would prefer
+ // the focus to move to another split-screen secondary stack or fullscreen stack
+ // over the primary split screen stack to avoid:
+ // - Moving the focus to the primary split-screen stack when it can't be focused
+ // because it will be minimized, but AM doesn't know that yet
+ // - primary split-screen stack overlapping with a fullscreen stack when a
+ // fullscreen stack is higher in z than the next split-screen stack. Assistant
+ // stack, I am looking at you...
+ // We only move the focus to the primary-split screen stack if there isn't a
+ // better alternative.
+ candidate = stack;
+ continue;
+ }
+ return stack;
}
}
- return null;
+ return candidate;
}
/**
@@ -3353,10 +3376,11 @@
} else {
stack.awakeFromSleepingLocked();
if (isFocusedStack(stack)
- && !mKeyguardController.isKeyguardActive(display.mDisplayId)) {
- // If there is no keyguard on this display - resume immediately. Otherwise
- // we'll wait for keyguard visibility callback and resume while ensuring
- // activities visibility
+ && !mKeyguardController.isKeyguardShowing(display.mDisplayId)) {
+ // If the keyguard is unlocked - resume immediately.
+ // It is possible that the display will not be awake at the time we
+ // process the keyguard going away, which can happen before the sleep token
+ // is released. As a result, it is important we resume the activity here.
resumeFocusedStackTopActivityLocked();
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index bd53eac..2670235 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -1815,8 +1815,9 @@
// We only want to move to the front, if we aren't going to launch on a
// different stack. If we launch on a different stack, we will put the
// task on top there.
- mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
- mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
+ mTargetStack.moveTaskToFrontLocked(intentTask, mStartActivity, mNoAnimation,
+ mOptions, mStartActivity.appTimeTracker,
+ "bringingFoundTaskToFront");
mMovedToFront = true;
} else if (launchStack.inSplitScreenWindowingMode()) {
if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
@@ -1830,7 +1831,7 @@
// We choose to move task to front instead of launching it adjacent
// when specific stack was requested explicitly and it appeared to be
// adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
- mTargetStack.moveTaskToFrontLocked(intentTask,
+ mTargetStack.moveTaskToFrontLocked(intentTask, mStartActivity,
mNoAnimation, mOptions, mStartActivity.appTimeTracker,
"bringToFrontInsteadOfAdjacentLaunch");
}
@@ -2059,7 +2060,7 @@
final TaskRecord topTask = mTargetStack.topTask();
if (topTask != sourceTask && !mAvoidMoveToFront) {
- mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
+ mTargetStack.moveTaskToFrontLocked(sourceTask, mStartActivity, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, "sourceTaskToFront");
} else if (mDoResume) {
mTargetStack.moveToFront("sourceStackToFront");
@@ -2125,7 +2126,7 @@
&& top.userId == mStartActivity.userId) {
if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) {
- mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
+ mTargetStack.moveTaskToFrontLocked(mInTask, mStartActivity, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, "inTaskToFront");
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and the client said not to do
@@ -2138,7 +2139,7 @@
}
if (!mAddingToTask) {
- mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
+ mTargetStack.moveTaskToFrontLocked(mInTask, mStartActivity, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, "inTaskToFront");
// We don't actually want to have this activity added to the task, so just
// stop here but still tell the caller that we consumed the intent.
@@ -2158,8 +2159,8 @@
updateBounds(mInTask, mLaunchParams.mBounds);
}
- mTargetStack.moveTaskToFrontLocked(
- mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
+ mTargetStack.moveTaskToFrontLocked(mInTask, mStartActivity, mNoAnimation, mOptions,
+ mStartActivity.appTimeTracker, "inTaskToFront");
addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index 6b8b380..72882de 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -86,16 +86,8 @@
* display, false otherwise
*/
boolean isKeyguardShowing(int displayId) {
- return isKeyguardActive(displayId) && !mKeyguardGoingAway;
- }
-
- /**
- * @return true if Keyguard is showing and not occluded. We ignore whether it is going away or
- * not here.
- */
- boolean isKeyguardActive(int displayId) {
- return mKeyguardShowing && (displayId == DEFAULT_DISPLAY ? !mOccluded
- : displayId == mSecondaryDisplayShowing);
+ return mKeyguardShowing && !mKeyguardGoingAway &&
+ (displayId == DEFAULT_DISPLAY ? !mOccluded : displayId == mSecondaryDisplayShowing);
}
/**
diff --git a/services/core/java/com/android/server/am/LockTaskController.java b/services/core/java/com/android/server/am/LockTaskController.java
index af99111..ed39329 100644
--- a/services/core/java/com/android/server/am/LockTaskController.java
+++ b/services/core/java/com/android/server/am/LockTaskController.java
@@ -469,6 +469,7 @@
if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
getStatusBarService().showPinningEnterExitToast(false /* entering */);
}
+ mWindowManager.onLockTaskStateChanged(LOCK_TASK_MODE_NONE);
} catch (RemoteException ex) {
throw new RuntimeException(ex);
} finally {
@@ -580,6 +581,7 @@
if (lockTaskModeState == LOCK_TASK_MODE_PINNED) {
getStatusBarService().showPinningEnterExitToast(true /* entering */);
}
+ mWindowManager.onLockTaskStateChanged(lockTaskModeState);
mLockTaskModeState = lockTaskModeState;
setStatusBarState(lockTaskModeState, userId);
setKeyguardState(lockTaskModeState, userId);
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 1f60755..0bf2691 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -129,6 +129,12 @@
// When true the process will oom adj score will be set to
// ProcessList#PERCEPTIBLE_APP_ADJ at minimum to reduce the chance
// of the process getting killed.
+ boolean runningRemoteAnimation; // Is the process currently running a RemoteAnimation? When true
+ // the process will be set to use the
+ // ProcessList#SCHED_GROUP_TOP_APP scheduling group to boost
+ // performance, as well as oom adj score will be set to
+ // ProcessList#VISIBLE_APP_ADJ at minimum to reduce the chance
+ // of the process getting killed.
boolean pendingUiClean; // Want to clean up resources from showing UI?
boolean hasAboveClient; // Bound using BIND_ABOVE_CLIENT, so want to be lower
boolean treatLikeActivity; // Bound using BIND_TREAT_LIKE_ACTIVITY
@@ -336,9 +342,10 @@
pw.print(" hasAboveClient="); pw.print(hasAboveClient);
pw.print(" treatLikeActivity="); pw.println(treatLikeActivity);
}
- if (hasTopUi || hasOverlayUi) {
+ if (hasTopUi || hasOverlayUi || runningRemoteAnimation) {
pw.print(prefix); pw.print("hasTopUi="); pw.print(hasTopUi);
- pw.print(" hasOverlayUi="); pw.println(hasOverlayUi);
+ pw.print(" hasOverlayUi="); pw.print(hasOverlayUi);
+ pw.print(" runningRemoteAnimation="); pw.println(runningRemoteAnimation);
}
if (foregroundServices || forcingToImportant != null) {
pw.print(prefix); pw.print("foregroundServices="); pw.print(foregroundServices);
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index 99f5298..3f05ece 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -828,6 +828,25 @@
}
/**
+ * @return ids of tasks that are presented in Recents UI.
+ */
+ SparseBooleanArray getRecentTaskIds() {
+ final SparseBooleanArray res = new SparseBooleanArray();
+ final int size = mTasks.size();
+ int numVisibleTasks = 0;
+ for (int i = 0; i < size; i++) {
+ final TaskRecord tr = mTasks.get(i);
+ if (isVisibleRecentTask(tr)) {
+ numVisibleTasks++;
+ if (isInVisibleRange(tr, numVisibleTasks)) {
+ res.put(tr.taskId, true);
+ }
+ }
+ }
+ return res;
+ }
+
+ /**
* @return the task in the task list with the given {@param id} if one exists.
*/
TaskRecord getTask(int id) {
@@ -1219,20 +1238,16 @@
* list (if any).
*/
private int findRemoveIndexForAddTask(TaskRecord task) {
- int recentsCount = mTasks.size();
+ final int recentsCount = mTasks.size();
+ final int taskActivityType = task.getActivityType();
final Intent intent = task.intent;
final boolean document = intent != null && intent.isDocument();
int maxRecents = task.maxRecents - 1;
- final ActivityStack stack = task.getStack();
for (int i = 0; i < recentsCount; i++) {
final TaskRecord tr = mTasks.get(i);
- final ActivityStack trStack = tr.getStack();
-
+ final int trActivityType = tr.getActivityType();
if (task != tr) {
- if (stack != null && trStack != null && stack != trStack) {
- continue;
- }
- if (task.userId != tr.userId) {
+ if (taskActivityType != trActivityType || task.userId != tr.userId) {
continue;
}
final Intent trIntent = tr.intent;
diff --git a/services/core/java/com/android/server/am/RecentsAnimation.java b/services/core/java/com/android/server/am/RecentsAnimation.java
index 4b1594c..9121568 100644
--- a/services/core/java/com/android/server/am/RecentsAnimation.java
+++ b/services/core/java/com/android/server/am/RecentsAnimation.java
@@ -16,7 +16,6 @@
package com.android.server.am;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
@@ -50,6 +49,7 @@
private final WindowManagerService mWindowManager;
private final UserController mUserController;
private final Handler mHandler;
+ private final int mCallingPid;
private final Runnable mCancelAnimationRunnable;
@@ -58,13 +58,14 @@
RecentsAnimation(ActivityManagerService am, ActivityStackSupervisor stackSupervisor,
ActivityStartController activityStartController, WindowManagerService wm,
- UserController userController) {
+ UserController userController, int callingPid) {
mService = am;
mStackSupervisor = stackSupervisor;
mActivityStartController = activityStartController;
mHandler = new Handler(mStackSupervisor.mLooper);
mWindowManager = wm;
mUserController = userController;
+ mCallingPid = callingPid;
mCancelAnimationRunnable = () -> {
// The caller has not finished the animation in a predefined amount of time, so
@@ -94,9 +95,10 @@
}
}
+ mService.setRunningRemoteAnimation(mCallingPid, true);
+
mWindowManager.deferSurfaceLayout();
try {
-
final ActivityDisplay display;
if (hasExistingHomeActivity) {
// Move the home activity into place for the animation if it is not already top most
@@ -136,7 +138,7 @@
// started
mWindowManager.cancelRecentsAnimation();
mWindowManager.initializeRecentsAnimation(recentsAnimationRunner, this,
- display.mDisplayId);
+ display.mDisplayId, mStackSupervisor.mRecentTasks.getRecentTaskIds());
// If we updated the launch-behind state, update the visibility of the activities after
// we fetch the visible tasks to be controlled by the animation
@@ -153,6 +155,8 @@
synchronized (mService) {
if (mWindowManager.getRecentsAnimationController() == null) return;
+ mService.setRunningRemoteAnimation(mCallingPid, false);
+
mWindowManager.inSurfaceTransaction(() -> {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER,
"RecentsAnimation#onAnimationFinished_inSurfaceTransaction");
diff --git a/services/core/java/com/android/server/am/SafeActivityOptions.java b/services/core/java/com/android/server/am/SafeActivityOptions.java
index d08111e..ac6f01f 100644
--- a/services/core/java/com/android/server/am/SafeActivityOptions.java
+++ b/services/core/java/com/android/server/am/SafeActivityOptions.java
@@ -121,10 +121,16 @@
if (mOriginalOptions != null) {
checkPermissions(intent, aInfo, callerApp, supervisor, mOriginalOptions,
mOriginalCallingPid, mOriginalCallingUid);
+ if (mOriginalOptions.getRemoteAnimationAdapter() != null) {
+ mOriginalOptions.getRemoteAnimationAdapter().setCallingPid(mOriginalCallingPid);
+ }
}
if (mCallerOptions != null) {
checkPermissions(intent, aInfo, callerApp, supervisor, mCallerOptions,
mRealCallingPid, mRealCallingUid);
+ if (mCallerOptions.getRemoteAnimationAdapter() != null) {
+ mCallerOptions.getRemoteAnimationAdapter().setCallingPid(mRealCallingPid);
+ }
}
return mergeActivityOptions(mOriginalOptions, mCallerOptions);
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 94a64eb..9ef84d2 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -39,6 +39,7 @@
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -256,6 +257,7 @@
private static final int MSG_SET_A2DP_SINK_CONNECTION_STATE = 102;
private static final int MSG_A2DP_DEVICE_CONFIG_CHANGE = 103;
private static final int MSG_DISABLE_AUDIO_FOR_UID = 104;
+ private static final int MSG_SET_HEARING_AID_CONNECTION_STATE = 105;
// end of messages handled under wakelock
private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000;
@@ -265,6 +267,8 @@
// retry delay in case of failure to indicate system ready to AudioFlinger
private static final int INDICATE_SYSTEM_READY_RETRY_DELAY_MS = 1000;
+ private static final int BT_HEARING_AID_GAIN_MIN = -128;
+
/** @see AudioSystemThread */
private AudioSystemThread mAudioSystemThread;
/** @see AudioHandler */
@@ -573,7 +577,7 @@
AudioSystem.DEVICE_OUT_HDMI_ARC |
AudioSystem.DEVICE_OUT_SPDIF |
AudioSystem.DEVICE_OUT_AUX_LINE;
- int mFullVolumeDevices = 0;
+ int mFullVolumeDevices = AudioSystem.DEVICE_OUT_HEARING_AID;
private final boolean mMonitorRotation;
@@ -590,6 +594,10 @@
private final MediaFocusControl mMediaFocusControl;
+ // Reference to BluetoothA2dp to query for volume.
+ private BluetoothHearingAid mHearingAid;
+ // lock always taken synchronized on mConnectedDevices
+ private final Object mHearingAidLock = new Object();
// Reference to BluetoothA2dp to query for AbsoluteVolume.
private BluetoothA2dp mA2dp;
// lock always taken synchronized on mConnectedDevices
@@ -719,6 +727,36 @@
}
}
+ int maxAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_steps", -1);
+ if (maxAlarmVolume != -1) {
+ MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = maxAlarmVolume;
+ }
+
+ int defaultAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_default", -1);
+ if (defaultAlarmVolume != -1 &&
+ defaultAlarmVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]) {
+ AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = defaultAlarmVolume;
+ } else {
+ // Default is 6 out of 7 (default maximum), so scale accordingly.
+ AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] =
+ 6 * MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] / 7;
+ }
+
+ int maxSystemVolume = SystemProperties.getInt("ro.config.system_vol_steps", -1);
+ if (maxSystemVolume != -1) {
+ MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = maxSystemVolume;
+ }
+
+ int defaultSystemVolume = SystemProperties.getInt("ro.config.system_vol_default", -1);
+ if (defaultSystemVolume != -1 &&
+ defaultSystemVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM]) {
+ AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = defaultSystemVolume;
+ } else {
+ // Default is to use maximum.
+ AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] =
+ MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM];
+ }
+
sSoundEffectVolumeDb = context.getResources().getInteger(
com.android.internal.R.integer.config_soundEffectVolumeDb);
@@ -849,6 +887,8 @@
if (adapter != null) {
adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
BluetoothProfile.A2DP);
+ adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
+ BluetoothProfile.HEARING_AID);
}
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
@@ -1607,6 +1647,20 @@
}
}
+ // Check if volume update should be send to Hearing Aid
+ if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
+ synchronized (mHearingAidLock) {
+ if (mHearingAid != null) {
+ //hearing aid expect volume value in range -128dB to 0dB
+ int gainDB = (int)AudioSystem.getStreamVolumeDB(streamType, newIndex/10,
+ AudioSystem.DEVICE_OUT_HEARING_AID);
+ if (gainDB < BT_HEARING_AID_GAIN_MIN)
+ gainDB = BT_HEARING_AID_GAIN_MIN;
+ mHearingAid.setVolume(gainDB);
+ }
+ }
+ }
+
// Check if volume update should be sent to Hdmi system audio.
if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
setSystemAudioVolume(oldIndex, newIndex, getStreamMaxVolume(streamType), flags);
@@ -1852,6 +1906,19 @@
}
}
+ if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
+ synchronized (mHearingAidLock) {
+ if (mHearingAid != null) {
+ //hearing aid expect volume value in range -128dB to 0dB
+ int gainDB = (int)AudioSystem.getStreamVolumeDB(streamType, index/10, AudioSystem.DEVICE_OUT_HEARING_AID);
+ if (gainDB < BT_HEARING_AID_GAIN_MIN)
+ gainDB = BT_HEARING_AID_GAIN_MIN;
+ mHearingAid.setVolume(gainDB);
+
+ }
+ }
+ }
+
if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
setSystemAudioVolume(oldIndex, index, getStreamMaxVolume(streamType), flags);
}
@@ -1915,7 +1982,16 @@
}
mUserSelectedVolumeControlStream = false;
} else {
- mForceControlStreamClient = new ForceControlStreamClient(cb);
+ if (null == mForceControlStreamClient) {
+ mForceControlStreamClient = new ForceControlStreamClient(cb);
+ } else {
+ if (mForceControlStreamClient.getBinder() == cb) {
+ Log.d(TAG, "forceVolumeControlStream cb:" + cb + " is already linked.");
+ } else {
+ mForceControlStreamClient.release();
+ mForceControlStreamClient = new ForceControlStreamClient(cb);
+ }
+ }
}
}
}
@@ -1955,6 +2031,10 @@
mCb = null;
}
}
+
+ public IBinder getBinder() {
+ return mCb;
+ }
}
private void sendBroadcastToAll(Intent intent) {
@@ -3596,6 +3676,30 @@
}
break;
+ case BluetoothProfile.HEARING_AID:
+ synchronized (mConnectedDevices) {
+ synchronized (mHearingAidLock) {
+ mHearingAid = (BluetoothHearingAid) proxy;
+ deviceList = mHearingAid.getConnectedDevices();
+ if (deviceList.size() > 0) {
+ btDevice = deviceList.get(0);
+ int state = mHearingAid.getConnectionState(btDevice);
+ int intState = (state == BluetoothHearingAid.STATE_CONNECTED) ? 1 : 0;
+ int delay = checkSendBecomingNoisyIntent(
+ AudioSystem.DEVICE_OUT_HEARING_AID, intState,
+ AudioSystem.DEVICE_NONE);
+ queueMsgUnderWakeLock(mAudioHandler,
+ MSG_SET_HEARING_AID_CONNECTION_STATE,
+ state,
+ 0 /* arg2 unused */,
+ btDevice,
+ delay);
+ }
+ }
+ }
+
+ break;
+
default:
break;
}
@@ -3615,6 +3719,10 @@
disconnectHeadset();
break;
+ case BluetoothProfile.HEARING_AID:
+ disconnectHearingAid();
+ break;
+
default:
break;
}
@@ -3625,6 +3733,7 @@
disconnectA2dp();
disconnectA2dpSink();
disconnectHeadset();
+ disconnectHearingAid();
}
void disconnectA2dp() {
@@ -3676,6 +3785,29 @@
}
}
+ void disconnectHearingAid() {
+ synchronized (mConnectedDevices) {
+ synchronized (mHearingAidLock) {
+ ArraySet<String> toRemove = null;
+ // Disconnect ALL DEVICE_OUT_HEARING_AID devices
+ for (int i = 0; i < mConnectedDevices.size(); i++) {
+ DeviceListSpec deviceSpec = mConnectedDevices.valueAt(i);
+ if (deviceSpec.mDeviceType == AudioSystem.DEVICE_OUT_HEARING_AID) {
+ toRemove = toRemove != null ? toRemove : new ArraySet<String>();
+ toRemove.add(deviceSpec.mDeviceAddress);
+ }
+ }
+ if (toRemove != null) {
+ int delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_HEARING_AID,
+ 0, AudioSystem.DEVICE_NONE);
+ for (int i = 0; i < toRemove.size(); i++) {
+ makeHearingAidDeviceUnavailable(toRemove.valueAt(i) /*, delay*/);
+ }
+ }
+ }
+ }
+ }
+
private void onCheckMusicActive(String caller) {
synchronized (mSafeMediaVolumeState) {
if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
@@ -4187,7 +4319,8 @@
handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time);
if (msg == MSG_SET_WIRED_DEVICE_CONNECTION_STATE ||
msg == MSG_SET_A2DP_SRC_CONNECTION_STATE ||
- msg == MSG_SET_A2DP_SINK_CONNECTION_STATE) {
+ msg == MSG_SET_A2DP_SINK_CONNECTION_STATE ||
+ msg == MSG_SET_HEARING_AID_CONNECTION_STATE) {
mLastDeviceConnectMsgTime = time;
}
}
@@ -4290,6 +4423,33 @@
@Override
public void setHearingAidDeviceConnectionState(BluetoothDevice device, int state)
{
+ Log.i(TAG, "setBluetoothHearingAidDeviceConnectionState");
+
+ setBluetoothHearingAidDeviceConnectionState(
+ device, state, false /* suppressNoisyIntent */, AudioSystem.DEVICE_NONE);
+ }
+
+ public int setBluetoothHearingAidDeviceConnectionState(
+ BluetoothDevice device, int state, boolean suppressNoisyIntent,
+ int musicDevice)
+ {
+ int delay;
+ synchronized (mConnectedDevices) {
+ if (!suppressNoisyIntent) {
+ int intState = (state == BluetoothHearingAid.STATE_CONNECTED) ? 1 : 0;
+ delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_HEARING_AID,
+ intState, musicDevice);
+ } else {
+ delay = 0;
+ }
+ queueMsgUnderWakeLock(mAudioHandler,
+ MSG_SET_HEARING_AID_CONNECTION_STATE,
+ state,
+ 0 /* arg2 unused */,
+ device,
+ delay);
+ }
+ return delay;
}
public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile)
@@ -5231,6 +5391,11 @@
mAudioEventWakeLock.release();
break;
+ case MSG_SET_HEARING_AID_CONNECTION_STATE:
+ onSetHearingAidConnectionState((BluetoothDevice)msg.obj, msg.arg1);
+ mAudioEventWakeLock.release();
+ break;
+
case MSG_A2DP_DEVICE_CONFIG_CHANGE:
onBluetoothA2dpDeviceConfigChange((BluetoothDevice)msg.obj);
mAudioEventWakeLock.release();
@@ -5423,14 +5588,8 @@
AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "");
mConnectedDevices.remove(
makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address));
- synchronized (mCurAudioRoutes) {
- // Remove A2DP routes as well
- if (mCurAudioRoutes.bluetoothName != null) {
- mCurAudioRoutes.bluetoothName = null;
- sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
- SENDMSG_NOOP, 0, 0, null, 0);
- }
- }
+ // Remove A2DP routes as well
+ setCurrentAudioRouteName(null);
}
// must be called synchronized on mConnectedDevices
@@ -5466,6 +5625,28 @@
}
// must be called synchronized on mConnectedDevices
+ private void makeHearingAidDeviceAvailable(String address, String name, String eventSource) {
+ AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID,
+ AudioSystem.DEVICE_STATE_AVAILABLE, address, name);
+ mConnectedDevices.put(
+ makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID, address),
+ new DeviceListSpec(AudioSystem.DEVICE_OUT_HEARING_AID, name,
+ address));
+ sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE,
+ AudioSystem.DEVICE_OUT_HEARING_AID, 0, null, 0);
+ }
+
+ // must be called synchronized on mConnectedDevices
+ private void makeHearingAidDeviceUnavailable(String address) {
+ AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID,
+ AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "");
+ mConnectedDevices.remove(
+ makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID, address));
+ // Remove Hearing Aid routes as well
+ setCurrentAudioRouteName(null);
+ }
+
+ // must be called synchronized on mConnectedDevices
private void cancelA2dpDeviceTimeout() {
mAudioHandler.removeMessages(MSG_BTA2DP_DOCK_TIMEOUT);
}
@@ -5506,13 +5687,7 @@
} else {
makeA2dpDeviceUnavailableNow(address);
}
- synchronized (mCurAudioRoutes) {
- if (mCurAudioRoutes.bluetoothName != null) {
- mCurAudioRoutes.bluetoothName = null;
- sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
- SENDMSG_NOOP, 0, 0, null, 0);
- }
- }
+ setCurrentAudioRouteName(null);
} else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
if (btDevice.isBluetoothDock()) {
// this could be a reconnection after a transient disconnection
@@ -5528,14 +5703,7 @@
}
makeA2dpDeviceAvailable(address, btDevice.getName(),
"onSetA2dpSinkConnectionState");
- synchronized (mCurAudioRoutes) {
- String name = btDevice.getAliasName();
- if (!TextUtils.equals(mCurAudioRoutes.bluetoothName, name)) {
- mCurAudioRoutes.bluetoothName = name;
- sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
- SENDMSG_NOOP, 0, 0, null, 0);
- }
- }
+ setCurrentAudioRouteName(btDevice.getAliasName());
}
}
}
@@ -5566,6 +5734,46 @@
}
}
+ private void onSetHearingAidConnectionState(BluetoothDevice btDevice, int state)
+ {
+ if (DEBUG_DEVICES) {
+ Log.d(TAG, "onSetHearingAidConnectionState btDevice=" + btDevice+", state=" + state);
+ }
+ if (btDevice == null) {
+ return;
+ }
+ String address = btDevice.getAddress();
+ if (!BluetoothAdapter.checkBluetoothAddress(address)) {
+ address = "";
+ }
+
+ synchronized (mConnectedDevices) {
+ final String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID,
+ btDevice.getAddress());
+ final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
+ boolean isConnected = deviceSpec != null;
+
+ if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
+ makeHearingAidDeviceUnavailable(address);
+ setCurrentAudioRouteName(null);
+ } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
+ makeHearingAidDeviceAvailable(address, btDevice.getName(),
+ "onSetHearingAidConnectionState");
+ setCurrentAudioRouteName(btDevice.getAliasName());
+ }
+ }
+ }
+
+ private void setCurrentAudioRouteName(String name){
+ synchronized (mCurAudioRoutes) {
+ if (!TextUtils.equals(mCurAudioRoutes.bluetoothName, name)) {
+ mCurAudioRoutes.bluetoothName = name;
+ sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
+ SENDMSG_NOOP, 0, 0, null, 0);
+ }
+ }
+ }
+
private void onBluetoothA2dpDeviceConfigChange(BluetoothDevice btDevice)
{
if (DEBUG_DEVICES) {
@@ -5701,6 +5909,7 @@
if (mAudioHandler.hasMessages(MSG_SET_A2DP_SRC_CONNECTION_STATE) ||
mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE) ||
+ mAudioHandler.hasMessages(MSG_SET_HEARING_AID_CONNECTION_STATE) ||
mAudioHandler.hasMessages(MSG_SET_WIRED_DEVICE_CONNECTION_STATE)) {
synchronized (mLastDeviceConnectMsgTime) {
long time = SystemClock.uptimeMillis();
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java b/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
index 406231a..954c001 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
@@ -101,7 +101,9 @@
}
TunerSession session = module.openSession(callback);
- session.setConfiguration(legacyConfig);
+ if (legacyConfig != null) {
+ session.setConfiguration(legacyConfig);
+ }
return session;
}
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
index daec97a..816ba0b 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
@@ -55,7 +55,7 @@
public static @Nullable RadioModule tryLoadingModule(int idx, @NonNull String fqName) {
try {
- IBroadcastRadio service = IBroadcastRadio.getService();
+ IBroadcastRadio service = IBroadcastRadio.getService(fqName);
if (service == null) return null;
Mutable<AmFmRegionConfig> amfmConfig = new Mutable<>();
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
index 8efaa2a..8f3f099 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
@@ -90,7 +90,8 @@
if (ret == AudioSystem.AUDIO_STATUS_OK) {
mIsAudioConnected = connected;
} else {
- Slog.e(TAG, "Failed to notify AudioService about new state: " + connected);
+ Slog.e(TAG, "Failed to notify AudioService about new state: "
+ + connected + ", response was: " + ret);
}
}
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index f1a806b..4f31e53 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -102,9 +102,12 @@
/**
- * There are only 2 possible callbacks.
+ * There are only 3 possible callbacks.
*
- * mNetdEventCallbackList[CALLBACK_CALLER_DEVICE_POLICY].
+ * mNetdEventCallbackList[CALLBACK_CALLER_CONNECTIVITY_SERVICE]
+ * Callback registered/unregistered by ConnectivityService.
+ *
+ * mNetdEventCallbackList[CALLBACK_CALLER_DEVICE_POLICY]
* Callback registered/unregistered when logging is being enabled/disabled in DPM
* by the device owner. It's DevicePolicyManager's responsibility to ensure that.
*
@@ -113,6 +116,7 @@
*/
@GuardedBy("this")
private static final int[] ALLOWED_CALLBACK_TYPES = {
+ INetdEventCallback.CALLBACK_CALLER_CONNECTIVITY_SERVICE,
INetdEventCallback.CALLBACK_CALLER_DEVICE_POLICY,
INetdEventCallback.CALLBACK_CALLER_NETWORK_WATCHLIST
};
@@ -212,6 +216,19 @@
@Override
// Called concurrently by multiple binder threads.
// This method must not block or perform long-running operations.
+ public synchronized void onPrivateDnsValidationEvent(int netId,
+ String ipAddress, String hostname, boolean validated)
+ throws RemoteException {
+ for (INetdEventCallback callback : mNetdEventCallbackList) {
+ if (callback != null) {
+ callback.onPrivateDnsValidationEvent(netId, ipAddress, hostname, validated);
+ }
+ }
+ }
+
+ @Override
+ // Called concurrently by multiple binder threads.
+ // This method must not block or perform long-running operations.
public synchronized void onConnectEvent(int netId, int error, int latencyMs, String ipAddr,
int port, int uid) throws RemoteException {
long timestamp = System.currentTimeMillis();
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index b7385d8..0d8ec6d 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -404,7 +404,8 @@
&& SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) {
mInfo.flags |= DisplayDeviceInfo.FLAG_ROUND;
}
- mInfo.displayCutout = DisplayCutout.fromResources(res, mInfo.width);
+ mInfo.displayCutout = DisplayCutout.fromResources(res, mInfo.width,
+ mInfo.height);
mInfo.type = Display.TYPE_BUILT_IN;
mInfo.densityDpi = (int)(phys.density * 160 + 0.5f);
mInfo.xDpi = phys.xDpi;
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index c3259c3..ac85484 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -26,8 +26,10 @@
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.AlarmManager;
import android.app.AppOpsManager;
+import android.app.IActivityManager;
import android.app.PendingIntent;
import android.app.SynchronousUserSwitchObserver;
+import android.app.TaskStackListener;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -137,6 +139,7 @@
@GuardedBy("this")
private IBiometricsFingerprint mDaemon;
private IStatusBarService mStatusBarService;
+ private final IActivityManager mActivityManager;
private final PowerManager mPowerManager;
private final AlarmManager mAlarmManager;
private final UserManager mUserManager;
@@ -215,6 +218,30 @@
}
};
+ private final TaskStackListener mTaskStackListener = new TaskStackListener() {
+ @Override
+ public void onTaskStackChanged() {
+ try {
+ if (!(mCurrentClient instanceof AuthenticationClient)) {
+ return;
+ }
+ if (isKeyguard(mCurrentClient.getOwnerString())) {
+ return; // Keyguard is always allowed
+ }
+ List<ActivityManager.RunningTaskInfo> runningTasks = mActivityManager.getTasks(1);
+ if (!runningTasks.isEmpty()) {
+ if (runningTasks.get(0).topActivity.getPackageName()
+ != mCurrentClient.getOwnerString()) {
+ mCurrentClient.stop(false /* initiatedByClient */);
+ Slog.e(TAG, "Stopping background authentication");
+ }
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to get running tasks", e);
+ }
+ }
+ };
+
public FingerprintService(Context context) {
super(context);
mContext = context;
@@ -230,6 +257,13 @@
mFailedAttempts = new SparseIntArray();
mStatusBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+ mActivityManager = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE))
+ .getService();
+ try {
+ mActivityManager.registerTaskStackListener(mTaskStackListener);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Could not register task stack listener", e);
+ }
}
@Override
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index a951d47..451acf4 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -17,12 +17,10 @@
package com.android.server.input;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.os.LocaleList;
import android.os.ShellCallback;
import android.util.Log;
import android.view.Display;
-import com.android.internal.inputmethod.InputMethodSubtypeHandle;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.SomeArgs;
@@ -79,8 +77,6 @@
import android.os.MessageQueue;
import android.os.Process;
import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.os.ShellCommand;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
@@ -99,8 +95,7 @@
import android.view.PointerIcon;
import android.view.Surface;
import android.view.ViewConfiguration;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodSubtype;
+import android.widget.Toast;
import java.io.File;
import java.io.FileDescriptor;
@@ -137,7 +132,6 @@
private static final int MSG_UPDATE_KEYBOARD_LAYOUTS = 4;
private static final int MSG_RELOAD_DEVICE_ALIASES = 5;
private static final int MSG_DELIVER_TABLET_MODE_CHANGED = 6;
- private static final int MSG_INPUT_METHOD_SUBTYPE_CHANGED = 7;
// Pointer to native input manager service object.
private final long mPtr;
@@ -174,7 +168,8 @@
private final ArrayList<InputDevice>
mTempFullKeyboards = new ArrayList<InputDevice>(); // handler thread only
private boolean mKeyboardLayoutNotificationShown;
- private InputMethodSubtypeHandle mCurrentImeHandle;
+ private PendingIntent mKeyboardLayoutIntent;
+ private Toast mSwitchedKeyboardLayoutToast;
// State for vibrator tokens.
private Object mVibratorLock = new Object();
@@ -1368,82 +1363,6 @@
}
@Override // Binder call
- @Nullable
- public KeyboardLayout getKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
- InputMethodInfo imeInfo, InputMethodSubtype imeSubtype) {
- InputMethodSubtypeHandle handle = new InputMethodSubtypeHandle(imeInfo, imeSubtype);
- String key = getLayoutDescriptor(identifier);
- final String keyboardLayoutDescriptor;
- synchronized (mDataStore) {
- keyboardLayoutDescriptor = mDataStore.getKeyboardLayout(key, handle);
- }
-
- if (keyboardLayoutDescriptor == null) {
- return null;
- }
-
- final KeyboardLayout[] result = new KeyboardLayout[1];
- visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
- @Override
- public void visitKeyboardLayout(Resources resources,
- int keyboardLayoutResId, KeyboardLayout layout) {
- result[0] = layout;
- }
- });
- if (result[0] == null) {
- Slog.w(TAG, "Could not get keyboard layout with descriptor '"
- + keyboardLayoutDescriptor + "'.");
- }
- return result[0];
- }
-
- @Override
- public void setKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
- InputMethodInfo imeInfo, InputMethodSubtype imeSubtype,
- String keyboardLayoutDescriptor) {
- if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
- "setKeyboardLayoutForInputDevice()")) {
- throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
- }
- if (keyboardLayoutDescriptor == null) {
- throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
- }
- if (imeInfo == null) {
- throw new IllegalArgumentException("imeInfo must not be null");
- }
- InputMethodSubtypeHandle handle = new InputMethodSubtypeHandle(imeInfo, imeSubtype);
- setKeyboardLayoutForInputDeviceInner(identifier, handle, keyboardLayoutDescriptor);
- }
-
- private void setKeyboardLayoutForInputDeviceInner(InputDeviceIdentifier identifier,
- InputMethodSubtypeHandle imeHandle, String keyboardLayoutDescriptor) {
- String key = getLayoutDescriptor(identifier);
- synchronized (mDataStore) {
- try {
- if (mDataStore.setKeyboardLayout(key, imeHandle, keyboardLayoutDescriptor)) {
- if (DEBUG) {
- Slog.d(TAG, "Set keyboard layout " + keyboardLayoutDescriptor +
- " for subtype " + imeHandle + " and device " + identifier +
- " using key " + key);
- }
- if (imeHandle.equals(mCurrentImeHandle)) {
- if (DEBUG) {
- Slog.d(TAG, "Layout for current subtype changed, switching layout");
- }
- SomeArgs args = SomeArgs.obtain();
- args.arg1 = identifier;
- args.arg2 = imeHandle;
- mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, args).sendToTarget();
- }
- mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
- }
- } finally {
- mDataStore.saveIfNeeded();
- }
- }
- }
-
- @Override // Binder call
public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor) {
if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
@@ -1462,7 +1381,8 @@
oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
}
if (mDataStore.addKeyboardLayout(key, keyboardLayoutDescriptor)
- && !Objects.equals(oldLayout, mDataStore.getCurrentKeyboardLayout(key))) {
+ && !Objects.equals(oldLayout,
+ mDataStore.getCurrentKeyboardLayout(key))) {
mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
}
} finally {
@@ -1505,51 +1425,43 @@
}
}
- // Must be called on handler.
- private void handleSwitchInputMethodSubtype(int userId,
- @Nullable InputMethodInfo inputMethodInfo, @Nullable InputMethodSubtype subtype) {
- if (DEBUG) {
- Slog.i(TAG, "InputMethodSubtype changed: userId=" + userId
- + " ime=" + inputMethodInfo + " subtype=" + subtype);
- }
- if (inputMethodInfo == null) {
- Slog.d(TAG, "No InputMethod is running, ignoring change");
- return;
- }
- if (subtype != null && !"keyboard".equals(subtype.getMode())) {
- Slog.d(TAG, "InputMethodSubtype changed to non-keyboard subtype, ignoring change");
- return;
- }
- InputMethodSubtypeHandle handle = new InputMethodSubtypeHandle(inputMethodInfo, subtype);
- if (!handle.equals(mCurrentImeHandle)) {
- mCurrentImeHandle = handle;
- handleSwitchKeyboardLayout(null, handle);
- }
+ public void switchKeyboardLayout(int deviceId, int direction) {
+ mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, deviceId, direction).sendToTarget();
}
// Must be called on handler.
- private void handleSwitchKeyboardLayout(@Nullable InputDeviceIdentifier identifier,
- InputMethodSubtypeHandle handle) {
- synchronized (mInputDevicesLock) {
- for (InputDevice device : mInputDevices) {
- if (identifier != null && !device.getIdentifier().equals(identifier) ||
- !device.isFullKeyboard()) {
- continue;
+ private void handleSwitchKeyboardLayout(int deviceId, int direction) {
+ final InputDevice device = getInputDevice(deviceId);
+ if (device != null) {
+ final boolean changed;
+ final String keyboardLayoutDescriptor;
+
+ String key = getLayoutDescriptor(device.getIdentifier());
+ synchronized (mDataStore) {
+ try {
+ changed = mDataStore.switchKeyboardLayout(key, direction);
+ keyboardLayoutDescriptor = mDataStore.getCurrentKeyboardLayout(
+ key);
+ } finally {
+ mDataStore.saveIfNeeded();
}
- String key = getLayoutDescriptor(device.getIdentifier());
- boolean changed = false;
- synchronized (mDataStore) {
- try {
- if (mDataStore.switchKeyboardLayout(key, handle)) {
- changed = true;
- }
- } finally {
- mDataStore.saveIfNeeded();
+ }
+
+ if (changed) {
+ if (mSwitchedKeyboardLayoutToast != null) {
+ mSwitchedKeyboardLayoutToast.cancel();
+ mSwitchedKeyboardLayoutToast = null;
+ }
+ if (keyboardLayoutDescriptor != null) {
+ KeyboardLayout keyboardLayout = getKeyboardLayout(keyboardLayoutDescriptor);
+ if (keyboardLayout != null) {
+ mSwitchedKeyboardLayoutToast = Toast.makeText(
+ mContext, keyboardLayout.getLabel(), Toast.LENGTH_SHORT);
+ mSwitchedKeyboardLayoutToast.show();
}
}
- if (changed) {
- reloadKeyboardLayouts();
- }
+
+ reloadKeyboardLayouts();
}
}
}
@@ -1790,7 +1702,7 @@
}
@Override
- public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
pw.println("INPUT MANAGER (dumpsys input)\n");
@@ -1798,49 +1710,8 @@
if (dumpStr != null) {
pw.println(dumpStr);
}
- pw.println(" Keyboard Layouts:");
- visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
- @Override
- public void visitKeyboardLayout(Resources resources,
- int keyboardLayoutResId, KeyboardLayout layout) {
- pw.println(" \"" + layout + "\": " + layout.getDescriptor());
- }
- });
- pw.println();
- synchronized(mDataStore) {
- mDataStore.dump(pw, " ");
- }
}
- @Override
- public void onShellCommand(FileDescriptor in, FileDescriptor out,
- FileDescriptor err, String[] args, ShellCallback callback,
- ResultReceiver resultReceiver) {
- (new Shell()).exec(this, in, out, err, args, callback, resultReceiver);
- }
-
- public int onShellCommand(Shell shell, String cmd) {
- if (TextUtils.isEmpty(cmd)) {
- shell.onHelp();
- return 1;
- }
- if (cmd.equals("setlayout")) {
- if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
- "onShellCommand()")) {
- throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
- }
- InputMethodSubtypeHandle handle = new InputMethodSubtypeHandle(
- shell.getNextArgRequired(), Integer.parseInt(shell.getNextArgRequired()));
- String descriptor = shell.getNextArgRequired();
- int vid = Integer.decode(shell.getNextArgRequired());
- int pid = Integer.decode(shell.getNextArgRequired());
- InputDeviceIdentifier id = new InputDeviceIdentifier(descriptor, vid, pid);
- setKeyboardLayoutForInputDeviceInner(id, handle, shell.getNextArgRequired());
- }
- return 0;
- }
-
-
private boolean checkCallingPermission(String permission, String func) {
// Quick check: if the calling permission is me, it's all okay.
if (Binder.getCallingPid() == Process.myPid()) {
@@ -2169,12 +2040,9 @@
case MSG_DELIVER_INPUT_DEVICES_CHANGED:
deliverInputDevicesChanged((InputDevice[])msg.obj);
break;
- case MSG_SWITCH_KEYBOARD_LAYOUT: {
- SomeArgs args = (SomeArgs)msg.obj;
- handleSwitchKeyboardLayout((InputDeviceIdentifier)args.arg1,
- (InputMethodSubtypeHandle)args.arg2);
+ case MSG_SWITCH_KEYBOARD_LAYOUT:
+ handleSwitchKeyboardLayout(msg.arg1, msg.arg2);
break;
- }
case MSG_RELOAD_KEYBOARD_LAYOUTS:
reloadKeyboardLayouts();
break;
@@ -2184,22 +2052,12 @@
case MSG_RELOAD_DEVICE_ALIASES:
reloadDeviceAliases();
break;
- case MSG_DELIVER_TABLET_MODE_CHANGED: {
+ case MSG_DELIVER_TABLET_MODE_CHANGED:
SomeArgs args = (SomeArgs) msg.obj;
long whenNanos = (args.argi1 & 0xFFFFFFFFl) | ((long) args.argi2 << 32);
boolean inTabletMode = (boolean) args.arg1;
deliverTabletModeChanged(whenNanos, inTabletMode);
break;
- }
- case MSG_INPUT_METHOD_SUBTYPE_CHANGED: {
- final int userId = msg.arg1;
- final SomeArgs args = (SomeArgs) msg.obj;
- final InputMethodInfo inputMethodInfo = (InputMethodInfo) args.arg1;
- final InputMethodSubtype subtype = (InputMethodSubtype) args.arg2;
- args.recycle();
- handleSwitchInputMethodSubtype(userId, inputMethodInfo, subtype);
- break;
- }
}
}
}
@@ -2341,25 +2199,6 @@
}
}
- private class Shell extends ShellCommand {
- @Override
- public int onCommand(String cmd) {
- return onShellCommand(this, cmd);
- }
-
- @Override
- public void onHelp() {
- final PrintWriter pw = getOutPrintWriter();
- pw.println("Input manager commands:");
- pw.println(" help");
- pw.println(" Print this help text.");
- pw.println("");
- pw.println(" setlayout IME_ID IME_SUPTYPE_HASH_CODE"
- + " DEVICE_DESCRIPTOR VENDOR_ID PRODUCT_ID KEYBOARD_DESCRIPTOR");
- pw.println(" Sets a keyboard layout for a given IME subtype and input device pair");
- }
- }
-
private final class LocalService extends InputManagerInternal {
@Override
public void setDisplayViewports(DisplayViewport defaultViewport,
@@ -2380,16 +2219,6 @@
}
@Override
- public void onInputMethodSubtypeChanged(int userId,
- @Nullable InputMethodInfo inputMethodInfo, @Nullable InputMethodSubtype subtype) {
- final SomeArgs someArgs = SomeArgs.obtain();
- someArgs.arg1 = inputMethodInfo;
- someArgs.arg2 = subtype;
- mHandler.obtainMessage(MSG_INPUT_METHOD_SUBTYPE_CHANGED, userId, 0, someArgs)
- .sendToTarget();
- }
-
- @Override
public void toggleCapsLock(int deviceId) {
nativeToggleCapsLock(mPtr, deviceId);
}
diff --git a/services/core/java/com/android/server/input/PersistentDataStore.java b/services/core/java/com/android/server/input/PersistentDataStore.java
index c9f8b20..196787a 100644
--- a/services/core/java/com/android/server/input/PersistentDataStore.java
+++ b/services/core/java/com/android/server/input/PersistentDataStore.java
@@ -16,7 +16,6 @@
package com.android.server.input;
-import com.android.internal.inputmethod.InputMethodSubtypeHandle;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
@@ -28,8 +27,6 @@
import android.annotation.Nullable;
import android.view.Surface;
import android.hardware.input.TouchCalibration;
-import android.text.TextUtils;
-import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.Xml;
@@ -41,13 +38,10 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -139,26 +133,9 @@
}
return state.getKeyboardLayouts();
}
- public String getKeyboardLayout(String inputDeviceDescriptor,
- InputMethodSubtypeHandle imeHandle) {
- InputDeviceState state = getInputDeviceState(inputDeviceDescriptor, false);
- if (state == null) {
- return null;
- }
- return state.getKeyboardLayout(imeHandle);
- }
- public boolean setKeyboardLayout(String inputDeviceDescriptor,
- InputMethodSubtypeHandle imeHandle, String keyboardLayoutDescriptor) {
- InputDeviceState state = getInputDeviceState(inputDeviceDescriptor, true);
- if (state.setKeyboardLayout(imeHandle, keyboardLayoutDescriptor)) {
- setDirty();
- return true;
- }
- return false;
- }
-
- public boolean addKeyboardLayout(String inputDeviceDescriptor, String keyboardLayoutDescriptor) {
+ public boolean addKeyboardLayout(String inputDeviceDescriptor,
+ String keyboardLayoutDescriptor) {
InputDeviceState state = getInputDeviceState(inputDeviceDescriptor, true);
if (state.addKeyboardLayout(keyboardLayoutDescriptor)) {
setDirty();
@@ -177,10 +154,9 @@
return false;
}
- public boolean switchKeyboardLayout(String inputDeviceDescriptor,
- InputMethodSubtypeHandle imeHandle) {
+ public boolean switchKeyboardLayout(String inputDeviceDescriptor, int direction) {
InputDeviceState state = getInputDeviceState(inputDeviceDescriptor, false);
- if (state != null && state.switchKeyboardLayout(imeHandle)) {
+ if (state != null && state.switchKeyboardLayout(direction)) {
setDirty();
return true;
}
@@ -327,18 +303,6 @@
serializer.endDocument();
}
- public void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + "PersistentDataStore");
- pw.println(prefix + " mLoaded=" + mLoaded);
- pw.println(prefix + " mDirty=" + mDirty);
- pw.println(prefix + " InputDeviceStates:");
- int i = 0;
- for (Map.Entry<String, InputDeviceState> entry : mInputDevices.entrySet()) {
- pw.println(prefix + " " + i++ + ": " + entry.getKey());
- entry.getValue().dump(pw, prefix + " ");
- }
- }
-
private static final class InputDeviceState {
private static final String[] CALIBRATION_NAME = { "x_scale",
"x_ymix", "x_offset", "y_xmix", "y_scale", "y_offset" };
@@ -346,8 +310,7 @@
private TouchCalibration[] mTouchCalibration = new TouchCalibration[4];
@Nullable
private String mCurrentKeyboardLayout;
- private List<String> mUnassociatedKeyboardLayouts = new ArrayList<>();
- private ArrayMap<InputMethodSubtypeHandle, String> mKeyboardLayouts = new ArrayMap<>();
+ private ArrayList<String> mKeyboardLayouts = new ArrayList<String>();
public TouchCalibration getTouchCalibration(int surfaceRotation) {
try {
@@ -386,34 +349,18 @@
}
public String[] getKeyboardLayouts() {
- if (mUnassociatedKeyboardLayouts.isEmpty()) {
+ if (mKeyboardLayouts.isEmpty()) {
return (String[])ArrayUtils.emptyArray(String.class);
}
- return mUnassociatedKeyboardLayouts.toArray(
- new String[mUnassociatedKeyboardLayouts.size()]);
- }
-
- public String getKeyboardLayout(InputMethodSubtypeHandle handle) {
- return mKeyboardLayouts.get(handle);
- }
-
- public boolean setKeyboardLayout(InputMethodSubtypeHandle imeHandle,
- String keyboardLayout) {
- String existingLayout = mKeyboardLayouts.get(imeHandle);
- if (TextUtils.equals(existingLayout, keyboardLayout)) {
- return false;
- }
- mKeyboardLayouts.put(imeHandle, keyboardLayout);
- return true;
+ return mKeyboardLayouts.toArray(new String[mKeyboardLayouts.size()]);
}
public boolean addKeyboardLayout(String keyboardLayout) {
- int index = Collections.binarySearch(
- mUnassociatedKeyboardLayouts, keyboardLayout);
+ int index = Collections.binarySearch(mKeyboardLayouts, keyboardLayout);
if (index >= 0) {
return false;
}
- mUnassociatedKeyboardLayouts.add(-index - 1, keyboardLayout);
+ mKeyboardLayouts.add(-index - 1, keyboardLayout);
if (mCurrentKeyboardLayout == null) {
mCurrentKeyboardLayout = keyboardLayout;
}
@@ -421,11 +368,11 @@
}
public boolean removeKeyboardLayout(String keyboardLayout) {
- int index = Collections.binarySearch(mUnassociatedKeyboardLayouts, keyboardLayout);
+ int index = Collections.binarySearch(mKeyboardLayouts, keyboardLayout);
if (index < 0) {
return false;
}
- mUnassociatedKeyboardLayouts.remove(index);
+ mKeyboardLayouts.remove(index);
updateCurrentKeyboardLayoutIfRemoved(keyboardLayout, index);
return true;
}
@@ -433,34 +380,41 @@
private void updateCurrentKeyboardLayoutIfRemoved(
String removedKeyboardLayout, int removedIndex) {
if (Objects.equals(mCurrentKeyboardLayout, removedKeyboardLayout)) {
- if (!mUnassociatedKeyboardLayouts.isEmpty()) {
+ if (!mKeyboardLayouts.isEmpty()) {
int index = removedIndex;
- if (index == mUnassociatedKeyboardLayouts.size()) {
+ if (index == mKeyboardLayouts.size()) {
index = 0;
}
- mCurrentKeyboardLayout = mUnassociatedKeyboardLayouts.get(index);
+ mCurrentKeyboardLayout = mKeyboardLayouts.get(index);
} else {
mCurrentKeyboardLayout = null;
}
}
}
- public boolean switchKeyboardLayout(InputMethodSubtypeHandle imeHandle) {
- final String layout = mKeyboardLayouts.get(imeHandle);
- if (!TextUtils.equals(mCurrentKeyboardLayout, layout)) {
- mCurrentKeyboardLayout = layout;
- return true;
+ public boolean switchKeyboardLayout(int direction) {
+ final int size = mKeyboardLayouts.size();
+ if (size < 2) {
+ return false;
}
- return false;
+ int index = Collections.binarySearch(mKeyboardLayouts, mCurrentKeyboardLayout);
+ assert index >= 0;
+ if (direction > 0) {
+ index = (index + 1) % size;
+ } else {
+ index = (index + size - 1) % size;
+ }
+ mCurrentKeyboardLayout = mKeyboardLayouts.get(index);
+ return true;
}
public boolean removeUninstalledKeyboardLayouts(Set<String> availableKeyboardLayouts) {
boolean changed = false;
- for (int i = mUnassociatedKeyboardLayouts.size(); i-- > 0; ) {
- String keyboardLayout = mUnassociatedKeyboardLayouts.get(i);
+ for (int i = mKeyboardLayouts.size(); i-- > 0; ) {
+ String keyboardLayout = mKeyboardLayouts.get(i);
if (!availableKeyboardLayouts.contains(keyboardLayout)) {
Slog.i(TAG, "Removing uninstalled keyboard layout " + keyboardLayout);
- mUnassociatedKeyboardLayouts.remove(i);
+ mKeyboardLayouts.remove(i);
updateCurrentKeyboardLayoutIfRemoved(keyboardLayout, i);
changed = true;
}
@@ -478,8 +432,13 @@
throw new XmlPullParserException(
"Missing descriptor attribute on keyboard-layout.");
}
-
String current = parser.getAttributeValue(null, "current");
+ if (mKeyboardLayouts.contains(descriptor)) {
+ throw new XmlPullParserException(
+ "Found duplicate keyboard layout.");
+ }
+
+ mKeyboardLayouts.add(descriptor);
if (current != null && current.equals("true")) {
if (mCurrentKeyboardLayout != null) {
throw new XmlPullParserException(
@@ -487,32 +446,6 @@
}
mCurrentKeyboardLayout = descriptor;
}
-
- String inputMethodId = parser.getAttributeValue(null, "input-method-id");
- String inputMethodSubtypeId =
- parser.getAttributeValue(null, "input-method-subtype-id");
- if (inputMethodId == null && inputMethodSubtypeId != null
- || inputMethodId != null && inputMethodSubtypeId == null) {
- throw new XmlPullParserException(
- "Found an incomplete input method description");
- }
-
- if (inputMethodSubtypeId != null) {
- InputMethodSubtypeHandle handle = new InputMethodSubtypeHandle(
- inputMethodId, Integer.parseInt(inputMethodSubtypeId));
- if (mKeyboardLayouts.containsKey(handle)) {
- throw new XmlPullParserException(
- "Found duplicate subtype to keyboard layout mapping: "
- + handle);
- }
- mKeyboardLayouts.put(handle, descriptor);
- } else {
- if (mUnassociatedKeyboardLayouts.contains(descriptor)) {
- throw new XmlPullParserException(
- "Found duplicate unassociated keyboard layout: " + descriptor);
- }
- mUnassociatedKeyboardLayouts.add(descriptor);
- }
} else if (parser.getName().equals("calibration")) {
String format = parser.getAttributeValue(null, "format");
String rotation = parser.getAttributeValue(null, "rotation");
@@ -563,31 +496,19 @@
}
// Maintain invariant that layouts are sorted.
- Collections.sort(mUnassociatedKeyboardLayouts);
+ Collections.sort(mKeyboardLayouts);
// Maintain invariant that there is always a current keyboard layout unless
// there are none installed.
- if (mCurrentKeyboardLayout == null && !mUnassociatedKeyboardLayouts.isEmpty()) {
- mCurrentKeyboardLayout = mUnassociatedKeyboardLayouts.get(0);
+ if (mCurrentKeyboardLayout == null && !mKeyboardLayouts.isEmpty()) {
+ mCurrentKeyboardLayout = mKeyboardLayouts.get(0);
}
}
public void saveToXml(XmlSerializer serializer) throws IOException {
- for (String layout : mUnassociatedKeyboardLayouts) {
+ for (String layout : mKeyboardLayouts) {
serializer.startTag(null, "keyboard-layout");
serializer.attribute(null, "descriptor", layout);
- serializer.endTag(null, "keyboard-layout");
- }
-
- final int N = mKeyboardLayouts.size();
- for (int i = 0; i < N; i++) {
- final InputMethodSubtypeHandle handle = mKeyboardLayouts.keyAt(i);
- final String layout = mKeyboardLayouts.valueAt(i);
- serializer.startTag(null, "keyboard-layout");
- serializer.attribute(null, "descriptor", layout);
- serializer.attribute(null, "input-method-id", handle.getInputMethodId());
- serializer.attribute(null, "input-method-subtype-id",
- Integer.toString(handle.getSubtypeId()));
if (layout.equals(mCurrentKeyboardLayout)) {
serializer.attribute(null, "current", "true");
}
@@ -612,22 +533,6 @@
}
}
- private void dump(final PrintWriter pw, final String prefix) {
- pw.println(prefix + "CurrentKeyboardLayout=" + mCurrentKeyboardLayout);
- pw.println(prefix + "UnassociatedKeyboardLayouts=" + mUnassociatedKeyboardLayouts);
- pw.println(prefix + "TouchCalibration=" + Arrays.toString(mTouchCalibration));
- pw.println(prefix + "Subtype to Layout Mappings:");
- final int N = mKeyboardLayouts.size();
- if (N != 0) {
- for (int i = 0; i < N; i++) {
- pw.println(prefix + " " + mKeyboardLayouts.keyAt(i) + ": "
- + mKeyboardLayouts.valueAt(i));
- }
- } else {
- pw.println(prefix + " <none>");
- }
- }
-
private static String surfaceRotationToString(int surfaceRotation) {
switch (surfaceRotation) {
case Surface.ROTATION_0: return "0";
diff --git a/services/core/java/com/android/server/job/JobSchedulerInternal.java b/services/core/java/com/android/server/job/JobSchedulerInternal.java
index 08607bc..425ec47 100644
--- a/services/core/java/com/android/server/job/JobSchedulerInternal.java
+++ b/services/core/java/com/android/server/job/JobSchedulerInternal.java
@@ -48,6 +48,11 @@
public long baseHeartbeatForApp(String packageName, @UserIdInt int userId, int appBucket);
/**
+ * Tell the scheduler when a JobServiceContext starts running a job in an app
+ */
+ void noteJobStart(String packageName, int userId);
+
+ /**
* Returns a list of pending jobs scheduled by the system service.
*/
List<JobInfo> getSystemScheduledPendingJobs();
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 0e7e540..0b1f9a6 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -88,7 +88,6 @@
import com.android.server.job.JobSchedulerServiceDumpProto.ActiveJob;
import com.android.server.job.JobSchedulerServiceDumpProto.PendingJob;
import com.android.server.job.JobSchedulerServiceDumpProto.RegisteredJob;
-import com.android.server.job.controllers.AppIdleController;
import com.android.server.job.controllers.BackgroundJobsController;
import com.android.server.job.controllers.BatteryController;
import com.android.server.job.controllers.ConnectivityController;
@@ -109,6 +108,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
@@ -239,6 +239,27 @@
long mHeartbeat = 0;
long mLastHeartbeatTime = sElapsedRealtimeClock.millis();
+ /**
+ * Named indices into the STANDBY_BEATS array, for clarity in referring to
+ * specific buckets' bookkeeping.
+ */
+ static final int ACTIVE_INDEX = 0;
+ static final int WORKING_INDEX = 1;
+ static final int FREQUENT_INDEX = 2;
+ static final int RARE_INDEX = 3;
+
+ /**
+ * Bookkeeping about when jobs last run. We keep our own record in heartbeat time,
+ * rather than rely on Usage Stats' timestamps, because heartbeat time can be
+ * manipulated for testing purposes and we need job runnability to track that rather
+ * than real time.
+ *
+ * Outer SparseArray slices by user handle; inner map of package name to heartbeat
+ * is a HashMap<> rather than ArrayMap<> because we expect O(hundreds) of keys
+ * and it will be accessed in a known-hot code path.
+ */
+ final SparseArray<HashMap<String, Long>> mLastJobHeartbeats = new SparseArray<>();
+
static final String HEARTBEAT_TAG = "*job.heartbeat*";
final HeartbeatAlarmListener mHeartbeatAlarm = new HeartbeatAlarmListener();
@@ -533,11 +554,11 @@
DEFAULT_MIN_EXP_BACKOFF_TIME);
STANDBY_HEARTBEAT_TIME = mParser.getDurationMillis(KEY_STANDBY_HEARTBEAT_TIME,
DEFAULT_STANDBY_HEARTBEAT_TIME);
- STANDBY_BEATS[1] = mParser.getInt(KEY_STANDBY_WORKING_BEATS,
+ STANDBY_BEATS[WORKING_INDEX] = mParser.getInt(KEY_STANDBY_WORKING_BEATS,
DEFAULT_STANDBY_WORKING_BEATS);
- STANDBY_BEATS[2] = mParser.getInt(KEY_STANDBY_FREQUENT_BEATS,
+ STANDBY_BEATS[FREQUENT_INDEX] = mParser.getInt(KEY_STANDBY_FREQUENT_BEATS,
DEFAULT_STANDBY_FREQUENT_BEATS);
- STANDBY_BEATS[3] = mParser.getInt(KEY_STANDBY_RARE_BEATS,
+ STANDBY_BEATS[RARE_INDEX] = mParser.getInt(KEY_STANDBY_RARE_BEATS,
DEFAULT_STANDBY_RARE_BEATS);
CONN_CONGESTION_DELAY_FRAC = mParser.getFloat(KEY_CONN_CONGESTION_DELAY_FRAC,
DEFAULT_CONN_CONGESTION_DELAY_FRAC);
@@ -1051,7 +1072,8 @@
final JobStatus job = jsc.getRunningJobLocked();
if (job != null
&& (job.getJob().getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) == 0
- && !job.dozeWhitelisted) {
+ && !job.dozeWhitelisted
+ && !job.uidActive) {
// We will report active if we have a job running and it is not an exception
// due to being in the foreground or whitelisted.
active = true;
@@ -1115,7 +1137,6 @@
mStorageController = new StorageController(this);
mControllers.add(mStorageController);
mControllers.add(new BackgroundJobsController(this));
- mControllers.add(new AppIdleController(this));
mControllers.add(new ContentObserverController(this));
mDeviceIdleJobsController = new DeviceIdleJobsController(this);
mControllers.add(mDeviceIdleJobsController);
@@ -1421,15 +1442,40 @@
periodicToReschedule.getLastFailedRunTime());
}
+ /*
+ * We default to "long enough ago that every bucket's jobs are immediately runnable" to
+ * avoid starvation of apps in uncommon-use buckets that might arise from repeated
+ * reboot behavior.
+ */
long heartbeatWhenJobsLastRun(String packageName, final @UserIdInt int userId) {
- final long heartbeat;
- final long timeSinceLastJob = mUsageStats.getTimeSinceLastJobRun(packageName, userId);
+ // The furthest back in pre-boot time that we need to bother with
+ long heartbeat = -mConstants.STANDBY_BEATS[RARE_INDEX];
+ boolean cacheHit = false;
synchronized (mLock) {
- heartbeat = mHeartbeat - (timeSinceLastJob / mConstants.STANDBY_HEARTBEAT_TIME);
+ HashMap<String, Long> jobPackages = mLastJobHeartbeats.get(userId);
+ if (jobPackages != null) {
+ long cachedValue = jobPackages.getOrDefault(packageName, Long.MAX_VALUE);
+ if (cachedValue < Long.MAX_VALUE) {
+ cacheHit = true;
+ heartbeat = cachedValue;
+ }
+ }
+ if (!cacheHit) {
+ // We haven't seen it yet; ask usage stats about it
+ final long timeSinceJob = mUsageStats.getTimeSinceLastJobRun(packageName, userId);
+ if (timeSinceJob < Long.MAX_VALUE) {
+ // Usage stats knows about it from before, so calculate back from that
+ // and go from there.
+ heartbeat = mHeartbeat - (timeSinceJob / mConstants.STANDBY_HEARTBEAT_TIME);
+ }
+ // If usage stats returned its "not found" MAX_VALUE, we still have the
+ // negative default 'heartbeat' value we established above
+ setLastJobHeartbeatLocked(packageName, userId, heartbeat);
+ }
}
if (DEBUG_STANDBY) {
- Slog.v(TAG, "Last job heartbeat " + heartbeat + " for " + packageName + "/" + userId
- + " delta=" + timeSinceLastJob);
+ Slog.v(TAG, "Last job heartbeat " + heartbeat + " for "
+ + packageName + "/" + userId);
}
return heartbeat;
}
@@ -1438,12 +1484,21 @@
return heartbeatWhenJobsLastRun(job.getSourcePackageName(), job.getSourceUserId());
}
+ void setLastJobHeartbeatLocked(String packageName, int userId, long heartbeat) {
+ HashMap<String, Long> jobPackages = mLastJobHeartbeats.get(userId);
+ if (jobPackages == null) {
+ jobPackages = new HashMap<>();
+ mLastJobHeartbeats.put(userId, jobPackages);
+ }
+ jobPackages.put(packageName, heartbeat);
+ }
+
// JobCompletedListener implementations.
/**
* A job just finished executing. We fetch the
* {@link com.android.server.job.controllers.JobStatus} from the store and depending on
- * whether we want to reschedule we readd it to the controllers.
+ * whether we want to reschedule we re-add it to the controllers.
* @param jobStatus Completed job.
* @param needsReschedule Whether the implementing class should reschedule this job.
*/
@@ -1867,6 +1922,9 @@
// scheduled are sitting there, not ready yet) and very cheap to check (just
// a few conditions on data in JobStatus).
if (!jobReady) {
+ if (job.getSourcePackageName().equals("android.jobscheduler.cts.jobtestapp")) {
+ Slog.v(TAG, " NOT READY: " + job);
+ }
return false;
}
@@ -1905,9 +1963,21 @@
// an appropriate amount of time since the last invocation. During device-
// wide parole, standby bucketing is ignored.
//
- // But if a job has FLAG_EXEMPT_FROM_APP_STANDBY, don't check it.
- if (!mInParole && !job.getJob().isExemptedFromAppStandby()) {
+ // Jobs in 'active' apps are not subject to standby, nor are jobs that are
+ // specifically marked as exempt.
+ if (DEBUG_STANDBY) {
+ Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString()
+ + " parole=" + mInParole + " active=" + job.uidActive
+ + " exempt=" + job.getJob().isExemptedFromAppStandby());
+ }
+ if (!mInParole
+ && !job.uidActive
+ && !job.getJob().isExemptedFromAppStandby()) {
final int bucket = job.getStandbyBucket();
+ if (DEBUG_STANDBY) {
+ Slog.v(TAG, " bucket=" + bucket + " heartbeat=" + mHeartbeat
+ + " next=" + mNextBucketHeartbeat[bucket]);
+ }
if (mHeartbeat < mNextBucketHeartbeat[bucket]) {
// Only skip this job if the app is still waiting for the end of its nominal
// bucket interval. Once it's waited that long, we let it go ahead and clear.
@@ -2194,6 +2264,12 @@
return baseHeartbeat;
}
+ public void noteJobStart(String packageName, int userId) {
+ synchronized (mLock) {
+ setLastJobHeartbeatLocked(packageName, userId, mHeartbeat);
+ }
+ }
+
/**
* Returns a list of all pending jobs. A running job is not considered pending. Periodic
* jobs are always considered pending.
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 1f8cf76..0bb6854 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -268,10 +268,14 @@
} catch (RemoteException e) {
// Whatever.
}
+ final String jobPackage = job.getSourcePackageName();
+ final int jobUserId = job.getSourceUserId();
UsageStatsManagerInternal usageStats =
LocalServices.getService(UsageStatsManagerInternal.class);
- usageStats.setLastJobRunTime(job.getSourcePackageName(), job.getSourceUserId(),
- mExecutionStartTimeElapsed);
+ usageStats.setLastJobRunTime(jobPackage, jobUserId, mExecutionStartTimeElapsed);
+ JobSchedulerInternal jobScheduler =
+ LocalServices.getService(JobSchedulerInternal.class);
+ jobScheduler.noteJobStart(jobPackage, jobUserId);
mAvailable = false;
mStoppedReason = null;
mStoppedTime = 0;
diff --git a/services/core/java/com/android/server/job/controllers/AppIdleController.java b/services/core/java/com/android/server/job/controllers/AppIdleController.java
deleted file mode 100644
index ed29a4c..0000000
--- a/services/core/java/com/android/server/job/controllers/AppIdleController.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.job.controllers;
-
-import android.app.usage.UsageStatsManagerInternal;
-import android.os.UserHandle;
-import android.util.Log;
-import android.util.Slog;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.internal.util.IndentingPrintWriter;
-import com.android.server.LocalServices;
-import com.android.server.job.JobSchedulerService;
-import com.android.server.job.StateControllerProto;
-
-import java.util.function.Consumer;
-import java.util.function.Predicate;
-
-/**
- * Controls when apps are considered idle and if jobs pertaining to those apps should
- * be executed. Apps that haven't been actively launched or accessed from a foreground app
- * for a certain amount of time (maybe hours or days) are considered idle. When the app comes
- * out of idle state, it will be allowed to run scheduled jobs.
- */
-public final class AppIdleController extends StateController {
- private static final String TAG = "JobScheduler.AppIdle";
- private static final boolean DEBUG = JobSchedulerService.DEBUG
- || Log.isLoggable(TAG, Log.DEBUG);
-
- private final UsageStatsManagerInternal mUsageStatsInternal;
- private boolean mInitializedParoleOn;
- boolean mAppIdleParoleOn;
-
- final class GlobalUpdateFunc implements Consumer<JobStatus> {
- boolean mChanged;
-
- @Override
- public void accept(JobStatus jobStatus) {
- String packageName = jobStatus.getSourcePackageName();
- final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName,
- jobStatus.getSourceUid(), jobStatus.getSourceUserId());
- if (DEBUG) {
- Slog.d(TAG, "Setting idle state of " + packageName + " to " + appIdle);
- }
- if (jobStatus.setAppNotIdleConstraintSatisfied(!appIdle)) {
- mChanged = true;
- }
- }
- }
-
- final static class PackageUpdateFunc implements Consumer<JobStatus> {
- final int mUserId;
- final String mPackage;
- final boolean mIdle;
- boolean mChanged;
-
- PackageUpdateFunc(int userId, String pkg, boolean idle) {
- mUserId = userId;
- mPackage = pkg;
- mIdle = idle;
- }
-
- @Override
- public void accept(JobStatus jobStatus) {
- if (jobStatus.getSourcePackageName().equals(mPackage)
- && jobStatus.getSourceUserId() == mUserId) {
- if (jobStatus.setAppNotIdleConstraintSatisfied(!mIdle)) {
- if (DEBUG) {
- Slog.d(TAG, "App Idle state changed, setting idle state of "
- + mPackage + " to " + mIdle);
- }
- mChanged = true;
- }
- }
- }
- }
-
- public AppIdleController(JobSchedulerService service) {
- super(service);
- mUsageStatsInternal = LocalServices.getService(UsageStatsManagerInternal.class);
- mAppIdleParoleOn = true;
- mUsageStatsInternal.addAppIdleStateChangeListener(new AppIdleStateChangeListener());
- }
-
- @Override
- public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
- if (!mInitializedParoleOn) {
- mInitializedParoleOn = true;
- mAppIdleParoleOn = mUsageStatsInternal.isAppIdleParoleOn();
- }
- String packageName = jobStatus.getSourcePackageName();
- final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName,
- jobStatus.getSourceUid(), jobStatus.getSourceUserId());
- if (DEBUG) {
- Slog.d(TAG, "Start tracking, setting idle state of "
- + packageName + " to " + appIdle);
- }
- jobStatus.setAppNotIdleConstraintSatisfied(!appIdle);
- }
-
- @Override
- public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
- boolean forUpdate) {
- }
-
- @Override
- public void dumpControllerStateLocked(final IndentingPrintWriter pw,
- final Predicate<JobStatus> predicate) {
- pw.println("Parole on: " + mAppIdleParoleOn);
- pw.println();
-
- mService.getJobStore().forEachJob(predicate, (jobStatus) -> {
- pw.print("#");
- jobStatus.printUniqueId(pw);
- pw.print(" from ");
- UserHandle.formatUid(pw, jobStatus.getSourceUid());
- pw.print(": ");
- pw.print(jobStatus.getSourcePackageName());
- if ((jobStatus.satisfiedConstraints&JobStatus.CONSTRAINT_APP_NOT_IDLE) != 0) {
- pw.println(" RUNNABLE");
- } else {
- pw.println(" WAITING");
- }
- });
- }
-
- @Override
- public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId,
- Predicate<JobStatus> predicate) {
- final long token = proto.start(fieldId);
- final long mToken = proto.start(StateControllerProto.APP_IDLE);
-
- proto.write(StateControllerProto.AppIdleController.IS_PAROLE_ON, mAppIdleParoleOn);
-
- mService.getJobStore().forEachJob(predicate, (js) -> {
- final long jsToken =
- proto.start(StateControllerProto.AppIdleController.TRACKED_JOBS);
- js.writeToShortProto(proto, StateControllerProto.AppIdleController.TrackedJob.INFO);
- proto.write(StateControllerProto.AppIdleController.TrackedJob.SOURCE_UID,
- js.getSourceUid());
- proto.write(StateControllerProto.AppIdleController.TrackedJob.SOURCE_PACKAGE_NAME,
- js.getSourcePackageName());
- proto.write(
- StateControllerProto.AppIdleController.TrackedJob.ARE_CONSTRAINTS_SATISFIED,
- (js.satisfiedConstraints & JobStatus.CONSTRAINT_APP_NOT_IDLE) != 0);
- proto.end(jsToken);
- });
-
- proto.end(mToken);
- proto.end(token);
- }
-
- void setAppIdleParoleOn(boolean isAppIdleParoleOn) {
- // Flag if any app's idle state has changed
- boolean changed = false;
- synchronized (mLock) {
- if (mAppIdleParoleOn == isAppIdleParoleOn) {
- return;
- }
- mAppIdleParoleOn = isAppIdleParoleOn;
- GlobalUpdateFunc update = new GlobalUpdateFunc();
- mService.getJobStore().forEachJob(update);
- if (update.mChanged) {
- changed = true;
- }
- }
- if (changed) {
- mStateChangedListener.onControllerStateChanged();
- }
- }
-
- private final class AppIdleStateChangeListener
- extends UsageStatsManagerInternal.AppIdleStateChangeListener {
- @Override
- public void onAppIdleStateChanged(String packageName, int userId, boolean idle, int bucket,
- int reason) {
- boolean changed = false;
- synchronized (mLock) {
- if (mAppIdleParoleOn) {
- return;
- }
-
- PackageUpdateFunc update = new PackageUpdateFunc(userId, packageName, idle);
- mService.getJobStore().forEachJob(update);
- if (update.mChanged) {
- changed = true;
- }
- }
- if (changed) {
- mStateChangedListener.onControllerStateChanged();
- }
- }
-
- @Override
- public void onParoleStateChanged(boolean isParoleOn) {
- if (DEBUG) {
- Slog.d(TAG, "Parole on: " + isParoleOn);
- }
- setAppIdleParoleOn(isParoleOn);
- }
- }
-}
diff --git a/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java b/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
index 36e75115..b698e5b 100644
--- a/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
+++ b/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
@@ -28,17 +28,32 @@
import com.android.server.AppStateTracker.Listener;
import com.android.server.LocalServices;
import com.android.server.job.JobSchedulerService;
+import com.android.server.job.JobStore;
import com.android.server.job.StateControllerProto;
import com.android.server.job.StateControllerProto.BackgroundJobsController.TrackedJob;
import java.util.function.Consumer;
import java.util.function.Predicate;
+/**
+ * Tracks the following pieces of JobStatus state:
+ *
+ * - the CONSTRAINT_BACKGROUND_NOT_RESTRICTED general constraint bit, which
+ * is used to selectively permit battery-saver exempted jobs to run; and
+ *
+ * - the uid-active boolean state expressed by the AppStateTracker. Jobs in 'active'
+ * uids are inherently eligible to run jobs regardless of the uid's standby bucket.
+ */
public final class BackgroundJobsController extends StateController {
private static final String TAG = "JobScheduler.Background";
private static final boolean DEBUG = JobSchedulerService.DEBUG
|| Log.isLoggable(TAG, Log.DEBUG);
+ // Tri-state about possible "is this uid 'active'?" knowledge
+ static final int UNKNOWN = 0;
+ static final int KNOWN_ACTIVE = 1;
+ static final int KNOWN_INACTIVE = 2;
+
private final AppStateTracker mAppStateTracker;
public BackgroundJobsController(JobSchedulerService service) {
@@ -51,7 +66,7 @@
@Override
public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
- updateSingleJobRestrictionLocked(jobStatus);
+ updateSingleJobRestrictionLocked(jobStatus, UNKNOWN);
}
@Override
@@ -137,23 +152,24 @@
}
private void updateAllJobRestrictionsLocked() {
- updateJobRestrictionsLocked(/*filterUid=*/ -1);
+ updateJobRestrictionsLocked(/*filterUid=*/ -1, UNKNOWN);
}
- private void updateJobRestrictionsForUidLocked(int uid) {
-
- // TODO Use forEachJobForSourceUid() once we have it.
-
- updateJobRestrictionsLocked(/*filterUid=*/ uid);
+ private void updateJobRestrictionsForUidLocked(int uid, boolean isActive) {
+ updateJobRestrictionsLocked(uid, (isActive) ? KNOWN_ACTIVE : KNOWN_INACTIVE);
}
- private void updateJobRestrictionsLocked(int filterUid) {
- final UpdateJobFunctor updateTrackedJobs =
- new UpdateJobFunctor(filterUid);
+ private void updateJobRestrictionsLocked(int filterUid, int newActiveState) {
+ final UpdateJobFunctor updateTrackedJobs = new UpdateJobFunctor(newActiveState);
final long start = DEBUG ? SystemClock.elapsedRealtimeNanos() : 0;
- mService.getJobStore().forEachJob(updateTrackedJobs);
+ final JobStore store = mService.getJobStore();
+ if (filterUid > 0) {
+ store.forEachJobForSourceUid(filterUid, updateTrackedJobs);
+ } else {
+ store.forEachJob(updateTrackedJobs);
+ }
final long time = DEBUG ? (SystemClock.elapsedRealtimeNanos() - start) : 0;
if (DEBUG) {
@@ -170,7 +186,7 @@
}
}
- boolean updateSingleJobRestrictionLocked(JobStatus jobStatus) {
+ boolean updateSingleJobRestrictionLocked(JobStatus jobStatus, int activeState) {
final int uid = jobStatus.getSourceUid();
final String packageName = jobStatus.getSourcePackageName();
@@ -179,28 +195,32 @@
(jobStatus.getInternalFlags() & JobStatus.INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION)
!= 0);
- return jobStatus.setBackgroundNotRestrictedConstraintSatisfied(canRun);
+ final boolean isActive;
+ if (activeState == UNKNOWN) {
+ isActive = mAppStateTracker.isUidActive(uid);
+ } else {
+ isActive = (activeState == KNOWN_ACTIVE);
+ }
+ boolean didChange = jobStatus.setBackgroundNotRestrictedConstraintSatisfied(canRun);
+ didChange |= jobStatus.setUidActive(isActive);
+ return didChange;
}
private final class UpdateJobFunctor implements Consumer<JobStatus> {
- private final int mFilterUid;
-
+ final int activeState;
boolean mChanged = false;
int mTotalCount = 0;
int mCheckedCount = 0;
- UpdateJobFunctor(int filterUid) {
- mFilterUid = filterUid;
+ public UpdateJobFunctor(int newActiveState) {
+ activeState = newActiveState;
}
@Override
public void accept(JobStatus jobStatus) {
mTotalCount++;
- if ((mFilterUid > 0) && (mFilterUid != jobStatus.getSourceUid())) {
- return;
- }
mCheckedCount++;
- if (updateSingleJobRestrictionLocked(jobStatus)) {
+ if (updateSingleJobRestrictionLocked(jobStatus, activeState)) {
mChanged = true;
}
}
@@ -215,16 +235,16 @@
}
@Override
- public void updateJobsForUid(int uid) {
+ public void updateJobsForUid(int uid, boolean isActive) {
synchronized (mLock) {
- updateJobRestrictionsForUidLocked(uid);
+ updateJobRestrictionsForUidLocked(uid, isActive);
}
}
@Override
- public void updateJobsForUidPackage(int uid, String packageName) {
+ public void updateJobsForUidPackage(int uid, String packageName, boolean isActive) {
synchronized (mLock) {
- updateJobRestrictionsForUidLocked(uid);
+ updateJobRestrictionsForUidLocked(uid, isActive);
}
}
};
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 5616197..578a32c 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -73,7 +73,6 @@
static final int CONSTRAINT_TIMING_DELAY = 1<<31;
static final int CONSTRAINT_DEADLINE = 1<<30;
static final int CONSTRAINT_CONNECTIVITY = 1<<28;
- static final int CONSTRAINT_APP_NOT_IDLE = 1<<27;
static final int CONSTRAINT_CONTENT_TRIGGER = 1<<26;
static final int CONSTRAINT_DEVICE_NOT_DOZING = 1<<25;
static final int CONSTRAINT_BACKGROUND_NOT_RESTRICTED = 1<<22;
@@ -153,6 +152,9 @@
// Set to true if doze constraint was satisfied due to app being whitelisted.
public boolean dozeWhitelisted;
+ // Set to true when the app is "active" per AppStateTracker
+ public boolean uidActive;
+
/**
* Flag for {@link #trackingControllers}: the battery controller is currently tracking this job.
*/
@@ -838,10 +840,6 @@
return setConstraintSatisfied(CONSTRAINT_CONNECTIVITY, state);
}
- boolean setAppNotIdleConstraintSatisfied(boolean state) {
- return setConstraintSatisfied(CONSTRAINT_APP_NOT_IDLE, state);
- }
-
boolean setContentTriggerConstraintSatisfied(boolean state) {
return setConstraintSatisfied(CONSTRAINT_CONTENT_TRIGGER, state);
}
@@ -855,6 +853,14 @@
return setConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED, state);
}
+ boolean setUidActive(final boolean newActiveState) {
+ if (newActiveState != uidActive) {
+ uidActive = newActiveState;
+ return true;
+ }
+ return false; /* unchanged */
+ }
+
boolean setConstraintSatisfied(int constraint, boolean state) {
boolean old = (satisfiedConstraints&constraint) != 0;
if (old == state) {
@@ -904,13 +910,11 @@
// NotRestrictedInBackground implicit constraint must be satisfied
final boolean deadlineSatisfied = (!job.isPeriodic() && hasDeadlineConstraint()
&& (satisfiedConstraints & CONSTRAINT_DEADLINE) != 0);
- final boolean notIdle = (satisfiedConstraints & CONSTRAINT_APP_NOT_IDLE) != 0;
final boolean notDozing = (satisfiedConstraints & CONSTRAINT_DEVICE_NOT_DOZING) != 0
|| (job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
final boolean notRestrictedInBg =
(satisfiedConstraints & CONSTRAINT_BACKGROUND_NOT_RESTRICTED) != 0;
- return (isConstraintsSatisfied() || deadlineSatisfied) && notIdle && notDozing
- && notRestrictedInBg;
+ return (isConstraintsSatisfied() || deadlineSatisfied) && notDozing && notRestrictedInBg;
}
static final int CONSTRAINTS_OF_INTEREST = CONSTRAINT_CHARGING | CONSTRAINT_BATTERY_NOT_LOW
@@ -990,9 +994,6 @@
if (job.isPersisted()) {
sb.append(" PERSISTED");
}
- if ((satisfiedConstraints&CONSTRAINT_APP_NOT_IDLE) == 0) {
- sb.append(" WAIT:APP_NOT_IDLE");
- }
if ((satisfiedConstraints&CONSTRAINT_DEVICE_NOT_DOZING) == 0) {
sb.append(" WAIT:DEV_NOT_DOZING");
}
@@ -1091,9 +1092,6 @@
if ((constraints&CONSTRAINT_CONNECTIVITY) != 0) {
pw.print(" CONNECTIVITY");
}
- if ((constraints&CONSTRAINT_APP_NOT_IDLE) != 0) {
- pw.print(" APP_NOT_IDLE");
- }
if ((constraints&CONSTRAINT_CONTENT_TRIGGER) != 0) {
pw.print(" CONTENT_TRIGGER");
}
@@ -1133,9 +1131,6 @@
if ((constraints & CONSTRAINT_CONNECTIVITY) != 0) {
proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_CONNECTIVITY);
}
- if ((constraints & CONSTRAINT_APP_NOT_IDLE) != 0) {
- proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_APP_NOT_IDLE);
- }
if ((constraints & CONSTRAINT_CONTENT_TRIGGER) != 0) {
proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_CONTENT_TRIGGER);
}
@@ -1307,6 +1302,9 @@
if (dozeWhitelisted) {
pw.print(prefix); pw.println("Doze whitelisted: true");
}
+ if (uidActive) {
+ pw.print(prefix); pw.println("Uid: active");
+ }
}
if (trackingControllers != 0) {
pw.print(prefix); pw.print("Tracking:");
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 468ec59..74ebf3e4 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -102,6 +102,7 @@
import com.android.internal.widget.ICheckCredentialProgressCallback;
import com.android.internal.widget.ILockSettings;
import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockSettingsInternal;
import com.android.internal.widget.VerifyCredentialResponse;
import com.android.server.LocalServices;
import com.android.server.SystemService;
@@ -436,6 +437,8 @@
mStrongAuthTracker.register(mStrongAuth);
mSpManager = injector.getSyntheticPasswordManager(mStorage);
+
+ LocalServices.addService(LockSettingsInternal.class, new LocalService());
}
/**
@@ -1041,14 +1044,10 @@
private boolean isUserSecure(int userId) {
synchronized (mSpManager) {
- try {
- if (isSyntheticPasswordBasedCredentialLocked(userId)) {
- long handle = getSyntheticPasswordHandleLocked(userId);
- return mSpManager.getCredentialType(handle, userId) !=
- LockPatternUtils.CREDENTIAL_TYPE_NONE;
- }
- } catch (RemoteException e) {
- // fall through
+ if (isSyntheticPasswordBasedCredentialLocked(userId)) {
+ long handle = getSyntheticPasswordHandleLocked(userId);
+ return mSpManager.getCredentialType(handle, userId) !=
+ LockPatternUtils.CREDENTIAL_TYPE_NONE;
}
}
return mStorage.hasCredential(userId);
@@ -2305,7 +2304,7 @@
SyntheticPasswordManager.DEFAULT_HANDLE, userId);
}
- private boolean isSyntheticPasswordBasedCredentialLocked(int userId) throws RemoteException {
+ private boolean isSyntheticPasswordBasedCredentialLocked(int userId) {
if (userId == USER_FRP) {
final int type = mStorage.readPersistentDataBlock().type;
return type == PersistentData.TYPE_SP || type == PersistentData.TYPE_SP_WEAVER;
@@ -2318,7 +2317,7 @@
}
@VisibleForTesting
- protected boolean shouldMigrateToSyntheticPasswordLocked(int userId) throws RemoteException {
+ protected boolean shouldMigrateToSyntheticPasswordLocked(int userId) {
long handle = getSyntheticPasswordHandleLocked(userId);
// This is a global setting
long enabled = getLong(SYNTHETIC_PASSWORD_ENABLED_KEY,
@@ -2326,7 +2325,7 @@
return enabled != 0 && handle == SyntheticPasswordManager.DEFAULT_HANDLE;
}
- private void enableSyntheticPasswordLocked() throws RemoteException {
+ private void enableSyntheticPasswordLocked() {
setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1, UserHandle.USER_SYSTEM);
}
@@ -2525,9 +2524,7 @@
mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, userId);
}
- @Override
- public long addEscrowToken(byte[] token, int userId) throws RemoteException {
- ensureCallerSystemUid();
+ private long addEscrowToken(byte[] token, int userId) throws RemoteException {
if (DEBUG) Slog.d(TAG, "addEscrowToken: user=" + userId);
synchronized (mSpManager) {
enableSyntheticPasswordLocked();
@@ -2559,7 +2556,7 @@
}
}
- private void activateEscrowTokens(AuthenticationToken auth, int userId) throws RemoteException {
+ private void activateEscrowTokens(AuthenticationToken auth, int userId) {
if (DEBUG) Slog.d(TAG, "activateEscrowTokens: user=" + userId);
synchronized (mSpManager) {
disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
@@ -2570,17 +2567,13 @@
}
}
- @Override
- public boolean isEscrowTokenActive(long handle, int userId) throws RemoteException {
- ensureCallerSystemUid();
+ private boolean isEscrowTokenActive(long handle, int userId) {
synchronized (mSpManager) {
return mSpManager.existsHandle(handle, userId);
}
}
- @Override
- public boolean removeEscrowToken(long handle, int userId) throws RemoteException {
- ensureCallerSystemUid();
+ private boolean removeEscrowToken(long handle, int userId) {
synchronized (mSpManager) {
if (handle == getSyntheticPasswordHandleLocked(userId)) {
Slog.w(TAG, "Cannot remove password handle");
@@ -2598,10 +2591,8 @@
}
}
- @Override
- public boolean setLockCredentialWithToken(String credential, int type, long tokenHandle,
+ private boolean setLockCredentialWithToken(String credential, int type, long tokenHandle,
byte[] token, int requestedQuality, int userId) throws RemoteException {
- ensureCallerSystemUid();
boolean result;
synchronized (mSpManager) {
if (!mSpManager.hasEscrowData(userId)) {
@@ -2650,10 +2641,8 @@
return true;
}
- @Override
- public void unlockUserWithToken(long tokenHandle, byte[] token, int userId)
+ private boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId)
throws RemoteException {
- ensureCallerSystemUid();
AuthenticationResult authResult;
synchronized (mSpManager) {
if (!mSpManager.hasEscrowData(userId)) {
@@ -2663,11 +2652,12 @@
tokenHandle, token, userId);
if (authResult.authToken == null) {
Slog.w(TAG, "Invalid escrow token supplied");
- return;
+ return false;
}
}
unlockUser(userId, null, authResult.authToken.deriveDiskEncryptionKey());
onAuthTokenKnownForUser(userId, authResult.authToken);
+ return true;
}
@Override
@@ -2732,20 +2722,11 @@
if (isSyntheticPasswordBasedCredentialLocked(userId)) {
mSpManager.destroyEscrowData(userId);
}
- } catch (RemoteException e) {
- Slog.e(TAG, "disableEscrowTokenOnNonManagedDevices", e);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
- private void ensureCallerSystemUid() throws SecurityException {
- final int callingUid = mInjector.binderGetCallingUid();
- if (callingUid != Process.SYSTEM_UID) {
- throw new SecurityException("Only system can call this API.");
- }
- }
-
private class DeviceProvisionedObserver extends ContentObserver {
private final Uri mDeviceProvisionedUri = Settings.Global.getUriFor(
Settings.Global.DEVICE_PROVISIONED);
@@ -2834,4 +2815,46 @@
Settings.Global.DEVICE_PROVISIONED, 0) != 0;
}
}
+
+ private final class LocalService extends LockSettingsInternal {
+
+ @Override
+ public long addEscrowToken(byte[] token, int userId) {
+ try {
+ return LockSettingsService.this.addEscrowToken(token, userId);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ @Override
+ public boolean removeEscrowToken(long handle, int userId) {
+ return LockSettingsService.this.removeEscrowToken(handle, userId);
+ }
+
+ @Override
+ public boolean isEscrowTokenActive(long handle, int userId) {
+ return LockSettingsService.this.isEscrowTokenActive(handle, userId);
+ }
+
+ @Override
+ public boolean setLockCredentialWithToken(String credential, int type, long tokenHandle,
+ byte[] token, int requestedQuality, int userId) {
+ try {
+ return LockSettingsService.this.setLockCredentialWithToken(credential, type,
+ tokenHandle, token, requestedQuality, userId);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ @Override
+ public boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId) {
+ try {
+ return LockSettingsService.this.unlockUserWithToken(tokenHandle, token, userId);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java b/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java
index e5fc6e5..6907c58 100644
--- a/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java
+++ b/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java
@@ -39,6 +39,7 @@
import com.android.internal.net.INetworkWatchlistManager;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
+import com.android.server.net.BaseNetdEventCallback;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -139,7 +140,7 @@
ServiceManager.getService(IpConnectivityLog.SERVICE_NAME));
}
- private final INetdEventCallback mNetdEventCallback = new INetdEventCallback.Stub() {
+ private final INetdEventCallback mNetdEventCallback = new BaseNetdEventCallback() {
@Override
public void onDnsEvent(String hostname, String[] ipAddresses, int ipAddressesCount,
long timestamp, int uid) {
diff --git a/services/core/java/com/android/server/notification/BadgeExtractor.java b/services/core/java/com/android/server/notification/BadgeExtractor.java
index d8a30ae..d91d541 100644
--- a/services/core/java/com/android/server/notification/BadgeExtractor.java
+++ b/services/core/java/com/android/server/notification/BadgeExtractor.java
@@ -15,6 +15,8 @@
*/
package com.android.server.notification;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
+
import android.content.Context;
import android.util.Slog;
@@ -54,6 +56,11 @@
}
}
+ if (record.isIntercepted()
+ && (record.getSuppressedVisualEffects() & SUPPRESSED_EFFECT_BADGE) != 0) {
+ record.setShowBadge(false);
+ }
+
return null;
}
@@ -64,6 +71,5 @@
@Override
public void setZenHelper(ZenModeHelper helper) {
-
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index cd387b0..b9fb2e0 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -22,6 +22,16 @@
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECTS_UNSET;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
import static android.content.pm.PackageManager.FEATURE_TELEVISION;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -60,8 +70,6 @@
import static android.service.notification.NotificationListenerService.REASON_TIMEOUT;
import static android.service.notification.NotificationListenerService.REASON_UNAUTOBUNDLED;
import static android.service.notification.NotificationListenerService.REASON_USER_STOPPED;
-import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_OFF;
-import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_ON;
import static android.service.notification.NotificationListenerService.TRIM_FULL;
import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -1342,6 +1350,7 @@
@Override
void onPolicyChanged() {
sendRegisteredOnlyBroadcast(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED);
+ mRankingHandler.requestSort();
}
});
mRankingHelper = new RankingHelper(getContext(),
@@ -1773,25 +1782,105 @@
* Report to usage stats that the notification was seen.
* @param r notification record
*/
+ @GuardedBy("mNotificationLock")
protected void reportSeen(NotificationRecord r) {
- final int userId = r.sbn.getUserId();
mAppUsageStats.reportEvent(r.sbn.getPackageName(),
- userId == UserHandle.USER_ALL ? USER_SYSTEM
- : userId,
+ getRealUserId(r.sbn.getUserId()),
UsageEvents.Event.NOTIFICATION_SEEN);
}
+ protected int calculateSuppressedVisualEffects(Policy incomingPolicy, Policy currPolicy,
+ int targetSdkVersion) {
+ if (incomingPolicy.suppressedVisualEffects == SUPPRESSED_EFFECTS_UNSET) {
+ return incomingPolicy.suppressedVisualEffects;
+ }
+ final int[] effectsIntroducedInP = {
+ SUPPRESSED_EFFECT_FULL_SCREEN_INTENT,
+ SUPPRESSED_EFFECT_LIGHTS,
+ SUPPRESSED_EFFECT_PEEK,
+ SUPPRESSED_EFFECT_STATUS_BAR,
+ SUPPRESSED_EFFECT_BADGE,
+ SUPPRESSED_EFFECT_AMBIENT,
+ SUPPRESSED_EFFECT_NOTIFICATION_LIST
+ };
+
+ int newSuppressedVisualEffects = incomingPolicy.suppressedVisualEffects;
+ if (targetSdkVersion <= Build.VERSION_CODES.O_MR1) {
+ // unset higher order bits introduced in P, maintain the user's higher order bits
+ for (int i = 0; i < effectsIntroducedInP.length ; i++) {
+ newSuppressedVisualEffects &= ~effectsIntroducedInP[i];
+ newSuppressedVisualEffects |=
+ (currPolicy.suppressedVisualEffects & effectsIntroducedInP[i]);
+ }
+ // set higher order bits according to lower order bits
+ if ((newSuppressedVisualEffects & SUPPRESSED_EFFECT_SCREEN_OFF) != 0) {
+ newSuppressedVisualEffects |= SUPPRESSED_EFFECT_LIGHTS;
+ newSuppressedVisualEffects |= SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
+ newSuppressedVisualEffects |= SUPPRESSED_EFFECT_AMBIENT;
+ }
+ if ((newSuppressedVisualEffects & SUPPRESSED_EFFECT_SCREEN_ON) != 0) {
+ newSuppressedVisualEffects |= SUPPRESSED_EFFECT_PEEK;
+ }
+ } else {
+ boolean hasNewEffects = (newSuppressedVisualEffects
+ - SUPPRESSED_EFFECT_SCREEN_ON - SUPPRESSED_EFFECT_SCREEN_OFF) > 0;
+ // if any of the new effects introduced in P are set
+ if (hasNewEffects) {
+ // clear out the deprecated effects
+ newSuppressedVisualEffects &= ~ (SUPPRESSED_EFFECT_SCREEN_ON
+ | SUPPRESSED_EFFECT_SCREEN_OFF);
+
+ // set the deprecated effects according to the new more specific effects
+ if ((newSuppressedVisualEffects & Policy.SUPPRESSED_EFFECT_PEEK) != 0) {
+ newSuppressedVisualEffects |= SUPPRESSED_EFFECT_SCREEN_ON;
+ }
+ if ((newSuppressedVisualEffects & Policy.SUPPRESSED_EFFECT_LIGHTS) != 0
+ && (newSuppressedVisualEffects
+ & Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT) != 0
+ && (newSuppressedVisualEffects
+ & Policy.SUPPRESSED_EFFECT_AMBIENT) != 0) {
+ newSuppressedVisualEffects |= SUPPRESSED_EFFECT_SCREEN_OFF;
+ }
+ } else {
+ // set higher order bits according to lower order bits
+ if ((newSuppressedVisualEffects & SUPPRESSED_EFFECT_SCREEN_OFF) != 0) {
+ newSuppressedVisualEffects |= SUPPRESSED_EFFECT_LIGHTS;
+ newSuppressedVisualEffects |= SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
+ newSuppressedVisualEffects |= SUPPRESSED_EFFECT_AMBIENT;
+ }
+ if ((newSuppressedVisualEffects & SUPPRESSED_EFFECT_SCREEN_ON) != 0) {
+ newSuppressedVisualEffects |= SUPPRESSED_EFFECT_PEEK;
+ }
+ }
+ }
+
+ return newSuppressedVisualEffects;
+ }
+
+ // TODO: log visual differences, not just audible ones
+ @GuardedBy("mNotificationLock")
+ protected void maybeRecordInterruptionLocked(NotificationRecord r) {
+ if (r.isInterruptive()) {
+ mAppUsageStats.reportInterruptiveNotification(r.sbn.getPackageName(),
+ r.getChannel().getId(),
+ getRealUserId(r.sbn.getUserId()));
+ }
+ }
+
/**
* Report to usage stats that the notification was clicked.
* @param r notification record
*/
protected void reportUserInteraction(NotificationRecord r) {
- final int userId = r.sbn.getUserId();
mAppUsageStats.reportEvent(r.sbn.getPackageName(),
- userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId,
+ getRealUserId(r.sbn.getUserId()),
UsageEvents.Event.USER_INTERACTION);
}
+ private int getRealUserId(int userId) {
+ return userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId;
+ }
+
@VisibleForTesting
NotificationManagerInternal getInternalService() {
return mInternalService;
@@ -3063,10 +3152,9 @@
try {
final ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(pkg,
0, UserHandle.getUserId(MY_UID));
+ Policy currPolicy = mZenModeHelper.getNotificationPolicy();
if (applicationInfo.targetSdkVersion <= Build.VERSION_CODES.O_MR1) {
- Policy currPolicy = mZenModeHelper.getNotificationPolicy();
-
int priorityCategories = policy.priorityCategories;
// ignore alarm and media values from new policy
priorityCategories &= ~Policy.PRIORITY_CATEGORY_ALARMS;
@@ -3084,11 +3172,13 @@
policy.priorityCallSenders, policy.priorityMessageSenders,
policy.suppressedVisualEffects);
}
+ int newVisualEffects = calculateSuppressedVisualEffects(
+ policy, currPolicy, applicationInfo.targetSdkVersion);
+ policy = new Policy(policy.priorityCategories,
+ policy.priorityCallSenders, policy.priorityMessageSenders,
+ newVisualEffects);
- Slog.i(TAG, "setNotificationPolicy pkg=" + pkg
- + " targetSdk=" + applicationInfo.targetSdkVersion
- + " policy="
- + Policy.priorityCategoriesToString(policy.priorityCategories));
+ ZenLog.traceSetNotificationPolicy(pkg, applicationInfo.targetSdkVersion, policy);
mZenModeHelper.setNotificationPolicy(policy);
} catch (RemoteException e) {
} finally {
@@ -4267,6 +4357,7 @@
}
buzzBeepBlinkLocked(r);
+ maybeRecordInterruptionLocked(r);
} finally {
int N = mEnqueuedNotifications.size();
for (int i = 0; i < N; i++) {
@@ -4465,8 +4556,7 @@
// release the light
boolean wasShowLights = mLights.remove(key);
if (record.getLight() != null && aboveThreshold
- && ((record.getSuppressedVisualEffects()
- & NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_OFF) == 0)) {
+ && ((record.getSuppressedVisualEffects() & SUPPRESSED_EFFECT_LIGHTS) == 0)) {
mLights.add(key);
updateLightsLocked();
if (mUseAttentionLight) {
@@ -4477,6 +4567,7 @@
updateLightsLocked();
}
if (buzz || beep || blink) {
+ record.setInterruptive(true);
MetricsLogger.action(record.getLogMaker()
.setCategory(MetricsEvent.NOTIFICATION_ALERT)
.setType(MetricsEvent.TYPE_OPEN)
@@ -4864,11 +4955,8 @@
private void applyZenModeLocked(NotificationRecord record) {
record.setIntercepted(mZenModeHelper.shouldIntercept(record));
if (record.isIntercepted()) {
- int suppressed = (mZenModeHelper.shouldSuppressWhenScreenOff()
- ? SUPPRESSED_EFFECT_SCREEN_OFF : 0)
- | (mZenModeHelper.shouldSuppressWhenScreenOn()
- ? SUPPRESSED_EFFECT_SCREEN_ON : 0);
- record.setSuppressedVisualEffects(suppressed);
+ record.setSuppressedVisualEffects(
+ mZenModeHelper.getNotificationPolicy().suppressedVisualEffects);
} else {
record.setSuppressedVisualEffects(0);
}
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 8d2f0dd..f1908bf 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -145,6 +145,7 @@
private final List<Adjustment> mAdjustments;
private final NotificationStats mStats;
private int mUserSentiment;
+ private boolean mIsInterruptive;
@VisibleForTesting
public NotificationRecord(Context context, StatusBarNotification sbn,
@@ -519,6 +520,7 @@
pw.println(prefix + "mLight= " + mLight);
pw.println(prefix + "mShowBadge=" + mShowBadge);
pw.println(prefix + "mColorized=" + notification.isColorized());
+ pw.println(prefix + "mIsInterruptive=" + mIsInterruptive);
pw.println(prefix + "effectiveNotificationChannel=" + getChannel());
if (getPeopleOverride() != null) {
pw.println(prefix + "overridePeople= " + TextUtils.join(",", getPeopleOverride()));
@@ -712,13 +714,8 @@
return Objects.equals(getNotification().category, category);
}
- public boolean isAudioStream(int stream) {
- return getNotification().audioStreamType == stream;
- }
-
public boolean isAudioAttributesUsage(int usage) {
- final AudioAttributes attributes = getNotification().audioAttributes;
- return attributes != null && attributes.getUsage() == usage;
+ return mAttributes != null && mAttributes.getUsage() == usage;
}
/**
@@ -893,6 +890,14 @@
return mPeopleOverride;
}
+ public void setInterruptive(boolean interruptive) {
+ mIsInterruptive = interruptive;
+ }
+
+ public boolean isInterruptive() {
+ return mIsInterruptive;
+ }
+
protected void setPeopleOverride(ArrayList<String> people) {
mPeopleOverride = people;
}
diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java
index f7efff0f..6760875 100644
--- a/services/core/java/com/android/server/notification/ZenLog.java
+++ b/services/core/java/com/android/server/notification/ZenLog.java
@@ -16,6 +16,7 @@
package com.android.server.notification;
+import android.app.NotificationManager;
import android.content.ComponentName;
import android.media.AudioManager;
import android.net.Uri;
@@ -60,6 +61,7 @@
private static final int TYPE_DISABLE_EFFECTS = 13;
private static final int TYPE_SUPPRESSOR_CHANGED = 14;
private static final int TYPE_LISTENER_HINTS_CHANGED = 15;
+ private static final int TYPE_SET_NOTIFICATION_POLICY = 16;
private static int sNext;
private static int sSize;
@@ -108,6 +110,12 @@
append(TYPE_EXIT_CONDITION, c + "," + componentToString(component) + "," + reason);
}
+ public static void traceSetNotificationPolicy(String pkg, int targetSdk,
+ NotificationManager.Policy policy) {
+ append(TYPE_SET_NOTIFICATION_POLICY, "pkg=" + pkg + " targetSdk=" + targetSdk
+ + " NotificationPolicy=" + policy.toString());
+ }
+
public static void traceSubscribe(Uri uri, IConditionProvider provider, RemoteException e) {
append(TYPE_SUBSCRIBE, uri + "," + subscribeResult(provider, e));
}
@@ -160,6 +168,7 @@
case TYPE_DISABLE_EFFECTS: return "disable_effects";
case TYPE_SUPPRESSOR_CHANGED: return "suppressor_changed";
case TYPE_LISTENER_HINTS_CHANGED: return "listener_hints_changed";
+ case TYPE_SET_NOTIFICATION_POLICY: return "set_notification_policy";
default: return "unknown";
}
}
diff --git a/services/core/java/com/android/server/notification/ZenModeExtractor.java b/services/core/java/com/android/server/notification/ZenModeExtractor.java
index 74f9806..a0aa1c3 100644
--- a/services/core/java/com/android/server/notification/ZenModeExtractor.java
+++ b/services/core/java/com/android/server/notification/ZenModeExtractor.java
@@ -16,8 +16,8 @@
package com.android.server.notification;
-import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_OFF;
-import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_ON;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
import android.content.Context;
import android.util.Log;
@@ -49,11 +49,8 @@
record.setIntercepted(mZenModeHelper.shouldIntercept(record));
if (record.isIntercepted()) {
- int suppressed = (mZenModeHelper.shouldSuppressWhenScreenOff()
- ? SUPPRESSED_EFFECT_SCREEN_OFF : 0)
- | (mZenModeHelper.shouldSuppressWhenScreenOn()
- ? SUPPRESSED_EFFECT_SCREEN_ON : 0);
- record.setSuppressedVisualEffects(suppressed);
+ record.setSuppressedVisualEffects(
+ mZenModeHelper.getNotificationPolicy().suppressedVisualEffects);
} else {
record.setSuppressedVisualEffects(0);
}
diff --git a/services/core/java/com/android/server/notification/ZenModeFiltering.java b/services/core/java/com/android/server/notification/ZenModeFiltering.java
index a0003a5..71cee05 100644
--- a/services/core/java/com/android/server/notification/ZenModeFiltering.java
+++ b/services/core/java/com/android/server/notification/ZenModeFiltering.java
@@ -16,7 +16,10 @@
package com.android.server.notification;
+import static android.provider.Settings.Global.ZEN_MODE_OFF;
+
import android.app.Notification;
+import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
import android.media.AudioAttributes;
@@ -30,6 +33,9 @@
import android.util.ArrayMap;
import android.util.Slog;
+import com.android.internal.messages.nano.SystemMessageProto;
+import com.android.internal.util.NotificationMessagingUtil;
+
import java.io.PrintWriter;
import java.util.Date;
import java.util.Objects;
@@ -43,9 +49,16 @@
private final Context mContext;
private ComponentName mDefaultPhoneApp;
+ private final NotificationMessagingUtil mMessagingUtil;
public ZenModeFiltering(Context context) {
mContext = context;
+ mMessagingUtil = new NotificationMessagingUtil(mContext);
+ }
+
+ public ZenModeFiltering(Context context, NotificationMessagingUtil messagingUtil) {
+ mContext = context;
+ mMessagingUtil = messagingUtil;
}
public void dump(PrintWriter pw, String prefix) {
@@ -104,6 +117,16 @@
}
public boolean shouldIntercept(int zen, ZenModeConfig config, NotificationRecord record) {
+ if (zen == ZEN_MODE_OFF) {
+ return false;
+ }
+ // Make an exception to policy for the notification saying that policy has changed
+ if (NotificationManager.Policy.areAllVisualEffectsSuppressed(config.suppressedVisualEffects)
+ && "android".equals(record.sbn.getPackageName())
+ && SystemMessageProto.SystemMessage.NOTE_ZEN_UPGRADE == record.sbn.getId()) {
+ ZenLog.traceNotIntercepted(record, "systemDndChangedNotification");
+ return false;
+ }
switch (zen) {
case Global.ZEN_MODE_NO_INTERRUPTIONS:
// #notevenalarms
@@ -192,9 +215,8 @@
return false;
}
- private static boolean isAlarm(NotificationRecord record) {
+ protected static boolean isAlarm(NotificationRecord record) {
return record.isCategory(Notification.CATEGORY_ALARM)
- || record.isAudioStream(AudioManager.STREAM_ALARM)
|| record.isAudioAttributesUsage(AudioAttributes.USAGE_ALARM);
}
@@ -234,17 +256,8 @@
&& pkg.equals(mDefaultPhoneApp.getPackageName());
}
- @SuppressWarnings("deprecation")
- private boolean isDefaultMessagingApp(NotificationRecord record) {
- final int userId = record.getUserId();
- if (userId == UserHandle.USER_NULL || userId == UserHandle.USER_ALL) return false;
- final String defaultApp = Secure.getStringForUser(mContext.getContentResolver(),
- Secure.SMS_DEFAULT_APPLICATION, userId);
- return Objects.equals(defaultApp, record.sbn.getPackageName());
- }
-
- private boolean isMessage(NotificationRecord record) {
- return record.isCategory(Notification.CATEGORY_MESSAGE) || isDefaultMessagingApp(record);
+ protected boolean isMessage(NotificationRecord record) {
+ return mMessagingUtil.isMessaging(record.sbn);
}
private static boolean audienceMatches(int source, float contactAffinity) {
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 28d692a..141b47d 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -602,7 +602,8 @@
pw.println(config);
return;
}
- pw.printf("allow(alarms=%b,media=%b,system=%b,calls=%b,callsFrom=%s,repeatCallers=%b,messages=%b,messagesFrom=%s,"
+ pw.printf("allow(alarms=%b,media=%b,system=%b,calls=%b,callsFrom=%s,repeatCallers=%b,"
+ + "messages=%b,messagesFrom=%s,"
+ "events=%b,reminders=%b,whenScreenOff=%b,whenScreenOn=%b)\n",
config.allowAlarms, config.allowMedia, config.allowSystem,
config.allowCalls, ZenModeConfig.sourceToString(config.allowCallsFrom),
@@ -610,6 +611,7 @@
ZenModeConfig.sourceToString(config.allowMessagesFrom),
config.allowEvents, config.allowReminders, config.allowWhenScreenOff,
config.allowWhenScreenOn);
+ pw.printf(" disallow(visualEffects=%s)\n", config.suppressedVisualEffects);
pw.print(prefix); pw.print(" manualRule="); pw.println(config.manualRule);
if (config.automaticRules.isEmpty()) return;
final int N = config.automaticRules.size();
@@ -623,7 +625,7 @@
throws XmlPullParserException, IOException {
final ZenModeConfig config = ZenModeConfig.readXml(parser);
if (config != null) {
- if (config.version < ZenModeConfig.XML_VERSION) {
+ if (config.version < ZenModeConfig.XML_VERSION || forRestore) {
Settings.Global.putInt(mContext.getContentResolver(),
Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 1);
}
@@ -872,7 +874,14 @@
} else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA) {
applyRestrictions(muteMedia || muteEverything, usage);
} else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_SYSTEM) {
- applyRestrictions(muteSystem || muteEverything, usage);
+ if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
+ // normally DND will only restrict touch sounds, not haptic feedback/vibrations
+ applyRestrictions(muteSystem || muteEverything, usage,
+ AppOpsManager.OP_PLAY_AUDIO);
+ applyRestrictions(false, usage, AppOpsManager.OP_VIBRATE);
+ } else {
+ applyRestrictions(muteSystem || muteEverything, usage);
+ }
} else {
applyRestrictions(muteEverything, usage);
}
@@ -881,18 +890,31 @@
@VisibleForTesting
- protected void applyRestrictions(boolean mute, int usage) {
+ protected void applyRestrictions(boolean mute, int usage, int code) {
final String[] exceptionPackages = null; // none (for now)
- mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, usage,
- mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
- exceptionPackages);
- mAppOps.setRestriction(AppOpsManager.OP_PLAY_AUDIO, usage,
- mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
- exceptionPackages);
+ // Only do this if we are executing within the system process... otherwise
+ // we are running as test code, so don't have access to the protected call.
+ if (Process.myUid() == Process.SYSTEM_UID) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ mAppOps.setRestriction(code, usage,
+ mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
+ exceptionPackages);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
}
@VisibleForTesting
+ protected void applyRestrictions(boolean mute, int usage) {
+ applyRestrictions(mute, usage, AppOpsManager.OP_VIBRATE);
+ applyRestrictions(mute, usage, AppOpsManager.OP_PLAY_AUDIO);
+ }
+
+
+ @VisibleForTesting
protected void applyZenToRingerMode() {
if (mAudioManager == null) return;
// force the ringer mode into compliance
@@ -1176,8 +1198,7 @@
@VisibleForTesting
protected Notification createZenUpgradeNotification() {
- Intent intent = new Intent(Settings.ACTION_ZEN_MODE_PRIORITY_SETTINGS)
- .setPackage("com.android.settings")
+ Intent intent = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
final Bundle extras = new Bundle();
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 9bba9ed..24abf86 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -65,6 +65,8 @@
public static final int DEXOPT_IDLE_BACKGROUND_JOB = 1 << 9;
/** Indicates that dexopt should restrict access to private APIs. */
public static final int DEXOPT_ENABLE_HIDDEN_API_CHECKS = 1 << 10;
+ /** Indicates that dexopt should convert to CompactDex. */
+ public static final int DEXOPT_GENERATE_COMPACT_DEX = 1 << 11;
// NOTE: keep in sync with installd
public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 9420a6c..5a7893a 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -266,8 +266,8 @@
throws InstallerException {
final StringBuilder builder = new StringBuilder();
- // The version. Right now it's 7.
- builder.append("7 ");
+ // The current version.
+ builder.append("8 ");
builder.append("dexopt");
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 77bf67d..9e7ad47 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -57,6 +57,7 @@
import static com.android.server.pm.Installer.DEXOPT_STORAGE_DE;
import static com.android.server.pm.Installer.DEXOPT_IDLE_BACKGROUND_JOB;
import static com.android.server.pm.Installer.DEXOPT_ENABLE_HIDDEN_API_CHECKS;
+import static com.android.server.pm.Installer.DEXOPT_GENERATE_COMPACT_DEX;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
@@ -532,12 +533,22 @@
// Some apps are executed with restrictions on hidden API usage. If this app is one
// of them, pass a flag to dexopt to enable the same restrictions during compilation.
int hiddenApiFlag = info.isAllowedToUseHiddenApi() ? 0 : DEXOPT_ENABLE_HIDDEN_API_CHECKS;
+ // Avoid generating CompactDex for modes that are latency critical.
+ final int compilationReason = options.getCompilationReason();
+ boolean generateCompactDex = true;
+ switch (compilationReason) {
+ case PackageManagerService.REASON_FIRST_BOOT:
+ case PackageManagerService.REASON_BOOT:
+ case PackageManagerService.REASON_INSTALL:
+ generateCompactDex = false;
+ }
int dexFlags =
(isPublic ? DEXOPT_PUBLIC : 0)
| (debuggable ? DEXOPT_DEBUGGABLE : 0)
| profileFlag
| (options.isBootComplete() ? DEXOPT_BOOTCOMPLETE : 0)
| (options.isDexoptIdleBackgroundJob() ? DEXOPT_IDLE_BACKGROUND_JOB : 0)
+ | (generateCompactDex ? DEXOPT_GENERATE_COMPACT_DEX : 0)
| hiddenApiFlag;
return adjustDexoptFlags(dexFlags);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index fdba99e..f0922b34 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2592,7 +2592,7 @@
| SCAN_AS_PRIVILEGED,
0);
- // Collected privileged system packages.
+ // Collect privileged system packages.
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
scanDirTracedLI(privilegedAppDir,
mDefParseFlags
@@ -2611,7 +2611,7 @@
| SCAN_AS_SYSTEM,
0);
- // Collected privileged vendor packages.
+ // Collect privileged vendor packages.
File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
try {
privilegedVendorAppDir = privilegedVendorAppDir.getCanonicalFile();
@@ -2642,6 +2642,40 @@
| SCAN_AS_VENDOR,
0);
+ // Collect privileged odm packages. /odm is another vendor partition
+ // other than /vendor.
+ File privilegedOdmAppDir = new File(Environment.getOdmDirectory(),
+ "priv-app");
+ try {
+ privilegedOdmAppDir = privilegedOdmAppDir.getCanonicalFile();
+ } catch (IOException e) {
+ // failed to look up canonical path, continue with original one
+ }
+ scanDirTracedLI(privilegedOdmAppDir,
+ mDefParseFlags
+ | PackageParser.PARSE_IS_SYSTEM_DIR,
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_VENDOR
+ | SCAN_AS_PRIVILEGED,
+ 0);
+
+ // Collect ordinary odm packages. /odm is another vendor partition
+ // other than /vendor.
+ File odmAppDir = new File(Environment.getOdmDirectory(), "app");
+ try {
+ odmAppDir = odmAppDir.getCanonicalFile();
+ } catch (IOException e) {
+ // failed to look up canonical path, continue with original one
+ }
+ scanDirTracedLI(odmAppDir,
+ mDefParseFlags
+ | PackageParser.PARSE_IS_SYSTEM_DIR,
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_VENDOR,
+ 0);
+
// Collect all OEM packages.
final File oemAppDir = new File(Environment.getOemDirectory(), "app");
scanDirTracedLI(oemAppDir,
@@ -2843,7 +2877,8 @@
rescanFlags =
scanFlags
| SCAN_AS_SYSTEM;
- } else if (FileUtils.contains(privilegedVendorAppDir, scanFile)) {
+ } else if (FileUtils.contains(privilegedVendorAppDir, scanFile)
+ || FileUtils.contains(privilegedOdmAppDir, scanFile)) {
reparseFlags =
mDefParseFlags |
PackageParser.PARSE_IS_SYSTEM_DIR;
@@ -2852,7 +2887,8 @@
| SCAN_AS_SYSTEM
| SCAN_AS_VENDOR
| SCAN_AS_PRIVILEGED;
- } else if (FileUtils.contains(vendorAppDir, scanFile)) {
+ } else if (FileUtils.contains(vendorAppDir, scanFile)
+ || FileUtils.contains(odmAppDir, scanFile)) {
reparseFlags =
mDefParseFlags |
PackageParser.PARSE_IS_SYSTEM_DIR;
@@ -3371,6 +3407,13 @@
// "/data/system/package_cache/1"
File cacheDir = FileUtils.createDir(cacheBaseDir, PACKAGE_PARSER_CACHE_VERSION);
+ if (cacheDir == null) {
+ // Something went wrong. Attempt to delete everything and return.
+ Slog.wtf(TAG, "Cache directory cannot be created - wiping base dir " + cacheBaseDir);
+ FileUtils.deleteContentsAndDir(cacheBaseDir);
+ return null;
+ }
+
// The following is a workaround to aid development on non-numbered userdebug
// builds or cases where "adb sync" is used on userdebug builds. If we detect that
// the system partition is newer.
@@ -11747,6 +11790,8 @@
codeRoot = Environment.getOemDirectory();
} else if (FileUtils.contains(Environment.getVendorDirectory(), codePath)) {
codeRoot = Environment.getVendorDirectory();
+ } else if (FileUtils.contains(Environment.getOdmDirectory(), codePath)) {
+ codeRoot = Environment.getOdmDirectory();
} else if (FileUtils.contains(Environment.getProductDirectory(), codePath)) {
codeRoot = Environment.getProductDirectory();
} else {
@@ -18176,9 +18221,11 @@
try {
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
final File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
+ final File privilegedOdmAppDir = new File(Environment.getOdmDirectory(), "priv-app");
final File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
return path.startsWith(privilegedAppDir.getCanonicalPath())
|| path.startsWith(privilegedVendorAppDir.getCanonicalPath())
+ || path.startsWith(privilegedOdmAppDir.getCanonicalPath())
|| path.startsWith(privilegedProductAppDir.getCanonicalPath());
} catch (IOException e) {
Slog.e(TAG, "Unable to access code path " + path);
@@ -18197,7 +18244,8 @@
static boolean locationIsVendor(String path) {
try {
- return path.startsWith(Environment.getVendorDirectory().getCanonicalPath());
+ return path.startsWith(Environment.getVendorDirectory().getCanonicalPath())
+ || path.startsWith(Environment.getOdmDirectory().getCanonicalPath());
} catch (IOException e) {
Slog.e(TAG, "Unable to access code path " + path);
}
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index 054f614..407ceb7 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -125,6 +125,9 @@
*/
public void fixSeInfoLocked() {
final List<PackageParser.Package> pkgList = getPackages();
+ if (pkgList == null || pkgList.size() == 0) {
+ return;
+ }
for (PackageParser.Package pkg : pkgList) {
if (pkg.applicationInfo.targetSdkVersion < seInfoTargetSdkVersion) {
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 4abcce1..bf85f30 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1240,6 +1240,10 @@
if (dir.isDirectory() && dir.canRead()) {
Collections.addAll(ret, dir.listFiles());
}
+ dir = new File(Environment.getOdmDirectory(), "etc/default-permissions");
+ if (dir.isDirectory() && dir.canRead()) {
+ Collections.addAll(ret, dir.listFiles());
+ }
dir = new File(Environment.getProductDirectory(), "etc/default-permissions");
if (dir.isDirectory() && dir.canRead()) {
Collections.addAll(ret, dir.listFiles());
diff --git a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
index c6ec287..4aa2446 100644
--- a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
@@ -16,6 +16,9 @@
package com.android.server.policy;
+import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
+import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
+
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.app.ActivityManager;
@@ -78,6 +81,7 @@
// Local copy of vr mode enabled state, to avoid calling into VrManager with
// the lock held.
boolean mVrModeEnabled = false;
+ private int mLockTaskState = LOCK_TASK_MODE_NONE;
public ImmersiveModeConfirmation(Context context) {
mContext = ActivityThread.currentActivityThread().getSystemUiContext();
@@ -148,7 +152,8 @@
&& userSetupComplete
&& !mVrModeEnabled
&& !navBarEmpty
- && !UserManager.isDeviceInDemoMode(mContext)) {
+ && !UserManager.isDeviceInDemoMode(mContext)
+ && (mLockTaskState != LOCK_TASK_MODE_LOCKED)) {
mHandler.sendEmptyMessageDelayed(H.SHOW, mShowDelayMs);
}
} else {
@@ -401,4 +406,8 @@
}
}
};
+
+ void onLockTaskModeChangedLw(int lockTaskState) {
+ mLockTaskState = lockTaskState;
+ }
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index a0e4f4f..3cd79e1 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1456,6 +1456,9 @@
+ "already in the process of turning the screen on.");
return;
}
+ Slog.d(TAG, "powerPress: eventTime=" + eventTime + " interactive=" + interactive
+ + " count=" + count + " beganFromNonInteractive=" + mBeganFromNonInteractive +
+ " mShortPressOnPowerBehavior=" + mShortPressOnPowerBehavior);
if (count == 2) {
powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
@@ -1755,7 +1758,6 @@
}
void showGlobalActionsInternal() {
- sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
if (mGlobalActions == null) {
mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
}
@@ -2680,8 +2682,9 @@
attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
break;
case TYPE_DREAM:
- // Dreams don't have an app window token and can thus not be letterboxed.
- // Hence always let them extend under the cutout.
+ case TYPE_WALLPAPER:
+ // Dreams and wallpapers don't have an app window token and can thus not be
+ // letterboxed. Hence always let them extend under the cutout.
attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
break;
case TYPE_STATUS_BAR:
@@ -3880,6 +3883,15 @@
hideRecentApps(true, false);
}
+ // Handle keyboard layout switching.
+ // TODO: Deprecate this behavior when we fully migrate to IME subtype-based layout rotation.
+ if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_SPACE
+ && ((metaState & KeyEvent.META_CTRL_MASK) != 0)) {
+ int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
+ mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
+ return -1;
+ }
+
// Handle input method switching.
if (down && repeatCount == 0
&& (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
@@ -4481,7 +4493,8 @@
displayWidth, displayHeight);
outFrame.intersect(taskBounds);
}
- outDisplayCutout.set(displayFrames.mDisplayCutout.calculateRelativeTo(outFrame));
+ outDisplayCutout.set(displayFrames.mDisplayCutout.calculateRelativeTo(outFrame)
+ .getDisplayCutout());
return mForceShowSystemBars;
} else {
if (layoutInScreen) {
@@ -4747,7 +4760,7 @@
// It's a system nav bar or a portrait screen; nav bar goes on bottom.
final int top = cutoutSafeUnrestricted.bottom
- getNavigationBarHeight(rotation, uiMode);
- mTmpNavigationFrame.set(0, top, displayWidth, cutoutSafeUnrestricted.bottom);
+ mTmpNavigationFrame.set(0, top, displayWidth, displayFrames.mUnrestricted.bottom);
displayFrames.mStable.bottom = displayFrames.mStableFullscreen.bottom = top;
if (transientNavBarShowing) {
mNavigationBarController.setBarShowingLw(true);
@@ -4770,7 +4783,7 @@
// Landscape screen; nav bar goes to the right.
final int left = cutoutSafeUnrestricted.right
- getNavigationBarWidth(rotation, uiMode);
- mTmpNavigationFrame.set(left, 0, cutoutSafeUnrestricted.right, displayHeight);
+ mTmpNavigationFrame.set(left, 0, displayFrames.mUnrestricted.right, displayHeight);
displayFrames.mStable.right = displayFrames.mStableFullscreen.right = left;
if (transientNavBarShowing) {
mNavigationBarController.setBarShowingLw(true);
@@ -4793,7 +4806,7 @@
// Seascape screen; nav bar goes to the left.
final int right = cutoutSafeUnrestricted.left
+ getNavigationBarWidth(rotation, uiMode);
- mTmpNavigationFrame.set(cutoutSafeUnrestricted.left, 0, right, displayHeight);
+ mTmpNavigationFrame.set(displayFrames.mUnrestricted.left, 0, right, displayHeight);
displayFrames.mStable.left = displayFrames.mStableFullscreen.left = right;
if (transientNavBarShowing) {
mNavigationBarController.setBarShowingLw(true);
@@ -4822,8 +4835,9 @@
mStatusBarLayer = mNavigationBar.getSurfaceLayer();
// And compute the final frame.
mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
- mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
- mTmpNavigationFrame, mTmpNavigationFrame, displayFrames.mDisplayCutout);
+ mTmpNavigationFrame, displayFrames.mDisplayCutoutSafe, mTmpNavigationFrame, dcf,
+ mTmpNavigationFrame, displayFrames.mDisplayCutoutSafe,
+ displayFrames.mDisplayCutout);
if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
return mNavigationBarController.checkHiddenLw();
}
@@ -4981,8 +4995,7 @@
df.set(displayFrames.mDock);
pf.set(displayFrames.mDock);
// IM dock windows layout below the nav bar...
- pf.bottom = df.bottom = of.bottom = Math.min(displayFrames.mUnrestricted.bottom,
- displayFrames.mDisplayCutoutSafe.bottom);
+ pf.bottom = df.bottom = of.bottom = displayFrames.mUnrestricted.bottom;
// ...with content insets above the nav bar
cf.bottom = vf.bottom = displayFrames.mStable.bottom;
if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
@@ -5094,11 +5107,12 @@
pf.set(displayFrames.mOverscan);
} else if (canHideNavigationBar()
&& (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
- && type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW) {
+ && (type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW
+ || type == TYPE_VOLUME_OVERLAY)) {
// Asking for layout as if the nav bar is hidden, lets the application
// extend into the unrestricted overscan screen area. We only do this for
- // application windows to ensure no window that can be above the nav bar can
- // do this.
+ // application windows and certain system windows to ensure no window that
+ // can be above the nav bar can do this.
df.set(displayFrames.mOverscan);
pf.set(displayFrames.mOverscan);
// We need to tell the app about where the frame inside the overscan is, so
@@ -5158,15 +5172,6 @@
if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
"Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
pf.left, pf.top, pf.right, pf.bottom));
- } else if (type == TYPE_VOLUME_OVERLAY) {
- // Volume overlay covers everything, including the status and navbar
- cf.set(displayFrames.mUnrestricted);
- of.set(displayFrames.mUnrestricted);
- df.set(displayFrames.mUnrestricted);
- pf.set(displayFrames.mUnrestricted);
- if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
- "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
- pf.left, pf.top, pf.right, pf.bottom));
} else if (type == TYPE_NAVIGATION_BAR || type == TYPE_NAVIGATION_BAR_PANEL) {
// The navigation bar has Real Ultimate Power.
of.set(displayFrames.mUnrestricted);
@@ -5250,8 +5255,8 @@
"): normal window");
// Otherwise, a normal window must be placed inside the content
// of all screen decorations.
- if (type == TYPE_STATUS_BAR_PANEL || type == TYPE_VOLUME_OVERLAY) {
- // Status bar panels and the volume dialog are the only windows who can go on
+ if (type == TYPE_STATUS_BAR_PANEL) {
+ // Status bar panels can go on
// top of the status bar. They are protected by the STATUS_BAR_SERVICE
// permission, so they have the same privileges as the status bar itself.
cf.set(displayFrames.mRestricted);
@@ -5291,27 +5296,48 @@
final int cutoutMode = attrs.layoutInDisplayCutoutMode;
final boolean attachedInParent = attached != null && !layoutInScreen;
+ final boolean requestedHideNavigation =
+ (requestedSysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
// Ensure that windows with a DEFAULT or NEVER display cutout mode are laid out in
// the cutout safe zone.
if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
- final Rect displayCutoutSafeExceptMaybeTop = mTmpRect;
- displayCutoutSafeExceptMaybeTop.set(displayFrames.mDisplayCutoutSafe);
+ final Rect displayCutoutSafeExceptMaybeBars = mTmpRect;
+ displayCutoutSafeExceptMaybeBars.set(displayFrames.mDisplayCutoutSafe);
if (layoutInScreen && layoutInsetDecor && !requestedFullscreen
&& cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT) {
// At the top we have the status bar, so apps that are
// LAYOUT_IN_SCREEN | LAYOUT_INSET_DECOR but not FULLSCREEN
// already expect that there's an inset there and we don't need to exclude
// the window from that area.
- displayCutoutSafeExceptMaybeTop.top = Integer.MIN_VALUE;
+ displayCutoutSafeExceptMaybeBars.top = Integer.MIN_VALUE;
+ }
+ if (layoutInScreen && layoutInsetDecor && !requestedHideNavigation
+ && cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT) {
+ // Same for the navigation bar.
+ switch (mNavigationBarPosition) {
+ case NAV_BAR_BOTTOM:
+ displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
+ break;
+ case NAV_BAR_RIGHT:
+ displayCutoutSafeExceptMaybeBars.right = Integer.MAX_VALUE;
+ break;
+ case NAV_BAR_LEFT:
+ displayCutoutSafeExceptMaybeBars.left = Integer.MIN_VALUE;
+ break;
+ }
+ }
+ if (type == TYPE_INPUT_METHOD && mNavigationBarPosition == NAV_BAR_BOTTOM) {
+ // The IME can always extend under the bottom cutout if the navbar is there.
+ displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
}
// Windows that are attached to a parent and laid out in said parent are already
// avoidingthe cutout according to that parent and don't need to be further constrained.
if (!attachedInParent) {
- pf.intersectUnchecked(displayCutoutSafeExceptMaybeTop);
+ pf.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
}
- // Make sure that NO_LIMITS windows clipped to the display don't extend into the display
- // don't extend under the cutout.
- df.intersectUnchecked(displayCutoutSafeExceptMaybeTop);
+ // Make sure that NO_LIMITS windows clipped to the display don't extend under the
+ // cutout.
+ df.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
}
// Content should never appear in the cutout.
@@ -8785,4 +8811,9 @@
return Integer.toString(behavior);
}
}
+
+ @Override
+ public void onLockTaskStateChangedLw(int lockTaskState) {
+ mImmersiveModeConfirmation.onLockTaskModeChangedLw(lockTaskState);
+ }
}
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index cd6ff30..b0d5e1a 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -66,6 +66,7 @@
import android.Manifest;
import android.annotation.IntDef;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.CompatibilityInfo;
@@ -93,6 +94,7 @@
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
import com.android.server.wm.DisplayFrames;
+import com.android.server.wm.utils.WmDisplayCutout;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -217,11 +219,11 @@
* @param stableFrame The frame around which stable system decoration is positioned.
* @param outsetFrame The frame that includes areas that aren't part of the surface but we
* want to treat them as such.
- * @param displayCutout the display displayCutout
+ * @param displayCutout the display cutout
*/
public void computeFrameLw(Rect parentFrame, Rect displayFrame,
Rect overlayFrame, Rect contentFrame, Rect visibleFrame, Rect decorFrame,
- Rect stableFrame, @Nullable Rect outsetFrame, DisplayCutout displayCutout);
+ Rect stableFrame, @Nullable Rect outsetFrame, WmDisplayCutout displayCutout);
/**
* Retrieve the current frame of the window that has been assigned by
@@ -545,6 +547,12 @@
public int getCameraLensCoverState();
/**
+ * Switch the keyboard layout for the given device.
+ * Direction should be +1 or -1 to go to the next or previous keyboard layout.
+ */
+ public void switchKeyboardLayout(int deviceId, int direction);
+
+ /**
* Switch the input method, to be precise, input method subtype.
*
* @param forwardDirection {@code true} to rotate in a forward direction.
@@ -1724,4 +1732,15 @@
* on the next user activity.
*/
public void requestUserActivityNotification();
+
+ /**
+ * Called when the state of lock task mode changes. This should be used to disable immersive
+ * mode confirmation.
+ *
+ * @param lockTaskState the new lock task mode state. One of
+ * {@link ActivityManager#LOCK_TASK_MODE_NONE},
+ * {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
+ * {@link ActivityManager#LOCK_TASK_MODE_PINNED}.
+ */
+ void onLockTaskStateChangedLw(int lockTaskState);
}
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index b729b6a..285532a 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -720,9 +720,12 @@
private void playChargingStartedSound() {
final boolean enabled = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.CHARGING_SOUNDS_ENABLED, 1) != 0;
+ final boolean dndOff = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
+ == Settings.Global.ZEN_MODE_OFF;
final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
Settings.Global.CHARGING_STARTED_SOUND);
- if (enabled && soundPath != null) {
+ if (enabled && dndOff && soundPath != null) {
final Uri soundUri = Uri.parse("file://" + soundPath);
if (soundUri != null) {
final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index f77b0ee..055e6ea 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -68,7 +68,6 @@
import android.service.dreams.DreamManagerInternal;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
-import android.util.EventLog;
import android.util.KeyValueListParser;
import android.util.MathUtils;
import android.util.PrintWriterPrinter;
@@ -488,6 +487,9 @@
// The screen brightness to use while dozing.
private int mDozeScreenBrightnessOverrideFromDreamManager = PowerManager.BRIGHTNESS_DEFAULT;
+ // Keep display state when dozing.
+ private boolean mDrawWakeLockOverrideFromSidekick;
+
// Time when we last logged a warning about calling userActivity() without permission.
private long mLastWarningAboutUserActivityPermission = Long.MIN_VALUE;
@@ -1487,7 +1489,7 @@
break;
}
}
- EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numWakeLocksCleared);
+ EventLogTags.writePowerSleepRequested(numWakeLocksCleared);
// Skip dozing if requested.
if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {
@@ -1572,7 +1574,7 @@
final long now = SystemClock.uptimeMillis();
final long savedWakeTimeMs = mOverriddenTimeout - now;
if (savedWakeTimeMs >= 0) {
- EventLog.writeEvent(EventLogTags.POWER_SOFT_SLEEP_REQUESTED, savedWakeTimeMs);
+ EventLogTags.writePowerSoftSleepRequested(savedWakeTimeMs);
mOverriddenTimeout = -1;
}
}
@@ -2424,7 +2426,8 @@
if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
- if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {
+ if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0
+ && !mDrawWakeLockOverrideFromSidekick) {
if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND) {
mDisplayPowerRequest.dozeScreenState = Display.STATE_DOZE;
}
@@ -3157,6 +3160,7 @@
synchronized (mLock) {
if (mUserActivityTimeoutOverrideFromWindowManager != timeoutMillis) {
mUserActivityTimeoutOverrideFromWindowManager = timeoutMillis;
+ EventLogTags.writeUserActivityTimeoutOverride(timeoutMillis);
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
}
@@ -3176,6 +3180,16 @@
}
}
+ private void setDrawWakeLockOverrideFromSidekickInternal(boolean keepState) {
+ synchronized (mLock) {
+ if (mDrawWakeLockOverrideFromSidekick != keepState) {
+ mDrawWakeLockOverrideFromSidekick = keepState;
+ mDirty |= DIRTY_SETTINGS;
+ updatePowerStateLocked();
+ }
+ }
+ }
+
@VisibleForTesting
void setVrModeEnabled(boolean enabled) {
mIsVrModeEnabled = enabled;
@@ -3381,6 +3395,7 @@
+ mUserInactiveOverrideFromWindowManager);
pw.println(" mDozeScreenStateOverrideFromDreamManager="
+ mDozeScreenStateOverrideFromDreamManager);
+ pw.println(" mDrawWakeLockOverrideFromSidekick=" + mDrawWakeLockOverrideFromSidekick);
pw.println(" mDozeScreenBrightnessOverrideFromDreamManager="
+ mDozeScreenBrightnessOverrideFromDreamManager);
pw.println(" mScreenBrightnessSettingMinimum=" + mScreenBrightnessSettingMinimum);
@@ -3717,6 +3732,10 @@
mDozeScreenStateOverrideFromDreamManager);
proto.write(
PowerServiceSettingsAndConfigurationDumpProto
+ .DRAW_WAKE_LOCK_OVERRIDE_FROM_SIDEKICK,
+ mDrawWakeLockOverrideFromSidekick);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
.DOZED_SCREEN_BRIGHTNESS_OVERRIDE_FROM_DREAM_MANAGER,
mDozeScreenBrightnessOverrideFromDreamManager);
@@ -4703,6 +4722,11 @@
}
@Override
+ public void setDrawWakeLockOverrideFromSidekick(boolean keepState) {
+ setDrawWakeLockOverrideFromSidekickInternal(keepState);
+ }
+
+ @Override
public void setMaximumScreenOffTimeoutFromDeviceAdmin(@UserIdInt int userId, long timeMs) {
setMaximumScreenOffTimeoutFromDeviceAdminInternal(userId, timeMs);
}
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 64a2570..954627b 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -73,6 +73,7 @@
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeoutException;
@@ -196,6 +197,7 @@
@Override
public void sendSubscriberBroadcast(IBinder intentSenderBinder, long configUid, long configKey,
long subscriptionId, long subscriptionRuleId,
+ String[] cookies,
StatsDimensionsValue dimensionsValue) {
enforceCallingPermission();
IntentSender intentSender = new IntentSender(intentSenderBinder);
@@ -205,10 +207,17 @@
.putExtra(StatsManager.EXTRA_STATS_SUBSCRIPTION_ID, subscriptionId)
.putExtra(StatsManager.EXTRA_STATS_SUBSCRIPTION_RULE_ID, subscriptionRuleId)
.putExtra(StatsManager.EXTRA_STATS_DIMENSIONS_VALUE, dimensionsValue);
+
+ ArrayList<String> cookieList = new ArrayList<>(cookies.length);
+ for (String cookie : cookies) { cookieList.add(cookie); }
+ intent.putStringArrayListExtra(
+ StatsManager.EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES, cookieList);
+
if (DEBUG) {
- Slog.d(TAG, String.format("Statsd sendSubscriberBroadcast with params {%d %d %d %d %s}",
- configUid, configKey, subscriptionId,
- subscriptionRuleId, dimensionsValue));
+ Slog.d(TAG, String.format(
+ "Statsd sendSubscriberBroadcast with params {%d %d %d %d %s %s}",
+ configUid, configKey, subscriptionId, subscriptionRuleId,
+ Arrays.toString(cookies), dimensionsValue));
}
try {
intentSender.sendIntent(mContext, CODE_SUBSCRIBER_BROADCAST, intent, null, null);
@@ -278,7 +287,7 @@
&& intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
return; // Keep only replacing or normal add and remove.
}
- Slog.i(TAG, "StatsCompanionService noticed an app was updated.");
+ if (DEBUG) Slog.d(TAG, "StatsCompanionService noticed an app was updated.");
synchronized (sStatsdLock) {
if (sStatsd == null) {
Slog.w(TAG, "Could not access statsd to inform it of an app update");
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index 0ac853b..6053512 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -16,11 +16,12 @@
package com.android.server.textclassifier;
-import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -30,6 +31,7 @@
import android.service.textclassifier.ITextLinksCallback;
import android.service.textclassifier.ITextSelectionCallback;
import android.service.textclassifier.TextClassifierService;
+import android.view.textclassifier.SelectionEvent;
import android.view.textclassifier.TextClassification;
import android.view.textclassifier.TextClassifier;
import android.view.textclassifier.TextLinks;
@@ -216,6 +218,23 @@
}
}
+ @Override
+ public void onSelectionEvent(SelectionEvent event) throws RemoteException {
+ validateInput(event, mContext);
+
+ synchronized (mLock) {
+ if (isBoundLocked()) {
+ mService.onSelectionEvent(event);
+ } else {
+ final Callable<Void> request = () -> {
+ onSelectionEvent(event);
+ return null;
+ };
+ enqueueRequestLocked(request, null /* onServiceFailure */, null /* binder */);
+ }
+ }
+ }
+
/**
* @return true if the service is bound or in the process of being bound.
* Returns false otherwise.
@@ -281,8 +300,8 @@
private final class PendingRequest implements IBinder.DeathRecipient {
private final Callable<Void> mRequest;
- private final Callable<Void> mOnServiceFailure;
- private final IBinder mBinder;
+ @Nullable private final Callable<Void> mOnServiceFailure;
+ @Nullable private final IBinder mBinder;
/**
* Initializes a new pending request.
@@ -292,15 +311,17 @@
* @param binder binder to the process that made this pending request
*/
PendingRequest(
- @NonNull Callable<Void> request, @NonNull Callable<Void> onServiceFailure,
- @NonNull IBinder binder) {
+ Callable<Void> request, @Nullable Callable<Void> onServiceFailure,
+ @Nullable IBinder binder) {
mRequest = Preconditions.checkNotNull(request);
- mOnServiceFailure = Preconditions.checkNotNull(onServiceFailure);
- mBinder = Preconditions.checkNotNull(binder);
- try {
- mBinder.linkToDeath(this, 0);
- } catch (RemoteException e) {
- e.printStackTrace();
+ mOnServiceFailure = onServiceFailure;
+ mBinder = binder;
+ if (mBinder != null) {
+ try {
+ mBinder.linkToDeath(this, 0);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
}
}
@@ -317,11 +338,13 @@
@GuardedBy("mLock")
void notifyServiceFailureLocked() {
removeLocked();
- try {
- mOnServiceFailure.call();
- } catch (Exception e) {
- Slog.d(LOG_TAG, "Error notifying callback of service failure: "
- + e.getMessage());
+ if (mOnServiceFailure != null) {
+ try {
+ mOnServiceFailure.call();
+ } catch (Exception e) {
+ Slog.d(LOG_TAG, "Error notifying callback of service failure: "
+ + e.getMessage());
+ }
}
}
@@ -336,7 +359,9 @@
@GuardedBy("mLock")
private void removeLocked() {
mPendingRequests.remove(this);
- mBinder.unlinkToDeath(this, 0);
+ if (mBinder != null) {
+ mBinder.unlinkToDeath(this, 0);
+ }
}
}
@@ -359,4 +384,16 @@
throw new RemoteException(e.getMessage());
}
}
+
+ private static void validateInput(SelectionEvent event, Context context)
+ throws RemoteException {
+ try {
+ final int uid = context.getPackageManager()
+ .getPackageUid(event.getPackageName(), 0);
+ Preconditions.checkArgument(Binder.getCallingUid() == uid);
+ } catch (IllegalArgumentException | NullPointerException |
+ PackageManager.NameNotFoundException e) {
+ throw new RemoteException(e.getMessage());
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/AnimationAdapter.java b/services/core/java/com/android/server/wm/AnimationAdapter.java
index 64f77a2..00e3050 100644
--- a/services/core/java/com/android/server/wm/AnimationAdapter.java
+++ b/services/core/java/com/android/server/wm/AnimationAdapter.java
@@ -17,13 +17,15 @@
package com.android.server.wm;
import android.annotation.ColorInt;
-import android.graphics.Point;
+import android.util.proto.ProtoOutputStream;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.animation.Animation;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+import java.io.PrintWriter;
+
/**
* Interface that describes an animation and bridges the animation start to the component
* responsible for running the animation.
@@ -83,4 +85,14 @@
* @return the desired start time of the status bar transition, in uptime millis
*/
long getStatusBarTransitionsStartTime();
+
+ void dump(PrintWriter pw, String prefix);
+
+ default void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+ writeToProto(proto);
+ proto.end(token);
+ }
+
+ void writeToProto(ProtoOutputStream proto);
}
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 40f772a..1170148 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -379,6 +379,8 @@
if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + wtoken);
wtoken.mAppStopped = false;
+
+ mContainer.transferStartingWindowFromHiddenAboveTokenIfNeeded();
}
// If we are preparing an app transition, then delay changing
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 2672337..b2f153a 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -187,6 +187,7 @@
StartingSurface startingSurface;
boolean startingDisplayed;
boolean startingMoved;
+
// True if the hidden state of this token was forced to false due to a transferred starting
// window.
private boolean mHiddenSetFromTransferredStartingWindow;
@@ -1136,6 +1137,25 @@
stopFreezingScreen(true, true);
}
+ /**
+ * Tries to transfer the starting window from a token that's above ourselves in the task but
+ * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
+ * activity M in the same task. Now, when reopening the task, T starts on top of M but then
+ * immediately finishes after, so we have to transfer T to M.
+ */
+ void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
+ final Task task = getTask();
+ for (int i = task.mChildren.size() - 1; i >= 0; i--) {
+ final AppWindowToken fromToken = task.mChildren.get(i);
+ if (fromToken == this) {
+ return;
+ }
+ if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
+ return;
+ }
+ }
+ }
+
boolean transferStartingWindow(IBinder transferFrom) {
final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
if (fromToken == null) {
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index a180a3a..5c62987 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -16,11 +16,19 @@
package com.android.server.wm;
-import android.view.SurfaceControl;
+import static com.android.server.wm.proto.AlphaAnimationSpecProto.DURATION;
+import static com.android.server.wm.proto.AlphaAnimationSpecProto.FROM;
+import static com.android.server.wm.proto.AlphaAnimationSpecProto.TO;
+import static com.android.server.wm.proto.AnimationSpecProto.ALPHA;
+
import android.graphics.Rect;
+import android.util.proto.ProtoOutputStream;
+import android.view.SurfaceControl;
import com.android.internal.annotations.VisibleForTesting;
+import java.io.PrintWriter;
+
/**
* Utility class for use by a WindowContainer implementation to add "DimLayer" support, that is
* black layers of varying opacity at various Z-levels which create the effect of a Dim.
@@ -334,5 +342,21 @@
+ mFromAlpha;
t.setAlpha(sc, alpha);
}
+
+ @Override
+ public void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.print("from="); pw.print(mFromAlpha);
+ pw.print(" to="); pw.print(mToAlpha);
+ pw.print(" duration="); pw.println(mDuration);
+ }
+
+ @Override
+ public void writeToProtoInner(ProtoOutputStream proto) {
+ final long token = proto.start(ALPHA);
+ proto.write(FROM, mFromAlpha);
+ proto.write(TO, mToAlpha);
+ proto.write(DURATION, mDuration);
+ proto.end(token);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 7b5e8b8..2dce913 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -154,6 +154,7 @@
import com.android.internal.view.IInputMethodClient;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.wm.utils.RotationCache;
+import com.android.server.wm.utils.WmDisplayCutout;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -214,7 +215,7 @@
int mInitialDisplayDensity = 0;
DisplayCutout mInitialDisplayCutout;
- private final RotationCache<DisplayCutout, DisplayCutout> mDisplayCutoutCache
+ private final RotationCache<DisplayCutout, WmDisplayCutout> mDisplayCutoutCache
= new RotationCache<>(this::calculateDisplayCutoutForRotationUncached);
/**
@@ -735,7 +736,8 @@
display.getDisplayInfo(mDisplayInfo);
display.getMetrics(mDisplayMetrics);
isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
- mDisplayFrames = new DisplayFrames(mDisplayId, mDisplayInfo);
+ mDisplayFrames = new DisplayFrames(mDisplayId, mDisplayInfo,
+ calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
initializeDisplayBaseInfo();
mDividerControllerLocked = new DockedStackDividerController(service, this);
mPinnedStackControllerLocked = new PinnedStackController(service, this);
@@ -1128,7 +1130,8 @@
mService.mPolicy.setInitialDisplaySize(getDisplay(),
mBaseDisplayWidth, mBaseDisplayHeight, mBaseDisplayDensity);
- mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo);
+ mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo,
+ calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
}
/**
@@ -1161,8 +1164,9 @@
}
// Update application display metrics.
- final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(
- mRotation);
+ final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(mRotation);
+ final DisplayCutout displayCutout = wmDisplayCutout.getDisplayCutout();
+
final int appWidth = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation, uiMode,
mDisplayId, displayCutout);
final int appHeight = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation, uiMode,
@@ -1177,7 +1181,7 @@
mDisplayInfo.getLogicalMetrics(mRealDisplayMetrics,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
}
- mDisplayInfo.displayCutout = displayCutout;
+ mDisplayInfo.displayCutout = displayCutout.isEmpty() ? null : displayCutout;
mDisplayInfo.getAppMetrics(mDisplayMetrics);
if (mDisplayScalingDisabled) {
mDisplayInfo.flags |= Display.FLAG_SCALING_DISABLED;
@@ -1199,24 +1203,25 @@
return mDisplayInfo;
}
- DisplayCutout calculateDisplayCutoutForRotation(int rotation) {
+ WmDisplayCutout calculateDisplayCutoutForRotation(int rotation) {
return mDisplayCutoutCache.getOrCompute(mInitialDisplayCutout, rotation);
}
- private DisplayCutout calculateDisplayCutoutForRotationUncached(
+ private WmDisplayCutout calculateDisplayCutoutForRotationUncached(
DisplayCutout cutout, int rotation) {
if (cutout == null || cutout == DisplayCutout.NO_CUTOUT) {
- return cutout;
+ return WmDisplayCutout.NO_CUTOUT;
}
if (rotation == ROTATION_0) {
- return cutout.computeSafeInsets(mInitialDisplayWidth, mInitialDisplayHeight);
+ return WmDisplayCutout.computeSafeInsets(
+ cutout, mInitialDisplayWidth, mInitialDisplayHeight);
}
final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
final Path bounds = cutout.getBounds().getBoundaryPath();
transformPhysicalToLogicalCoordinates(rotation, mInitialDisplayWidth, mInitialDisplayHeight,
mTmpMatrix);
bounds.transform(mTmpMatrix);
- return DisplayCutout.fromBounds(bounds).computeSafeInsets(
+ return WmDisplayCutout.computeSafeInsets(DisplayCutout.fromBounds(bounds),
rotated ? mInitialDisplayHeight : mInitialDisplayWidth,
rotated ? mInitialDisplayWidth : mInitialDisplayHeight);
}
@@ -1441,7 +1446,8 @@
private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int displayId, int rotation,
int uiMode, int dw, int dh) {
- final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(rotation);
+ final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(
+ rotation).getDisplayCutout();
final int width = mService.mPolicy.getConfigDisplayWidth(dw, dh, rotation, uiMode,
displayId, displayCutout);
if (width < displayInfo.smallestNominalAppWidth) {
@@ -2910,7 +2916,8 @@
Slog.v(TAG, "performLayout: needed=" + isLayoutNeeded() + " dw=" + dw + " dh=" + dh);
}
- mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo);
+ mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo,
+ calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
// TODO: Not sure if we really need to set the rotation here since we are updating from the
// display info above...
mDisplayFrames.mRotation = mRotation;
diff --git a/services/core/java/com/android/server/wm/DisplayFrames.java b/services/core/java/com/android/server/wm/DisplayFrames.java
index 57ce15bc..57693ac 100644
--- a/services/core/java/com/android/server/wm/DisplayFrames.java
+++ b/services/core/java/com/android/server/wm/DisplayFrames.java
@@ -27,6 +27,8 @@
import android.view.DisplayCutout;
import android.view.DisplayInfo;
+import com.android.server.wm.utils.WmDisplayCutout;
+
import java.io.PrintWriter;
/**
@@ -97,10 +99,10 @@
public final Rect mDock = new Rect();
/** The display cutout used for layout (after rotation) */
- @NonNull public DisplayCutout mDisplayCutout = DisplayCutout.NO_CUTOUT;
+ @NonNull public WmDisplayCutout mDisplayCutout = WmDisplayCutout.NO_CUTOUT;
/** The cutout as supplied by display info */
- @NonNull private DisplayCutout mDisplayInfoCutout = DisplayCutout.NO_CUTOUT;
+ @NonNull public WmDisplayCutout mDisplayInfoCutout = WmDisplayCutout.NO_CUTOUT;
/**
* During layout, the frame that is display-cutout safe, i.e. that does not intersect with it.
@@ -114,19 +116,18 @@
public int mRotation;
- public DisplayFrames(int displayId, DisplayInfo info) {
+ public DisplayFrames(int displayId, DisplayInfo info, WmDisplayCutout displayCutout) {
mDisplayId = displayId;
- onDisplayInfoUpdated(info);
+ onDisplayInfoUpdated(info, displayCutout);
}
- public void onDisplayInfoUpdated(DisplayInfo info) {
+ public void onDisplayInfoUpdated(DisplayInfo info, WmDisplayCutout displayCutout) {
mDisplayWidth = info.logicalWidth;
mDisplayHeight = info.logicalHeight;
mRotation = info.rotation;
mDisplayInfoOverscan.set(
info.overscanLeft, info.overscanTop, info.overscanRight, info.overscanBottom);
- mDisplayInfoCutout = info.displayCutout != null
- ? info.displayCutout : DisplayCutout.NO_CUTOUT;
+ mDisplayInfoCutout = displayCutout != null ? displayCutout : WmDisplayCutout.NO_CUTOUT;
}
public void onBeginLayout() {
@@ -171,8 +172,8 @@
mDisplayCutout = mDisplayInfoCutout;
mDisplayCutoutSafe.set(Integer.MIN_VALUE, Integer.MIN_VALUE,
Integer.MAX_VALUE, Integer.MAX_VALUE);
- if (!mDisplayCutout.isEmpty()) {
- final DisplayCutout c = mDisplayCutout;
+ if (!mDisplayCutout.getDisplayCutout().isEmpty()) {
+ final DisplayCutout c = mDisplayCutout.getDisplayCutout();
if (c.getSafeInsetLeft() > 0) {
mDisplayCutoutSafe.left = mRestrictedOverscan.left + c.getSafeInsetLeft();
}
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 1f1efc4..b99e85f 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -175,7 +175,7 @@
getContentWidth());
final DisplayCutout displayCutout = mDisplayContent.calculateDisplayCutoutForRotation(
- rotation);
+ rotation).getDisplayCutout();
// Since we only care about feasible states, snap to the closest snap target, like it
// would happen when actually rotating the screen.
@@ -233,7 +233,7 @@
? mDisplayContent.mBaseDisplayWidth
: mDisplayContent.mBaseDisplayHeight;
final DisplayCutout displayCutout =
- mDisplayContent.calculateDisplayCutoutForRotation(rotation);
+ mDisplayContent.calculateDisplayCutoutForRotation(rotation).getDisplayCutout();
mService.mPolicy.getStableInsetsLw(rotation, dw, dh, displayCutout, mTmpRect);
config.unset();
config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
diff --git a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
index 1b41cb8..3f1fde9 100644
--- a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
+++ b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
@@ -16,12 +16,18 @@
package com.android.server.wm;
+import static com.android.server.wm.proto.AnimationAdapterProto.LOCAL;
+import static com.android.server.wm.proto.LocalAnimationAdapterProto.ANIMATION_SPEC;
+
import android.os.SystemClock;
+import android.util.proto.ProtoOutputStream;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+import java.io.PrintWriter;
+
/**
* Animation that can be executed without holding the window manager lock. See
* {@link SurfaceAnimationRunner}.
@@ -74,6 +80,18 @@
return mSpec.calculateStatusBarTransitionStartTime();
}
+ @Override
+ public void dump(PrintWriter pw, String prefix) {
+ mSpec.dump(pw, prefix);
+ }
+
+ @Override
+ public void writeToProto(ProtoOutputStream proto) {
+ final long token = proto.start(LOCAL);
+ mSpec.writeToProto(proto, ANIMATION_SPEC);
+ proto.end(token);
+ }
+
/**
* Describes how to apply an animation.
*/
@@ -127,5 +145,15 @@
default boolean canSkipFirstFrame() {
return false;
}
+
+ void dump(PrintWriter pw, String prefix);
+
+ default void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+ writeToProtoInner(proto);
+ proto.end(token);
+ }
+
+ void writeToProtoInner(ProtoOutputStream proto);
}
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index f7344b2..0b0df6f 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -23,28 +23,33 @@
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.proto.RemoteAnimationAdapterWrapperProto.TARGET;
+import static com.android.server.wm.proto.AnimationAdapterProto.REMOTE;
import android.app.ActivityManager.TaskSnapshot;
import android.app.WindowConfiguration;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Binder;
-import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.ArraySet;
import android.util.Log;
-import android.util.Slog;
+import android.util.Slog;import android.util.proto.ProtoOutputStream;
+import android.util.SparseBooleanArray;
+import android.util.proto.ProtoOutputStream;
import android.view.IRecentsAnimationController;
import android.view.IRecentsAnimationRunner;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
-import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+
import com.google.android.collect.Sets;
+
+import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+
import java.io.PrintWriter;
import java.util.ArrayList;
-
/**
* Controls a single instance of the remote driven recents animation. In particular, this allows
* the calling SystemUI to animate the visible task windows as a part of the transition. The remote
@@ -136,6 +141,22 @@
}
@Override
+ public void setAnimationTargetsBehindSystemBars(boolean behindSystemBars)
+ throws RemoteException {
+ long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mService.getWindowManagerLock()) {
+ for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+ mPendingAnimations.get(i).mTask.setCanAffectSystemUiFlags(behindSystemBars);
+ }
+ mService.mWindowPlacerLocked.requestTraversal();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
public void setInputConsumerEnabled(boolean enabled) {
if (DEBUG) Log.d(TAG, "setInputConsumerEnabled(" + enabled + "): mCanceled="
+ mCanceled);
@@ -175,7 +196,7 @@
* because it may call cancelAnimation() which needs to properly clean up the controller
* in the window manager.
*/
- public void initialize() {
+ public void initialize(SparseBooleanArray recentTaskIds) {
// Make leashes for each of the visible tasks and add it to the recents animation to be
// started
final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId);
@@ -189,7 +210,7 @@
|| config.getActivityType() == ACTIVITY_TYPE_HOME) {
continue;
}
- addAnimation(task);
+ addAnimation(task, !recentTaskIds.get(task.mTaskId));
}
// Skip the animation if there is nothing to animate
@@ -216,11 +237,12 @@
mService.mWindowPlacerLocked.performSurfacePlacement();
}
- private void addAnimation(Task task) {
+ private void addAnimation(Task task, boolean isRecentTaskInvisible) {
if (DEBUG) Log.d(TAG, "addAnimation(" + task.getName() + ")");
final SurfaceAnimator anim = new SurfaceAnimator(task, null /* animationFinishedCallback */,
mService);
- final TaskAnimationAdapter taskAdapter = new TaskAnimationAdapter(task);
+ final TaskAnimationAdapter taskAdapter = new TaskAnimationAdapter(task,
+ isRecentTaskInvisible);
anim.startAnimation(task.getPendingTransaction(), taskAdapter, false /* hidden */);
task.commitPendingTransaction();
mPendingAnimations.add(taskAdapter);
@@ -234,11 +256,16 @@
return;
}
try {
- final RemoteAnimationTarget[] appAnimations =
- new RemoteAnimationTarget[mPendingAnimations.size()];
+ final ArrayList<RemoteAnimationTarget> appAnimations = new ArrayList<>();
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
- appAnimations[i] = mPendingAnimations.get(i).createRemoteAnimationApp();
+ final RemoteAnimationTarget target =
+ mPendingAnimations.get(i).createRemoteAnimationApp();
+ if (target != null) {
+ appAnimations.add(target);
+ }
}
+ final RemoteAnimationTarget[] appTargets = appAnimations.toArray(
+ new RemoteAnimationTarget[appAnimations.size()]);
mPendingStart = false;
final Rect minimizedHomeBounds =
@@ -247,7 +274,7 @@
final Rect contentInsets =
mHomeAppToken != null && mHomeAppToken.findMainWindow() != null
? mHomeAppToken.findMainWindow().mContentInsets : null;
- mRunner.onAnimationStart_New(mController, appAnimations, contentInsets,
+ mRunner.onAnimationStart_New(mController, appTargets, contentInsets,
minimizedHomeBounds);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to start recents animation", e);
@@ -278,6 +305,7 @@
+ mPendingAnimations.size());
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
final TaskAnimationAdapter adapter = mPendingAnimations.get(i);
+ adapter.mTask.setCanAffectSystemUiFlags(true);
adapter.mCapturedFinishCallback.onAnimationFinished(adapter);
}
mPendingAnimations.clear();
@@ -343,12 +371,15 @@
private class TaskAnimationAdapter implements AnimationAdapter {
- private Task mTask;
+ private final Task mTask;
private SurfaceControl mCapturedLeash;
private OnAnimationFinishedCallback mCapturedFinishCallback;
+ private final boolean mIsRecentTaskInvisible;
+ private RemoteAnimationTarget mTarget;
- TaskAnimationAdapter(Task task) {
+ TaskAnimationAdapter(Task task, boolean isRecentTaskInvisible) {
mTask = task;
+ mIsRecentTaskInvisible = isRecentTaskInvisible;
}
RemoteAnimationTarget createRemoteAnimationApp() {
@@ -358,10 +389,14 @@
container.getRelativePosition(position);
container.getBounds(bounds);
final WindowState mainWindow = mTask.getTopVisibleAppMainWindow();
- return new RemoteAnimationTarget(mTask.mTaskId, MODE_CLOSING, mCapturedLeash,
+ if (mainWindow == null) {
+ return null;
+ }
+ mTarget = new RemoteAnimationTarget(mTask.mTaskId, MODE_CLOSING, mCapturedLeash,
!mTask.fillsParent(), mainWindow.mWinAnimator.mLastClipRect,
mainWindow.mContentInsets, mTask.getPrefixOrderIndex(), position, bounds,
- mTask.getWindowConfiguration());
+ mTask.getWindowConfiguration(), mIsRecentTaskInvisible);
+ return mTarget;
}
@Override
@@ -400,6 +435,26 @@
public long getStatusBarTransitionsStartTime() {
return SystemClock.uptimeMillis();
}
+
+ @Override
+ public void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.println("task=" + mTask);
+ if (mTarget != null) {
+ pw.print(prefix); pw.println("Target:");
+ mTarget.dump(pw, prefix + " ");
+ } else {
+ pw.print(prefix); pw.println("Target: null");
+ }
+ }
+
+ @Override
+ public void writeToProto(ProtoOutputStream proto) {
+ final long token = proto.start(REMOTE);
+ if (mTarget != null) {
+ mTarget.writeToProto(proto, TARGET);
+ }
+ proto.end(token);
+ }
}
public void dump(PrintWriter pw, String prefix) {
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index ed6e606..d645110 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -16,8 +16,11 @@
package com.android.server.wm;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.proto.AnimationAdapterProto.REMOTE;
+import static com.android.server.wm.proto.RemoteAnimationAdapterWrapperProto.TARGET;
import android.graphics.Point;
import android.graphics.Rect;
@@ -25,16 +28,18 @@
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import android.view.IRemoteAnimationFinishedCallback;
-import android.view.IRemoteAnimationFinishedCallback.Stub;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
+import com.android.internal.util.FastPrintWriter;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
-import java.lang.ref.WeakReference;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.ArrayList;
/**
@@ -103,6 +108,21 @@
onAnimationFinished();
}
});
+ sendRunningRemoteAnimation(true);
+ if (DEBUG_APP_TRANSITIONS) {
+ writeStartDebugStatement();
+ }
+ }
+
+ private void writeStartDebugStatement() {
+ Slog.i(TAG, "Starting remote animation");
+ final StringWriter sw = new StringWriter();
+ final FastPrintWriter pw = new FastPrintWriter(sw);
+ for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+ mPendingAnimations.get(i).dump(pw, "");
+ }
+ pw.close();
+ Slog.i(TAG, sw.toString());
}
private RemoteAnimationTarget[] createAnimations() {
@@ -131,6 +151,8 @@
mService.closeSurfaceTransaction("RemoteAnimationController#finished");
}
}
+ sendRunningRemoteAnimation(false);
+ if (DEBUG_APP_TRANSITIONS) Slog.i(TAG, "Finishing remote animation");
}
private void invokeAnimationCancelled() {
@@ -148,6 +170,14 @@
}
}
+ private void sendRunningRemoteAnimation(boolean running) {
+ final int pid = mRemoteAnimationAdapter.getCallingPid();
+ if (pid == 0) {
+ throw new RuntimeException("Calling pid of remote animation was null");
+ }
+ mService.sendSetRunningRemoteAnimation(pid, running);
+ }
+
private static final class FinishedCallback extends IRemoteAnimationFinishedCallback.Stub {
RemoteAnimationController mOuter;
@@ -183,6 +213,7 @@
private OnAnimationFinishedCallback mCapturedFinishCallback;
private final Point mPosition = new Point();
private final Rect mStackBounds = new Rect();
+ private RemoteAnimationTarget mTarget;
RemoteAnimationAdapterWrapper(AppWindowToken appWindowToken, Point position,
Rect stackBounds) {
@@ -200,11 +231,12 @@
if (mainWindow == null) {
return null;
}
- return new RemoteAnimationTarget(task.mTaskId, getMode(),
+ mTarget = new RemoteAnimationTarget(task.mTaskId, getMode(),
mCapturedLeash, !mAppWindowToken.fillsParent(),
mainWindow.mWinAnimator.mLastClipRect, mainWindow.mContentInsets,
mAppWindowToken.getPrefixOrderIndex(), mPosition, mStackBounds,
- task.getWindowConfiguration());
+ task.getWindowConfiguration(), false /*isNotInRecents*/);
+ return mTarget;
}
private int getMode() {
@@ -251,6 +283,7 @@
mHandler.removeCallbacks(mTimeoutRunnable);
releaseFinishedCallback();
invokeAnimationCancelled();
+ sendRunningRemoteAnimation(false);
}
}
@@ -264,5 +297,25 @@
return SystemClock.uptimeMillis()
+ mRemoteAnimationAdapter.getStatusBarTransitionDelay();
}
+
+ @Override
+ public void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.print("token="); pw.println(mAppWindowToken);
+ if (mTarget != null) {
+ pw.print(prefix); pw.println("Target:");
+ mTarget.dump(pw, prefix + " ");
+ } else {
+ pw.print(prefix); pw.println("Target: null");
+ }
+ }
+
+ @Override
+ public void writeToProto(ProtoOutputStream proto) {
+ final long token = proto.start(REMOTE);
+ if (mTarget != null) {
+ mTarget.writeToProto(proto, TARGET);
+ }
+ proto.end(token);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index 76f5396..c06caaf 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -313,7 +313,9 @@
*/
void writeToProto(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
- proto.write(ANIMATION_ADAPTER, mAnimation != null ? mAnimation.toString() : "null");
+ if (mAnimation != null) {
+ mAnimation.writeToProto(proto, ANIMATION_ADAPTER);
+ }
if (mLeash != null){
mLeash.writeToProto(proto, LEASH);
}
@@ -322,8 +324,18 @@
}
void dump(PrintWriter pw, String prefix) {
- pw.print(prefix); pw.print("mAnimation="); pw.print(mAnimation);
- pw.print(" mLeash="); pw.println(mLeash);
+ pw.print(prefix); pw.print("mLeash="); pw.print(mLeash);
+ if (mAnimationStartDelayed) {
+ pw.print(" mAnimationStartDelayed="); pw.println(mAnimationStartDelayed);
+ } else {
+ pw.println();
+ }
+ pw.print(prefix); pw.println("Animation:");
+ if (mAnimation != null) {
+ mAnimation.dump(pw, prefix + " ");
+ } else {
+ pw.print(prefix); pw.println("null");
+ }
}
/**
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 2e86351..a403e6f2 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -96,6 +96,9 @@
private Dimmer mDimmer = new Dimmer(this);
private final Rect mTmpDimBoundsRect = new Rect();
+ /** @see #setCanAffectSystemUiFlags */
+ private boolean mCanAffectSystemUiFlags = true;
+
Task(int taskId, TaskStack stack, int userId, WindowManagerService service, int resizeMode,
boolean supportsPictureInPicture, TaskDescription taskDescription,
TaskWindowContainerController controller) {
@@ -627,6 +630,21 @@
callback.accept(this);
}
+ /**
+ * @param canAffectSystemUiFlags If false, all windows in this task can not affect SystemUI
+ * flags. See {@link WindowState#canAffectSystemUiFlags()}.
+ */
+ void setCanAffectSystemUiFlags(boolean canAffectSystemUiFlags) {
+ mCanAffectSystemUiFlags = canAffectSystemUiFlags;
+ }
+
+ /**
+ * @see #setCanAffectSystemUiFlags
+ */
+ boolean canAffectSystemUiFlags() {
+ return mCanAffectSystemUiFlags;
+ }
+
@Override
public String toString() {
return "{taskId=" + mTaskId + " appTokens=" + mChildren + " mdr=" + mDeferRemoval + "}";
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index a5a1ca5..9310dc4 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -273,7 +273,8 @@
}
return new TaskSnapshot(buffer, top.getConfiguration().orientation,
getInsetsFromTaskBounds(mainWindow, task),
- isLowRamDevice /* reduced */, scaleFraction /* scale */);
+ isLowRamDevice /* reduced */, scaleFraction /* scale */,
+ true /* isRealSnapshot */);
}
private boolean shouldDisableSnapshots() {
@@ -369,7 +370,8 @@
}
return new TaskSnapshot(hwBitmap.createGraphicBufferHandle(),
topChild.getConfiguration().orientation, mainWindow.mStableInsets,
- ActivityManager.isLowRamDeviceStatic() /* reduced */, 1.0f /* scale */);
+ ActivityManager.isLowRamDeviceStatic() /* reduced */, 1.0f /* scale */,
+ false /* isRealSnapshot */);
}
/**
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
index 537f317..31da5f3 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
@@ -89,7 +89,8 @@
}
return new TaskSnapshot(buffer, proto.orientation,
new Rect(proto.insetLeft, proto.insetTop, proto.insetRight, proto.insetBottom),
- reducedResolution, reducedResolution ? REDUCED_SCALE : 1f);
+ reducedResolution, reducedResolution ? REDUCED_SCALE : 1f,
+ proto.isRealSnapshot);
} catch (IOException e) {
Slog.w(TAG, "Unable to load task snapshot data for taskId=" + taskId);
return null;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 621bee7..086fffa 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -318,6 +318,7 @@
proto.insetTop = mSnapshot.getContentInsets().top;
proto.insetRight = mSnapshot.getContentInsets().right;
proto.insetBottom = mSnapshot.getContentInsets().bottom;
+ proto.isRealSnapshot = mSnapshot.isRealSnapshot();
final byte[] bytes = TaskSnapshotProto.toByteArray(proto);
final File file = getProtoFile(mTaskId, mUserId);
final AtomicFile atomicFile = new AtomicFile(file);
diff --git a/services/core/java/com/android/server/wm/WindowAnimationSpec.java b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
index 43fa3d5..a41eba8 100644
--- a/services/core/java/com/android/server/wm/WindowAnimationSpec.java
+++ b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
@@ -19,10 +19,13 @@
import static com.android.server.wm.AnimationAdapter.STATUS_BAR_TRANSITION_DURATION;
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
+import static com.android.server.wm.proto.AnimationSpecProto.WINDOW;
+import static com.android.server.wm.proto.WindowAnimationSpecProto.ANIMATION;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.SystemClock;
+import android.util.proto.ProtoOutputStream;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.animation.Animation;
@@ -33,6 +36,8 @@
import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
+import java.io.PrintWriter;
+
/**
* Animation spec for regular window animations.
*/
@@ -129,6 +134,18 @@
return mCanSkipFirstFrame;
}
+ @Override
+ public void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.println(mAnimation);
+ }
+
+ @Override
+ public void writeToProtoInner(ProtoOutputStream proto) {
+ final long token = proto.start(WINDOW);
+ proto.write(ANIMATION, mAnimation.toString());
+ proto.end(token);
+ }
+
/**
* Tries to find a {@link TranslateAnimation} inside the {@code animation}.
*
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b44d8a9..82fbb51 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -181,6 +181,7 @@
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.TimeUtils;
import android.util.TypedValue;
@@ -1437,7 +1438,9 @@
final DisplayFrames displayFrames = displayContent.mDisplayFrames;
// TODO: Not sure if onDisplayInfoUpdated() call is needed.
- displayFrames.onDisplayInfoUpdated(displayContent.getDisplayInfo());
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+ displayFrames.onDisplayInfoUpdated(displayInfo,
+ displayContent.calculateDisplayCutoutForRotation(displayInfo.rotation));
final Rect taskBounds;
if (atoken != null && atoken.getTask() != null) {
taskBounds = mTmpRect;
@@ -2096,7 +2099,7 @@
win.mLastRelayoutContentInsets.set(win.mContentInsets);
outVisibleInsets.set(win.mVisibleInsets);
outStableInsets.set(win.mStableInsets);
- outCutout.set(win.mDisplayCutout);
+ outCutout.set(win.mDisplayCutout.getDisplayCutout());
outOutsets.set(win.mOutsets);
outBackdropFrame.set(win.getBackdropFrame(win.mFrame));
if (localLOGV) Slog.v(
@@ -2660,11 +2663,12 @@
public void initializeRecentsAnimation(
IRecentsAnimationRunner recentsAnimationRunner,
- RecentsAnimationController.RecentsAnimationCallbacks callbacks, int displayId) {
+ RecentsAnimationController.RecentsAnimationCallbacks callbacks, int displayId,
+ SparseBooleanArray recentTaskIds) {
synchronized (mWindowMap) {
mRecentsAnimationController = new RecentsAnimationController(this,
recentsAnimationRunner, callbacks, displayId);
- mRecentsAnimationController.initialize();
+ mRecentsAnimationController.initialize(recentTaskIds);
}
}
@@ -3178,6 +3182,12 @@
// Called by window manager policy. Not exposed externally.
@Override
+ public void switchKeyboardLayout(int deviceId, int direction) {
+ mInputManager.switchKeyboardLayout(deviceId, direction);
+ }
+
+ // Called by window manager policy. Not exposed externally.
+ @Override
public void switchInputMethod(boolean forwardDirection) {
final InputMethodManagerInternal inputMethodManagerInternal =
LocalServices.getService(InputMethodManagerInternal.class);
@@ -4555,6 +4565,7 @@
public static final int NOTIFY_KEYGUARD_FLAGS_CHANGED = 56;
public static final int NOTIFY_KEYGUARD_TRUSTED_CHANGED = 57;
public static final int SET_HAS_OVERLAY_UI = 58;
+ public static final int SET_RUNNING_REMOTE_ANIMATION = 59;
/**
* Used to denote that an integer field in a message will not be used.
@@ -4969,6 +4980,10 @@
mAmInternal.setHasOverlayUi(msg.arg1, msg.arg2 == 1);
}
break;
+ case SET_RUNNING_REMOTE_ANIMATION: {
+ mAmInternal.setRunningRemoteAnimation(msg.arg1, msg.arg2 == 1);
+ }
+ break;
}
if (DEBUG_WINDOW_TRACE) {
Slog.v(TAG_WM, "handleMessage: exit");
@@ -7418,5 +7433,24 @@
SurfaceControl.Builder makeSurfaceBuilder(SurfaceSession s) {
return mSurfaceBuilderFactory.make(s);
}
-}
+ void sendSetRunningRemoteAnimation(int pid, boolean runningRemoteAnimation) {
+ mH.obtainMessage(H.SET_RUNNING_REMOTE_ANIMATION, pid, runningRemoteAnimation ? 1 : 0)
+ .sendToTarget();
+ }
+
+ /**
+ * Called when the state of lock task mode changes. This should be used to disable immersive
+ * mode confirmation.
+ *
+ * @param lockTaskState the new lock task mode state. One of
+ * {@link ActivityManager#LOCK_TASK_MODE_NONE},
+ * {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
+ * {@link ActivityManager#LOCK_TASK_MODE_PINNED}.
+ */
+ public void onLockTaskStateChanged(int lockTaskState) {
+ synchronized (mWindowMap) {
+ mPolicy.onLockTaskStateChangedLw(lockTaskState);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c4185fa..68bb530 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -113,6 +113,10 @@
import static com.android.server.wm.proto.IdentifierProto.HASH_CODE;
import static com.android.server.wm.proto.IdentifierProto.TITLE;
import static com.android.server.wm.proto.IdentifierProto.USER_ID;
+import static com.android.server.wm.proto.AnimationSpecProto.MOVE;
+import static com.android.server.wm.proto.MoveAnimationSpecProto.DURATION;
+import static com.android.server.wm.proto.MoveAnimationSpecProto.FROM;
+import static com.android.server.wm.proto.MoveAnimationSpecProto.TO;
import static com.android.server.wm.proto.WindowStateProto.ANIMATING_EXIT;
import static com.android.server.wm.proto.WindowStateProto.ANIMATOR;
import static com.android.server.wm.proto.WindowStateProto.ATTRIBUTES;
@@ -202,6 +206,7 @@
import com.android.server.input.InputWindowHandle;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
+import com.android.server.wm.utils.WmDisplayCutout;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
@@ -351,8 +356,8 @@
private boolean mOutsetsChanged = false;
/** Part of the display that has been cut away. See {@link DisplayCutout}. */
- DisplayCutout mDisplayCutout = DisplayCutout.NO_CUTOUT;
- private DisplayCutout mLastDisplayCutout = DisplayCutout.NO_CUTOUT;
+ WmDisplayCutout mDisplayCutout = WmDisplayCutout.NO_CUTOUT;
+ private WmDisplayCutout mLastDisplayCutout = WmDisplayCutout.NO_CUTOUT;
private boolean mDisplayCutoutChanged;
/**
@@ -693,6 +698,7 @@
mOwnerCanAddInternalSystemWindow = ownerCanAddInternalSystemWindow;
mWindowId = new WindowId(this);
mAttrs.copyFrom(a);
+ mLastSurfaceInsets.set(mAttrs.surfaceInsets);
mViewVisibility = viewVisibility;
mPolicy = mService.mPolicy;
mContext = mService.mContext;
@@ -833,7 +839,7 @@
@Override
public void computeFrameLw(Rect parentFrame, Rect displayFrame, Rect overscanFrame,
Rect contentFrame, Rect visibleFrame, Rect decorFrame, Rect stableFrame,
- Rect outsetFrame, DisplayCutout displayCutout) {
+ Rect outsetFrame, WmDisplayCutout displayCutout) {
if (mWillReplaceWindow && (mAnimatingExit || !mReplacingRemoveRequested)) {
// This window is being replaced and either already got information that it's being
// removed or we are still waiting for some information. Because of this we don't
@@ -1567,7 +1573,9 @@
final boolean exiting = mAnimatingExit || mDestroying;
return shown && !exiting;
} else {
- return !mAppToken.isHidden();
+ final Task task = getTask();
+ final boolean canFromTask = task != null && task.canAffectSystemUiFlags();
+ return canFromTask && !mAppToken.isHidden();
}
}
@@ -2914,7 +2922,7 @@
final boolean reportDraw = mWinAnimator.mDrawState == DRAW_PENDING;
final boolean reportOrientation = mReportOrientationChanged;
final int displayId = getDisplayId();
- final DisplayCutout displayCutout = mDisplayCutout;
+ final DisplayCutout displayCutout = mDisplayCutout.getDisplayCutout();
if (mAttrs.type != WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
&& mClient instanceof IWindow.Stub) {
// To prevent deadlock simulate one-way call if win.mClient is a local object.
@@ -3186,7 +3194,7 @@
mVisibleInsets.writeToProto(proto, VISIBLE_INSETS);
mStableInsets.writeToProto(proto, STABLE_INSETS);
mOutsets.writeToProto(proto, OUTSETS);
- mDisplayCutout.writeToProto(proto, CUTOUT);
+ mDisplayCutout.getDisplayCutout().writeToProto(proto, CUTOUT);
proto.write(REMOVE_ON_EXIT, mRemoveOnExit);
proto.write(DESTROYING, mDestroying);
proto.write(REMOVED, mRemoved);
@@ -3332,7 +3340,7 @@
pw.print(" stable="); mStableInsets.printShortString(pw);
pw.print(" surface="); mAttrs.surfaceInsets.printShortString(pw);
pw.print(" outsets="); mOutsets.printShortString(pw);
- pw.print(" cutout=" + mDisplayCutout);
+ pw.print(" cutout=" + mDisplayCutout.getDisplayCutout());
pw.println();
pw.print(prefix); pw.print("Lst insets: overscan=");
mLastOverscanInsets.printShortString(pw);
@@ -4722,5 +4730,21 @@
t.setPosition(leash, mFrom.x + (mTo.x - mFrom.x) * v,
mFrom.y + (mTo.y - mFrom.y) * v);
}
+
+ @Override
+ public void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.print("from="); pw.print(mFrom);
+ pw.print(" to="); pw.print(mTo);
+ pw.print(" duration="); pw.println(mDuration);
+ }
+
+ @Override
+ public void writeToProtoInner(ProtoOutputStream proto) {
+ final long token = proto.start(MOVE);
+ mFrom.writeToProto(proto, FROM);
+ mTo.writeToProto(proto, TO);
+ proto.write(DURATION, mDuration);
+ proto.end(token);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 4179590..40ee552 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -559,7 +559,8 @@
+ wtoken.allDrawn + " startingDisplayed="
+ wtoken.startingDisplayed + " startingMoved="
+ wtoken.startingMoved + " isRelaunching()="
- + wtoken.isRelaunching());
+ + wtoken.isRelaunching() + " startingWindow="
+ + wtoken.startingWindow);
final boolean allDrawn = wtoken.allDrawn && !wtoken.isRelaunching();
diff --git a/services/core/java/com/android/server/wm/utils/WmDisplayCutout.java b/services/core/java/com/android/server/wm/utils/WmDisplayCutout.java
new file mode 100644
index 0000000..ea3f758
--- /dev/null
+++ b/services/core/java/com/android/server/wm/utils/WmDisplayCutout.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.utils;
+
+import android.graphics.Rect;
+import android.util.Size;
+import android.view.DisplayCutout;
+import android.view.Gravity;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Wrapper for DisplayCutout that also tracks the display size and using this allows (re)calculating
+ * safe insets.
+ */
+public class WmDisplayCutout {
+
+ public static final WmDisplayCutout NO_CUTOUT = new WmDisplayCutout(DisplayCutout.NO_CUTOUT,
+ null);
+
+ private final DisplayCutout mInner;
+ private final Size mFrameSize;
+
+ public WmDisplayCutout(DisplayCutout inner, Size frameSize) {
+ mInner = inner;
+ mFrameSize = frameSize;
+ }
+
+ public static WmDisplayCutout computeSafeInsets(DisplayCutout inner,
+ int displayWidth, int displayHeight) {
+ if (inner == DisplayCutout.NO_CUTOUT || inner.isBoundsEmpty()) {
+ return NO_CUTOUT;
+ }
+
+ final Size displaySize = new Size(displayWidth, displayHeight);
+ final Rect safeInsets = computeSafeInsets(displaySize, inner);
+ return new WmDisplayCutout(inner.replaceSafeInsets(safeInsets), displaySize);
+ }
+
+ /**
+ * Insets the reference frame of the cutout in the given directions.
+ *
+ * @return a copy of this instance which has been inset
+ * @hide
+ */
+ public WmDisplayCutout inset(int insetLeft, int insetTop, int insetRight, int insetBottom) {
+ DisplayCutout newInner = mInner.inset(insetLeft, insetTop, insetRight, insetBottom);
+
+ if (mInner == newInner) {
+ return this;
+ }
+
+ Size frame = mFrameSize == null ? null : new Size(
+ mFrameSize.getWidth() - insetLeft - insetRight,
+ mFrameSize.getHeight() - insetTop - insetBottom);
+
+ return new WmDisplayCutout(newInner, frame);
+ }
+
+ /**
+ * Recalculates the cutout relative to the given reference frame.
+ *
+ * The safe insets must already have been computed, e.g. with {@link #computeSafeInsets}.
+ *
+ * @return a copy of this instance with the safe insets recalculated
+ * @hide
+ */
+ public WmDisplayCutout calculateRelativeTo(Rect frame) {
+ if (mInner.isEmpty()) {
+ return this;
+ }
+ return inset(frame.left, frame.top,
+ mFrameSize.getWidth() - frame.right, mFrameSize.getHeight() - frame.bottom);
+ }
+
+ /**
+ * Calculates the safe insets relative to the given display size.
+ *
+ * @return a copy of this instance with the safe insets calculated
+ * @hide
+ */
+ public WmDisplayCutout computeSafeInsets(int width, int height) {
+ return computeSafeInsets(mInner, width, height);
+ }
+
+ private static Rect computeSafeInsets(Size displaySize, DisplayCutout cutout) {
+ if (displaySize.getWidth() < displaySize.getHeight()) {
+ final List<Rect> boundingRects = cutout.replaceSafeInsets(
+ new Rect(0, displaySize.getHeight() / 2, 0, displaySize.getHeight() / 2))
+ .getBoundingRects();
+ int topInset = findInsetForSide(displaySize, boundingRects, Gravity.TOP);
+ int bottomInset = findInsetForSide(displaySize, boundingRects, Gravity.BOTTOM);
+ return new Rect(0, topInset, 0, bottomInset);
+ } else if (displaySize.getWidth() > displaySize.getHeight()) {
+ final List<Rect> boundingRects = cutout.replaceSafeInsets(
+ new Rect(displaySize.getWidth() / 2, 0, displaySize.getWidth() / 2, 0))
+ .getBoundingRects();
+ int leftInset = findInsetForSide(displaySize, boundingRects, Gravity.LEFT);
+ int right = findInsetForSide(displaySize, boundingRects, Gravity.RIGHT);
+ return new Rect(leftInset, 0, right, 0);
+ } else {
+ throw new UnsupportedOperationException("not implemented: display=" + displaySize +
+ " cutout=" + cutout);
+ }
+ }
+
+ private static int findInsetForSide(Size display, List<Rect> boundingRects, int gravity) {
+ int inset = 0;
+ final int size = boundingRects.size();
+ for (int i = 0; i < size; i++) {
+ Rect boundingRect = boundingRects.get(i);
+ switch (gravity) {
+ case Gravity.TOP:
+ if (boundingRect.top == 0) {
+ inset = Math.max(inset, boundingRect.bottom);
+ }
+ break;
+ case Gravity.BOTTOM:
+ if (boundingRect.bottom == display.getHeight()) {
+ inset = Math.max(inset, display.getHeight() - boundingRect.top);
+ }
+ break;
+ case Gravity.LEFT:
+ if (boundingRect.left == 0) {
+ inset = Math.max(inset, boundingRect.right);
+ }
+ break;
+ case Gravity.RIGHT:
+ if (boundingRect.right == display.getWidth()) {
+ inset = Math.max(inset, display.getWidth() - boundingRect.left);
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("unknown gravity: " + gravity);
+ }
+ }
+ return inset;
+ }
+
+ public DisplayCutout getDisplayCutout() {
+ return mInner;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof WmDisplayCutout)) {
+ return false;
+ }
+ WmDisplayCutout that = (WmDisplayCutout) o;
+ return Objects.equals(mInner, that.mInner) &&
+ Objects.equals(mFrameSize, that.mFrameSize);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mInner, mFrameSize);
+ }
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java
index 0aaf32c..0967652 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java
@@ -30,6 +30,7 @@
import android.util.Slog;
import com.android.server.ServiceThread;
+import com.android.server.net.BaseNetdEventCallback;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -50,7 +51,7 @@
private ServiceThread mHandlerThread;
private NetworkLoggingHandler mNetworkLoggingHandler;
- private final INetdEventCallback mNetdEventCallback = new INetdEventCallback.Stub() {
+ private final INetdEventCallback mNetdEventCallback = new BaseNetdEventCallback() {
@Override
public void onDnsEvent(String hostname, String[] ipAddresses, int ipAddressesCount,
long timestamp, int uid) {
diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk
index aed57e3..3d7fdbdd 100644
--- a/services/robotests/Android.mk
+++ b/services/robotests/Android.mk
@@ -62,7 +62,8 @@
$(call all-java-files-under, ../../core/java/android/app/backup) \
$(call all-Iaidl-files-under, ../../core/java/android/app/backup) \
../../core/java/android/content/pm/PackageInfo.java \
- ../../core/java/android/app/IBackupAgent.aidl
+ ../../core/java/android/app/IBackupAgent.aidl \
+ ../../core/java/android/util/KeyValueSettingObserver.java
LOCAL_AIDL_INCLUDES := \
$(call all-Iaidl-files-under, $(INTERNAL_BACKUP)) \
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java b/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
index 0752537..2a32c2e 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
@@ -18,79 +18,218 @@
import static com.google.common.truth.Truth.assertThat;
-import android.app.AlarmManager;
+import android.content.ContentResolver;
import android.content.Context;
import android.os.Handler;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
-
+import android.util.KeyValueSettingObserver;
import com.android.server.testing.FrameworkRobolectricTestRunner;
import com.android.server.testing.SystemLoaderClasses;
import com.android.server.testing.SystemLoaderPackages;
-
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(FrameworkRobolectricTestRunner.class)
@Config(manifest = Config.NONE, sdk = 26)
@SystemLoaderPackages({"com.android.server.backup"})
+@SystemLoaderClasses({KeyValueSettingObserver.class})
@Presubmit
public class BackupManagerConstantsTest {
private static final String PACKAGE_NAME = "some.package.name";
private static final String ANOTHER_PACKAGE_NAME = "another.package.name";
+ private ContentResolver mContentResolver;
+ private BackupManagerConstants mConstants;
+
@Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
+ public void setUp() {
+ final Context context = RuntimeEnvironment.application.getApplicationContext();
+
+ mContentResolver = context.getContentResolver();
+ mConstants = new BackupManagerConstants(new Handler(), mContentResolver);
+ mConstants.start();
+ }
+
+ @After
+ public void tearDown() {
+ mConstants.stop();
}
@Test
- public void testDefaultValues() throws Exception {
- final Context context = RuntimeEnvironment.application.getApplicationContext();
- final Handler handler = new Handler();
+ public void testGetConstants_afterConstructorWithStart_returnsDefaultValues() {
+ long keyValueBackupIntervalMilliseconds =
+ mConstants.getKeyValueBackupIntervalMilliseconds();
+ long keyValueBackupFuzzMilliseconds = mConstants.getKeyValueBackupFuzzMilliseconds();
+ boolean keyValueBackupRequireCharging = mConstants.getKeyValueBackupRequireCharging();
+ int keyValueBackupRequiredNetworkType = mConstants.getKeyValueBackupRequiredNetworkType();
+ long fullBackupIntervalMilliseconds = mConstants.getFullBackupIntervalMilliseconds();
+ boolean fullBackupRequireCharging = mConstants.getFullBackupRequireCharging();
+ int fullBackupRequiredNetworkType = mConstants.getFullBackupRequiredNetworkType();
+ String[] backupFinishedNotificationReceivers =
+ mConstants.getBackupFinishedNotificationReceivers();
- Settings.Secure.putString(
- context.getContentResolver(), Settings.Secure.BACKUP_MANAGER_CONSTANTS, null);
+ assertThat(keyValueBackupIntervalMilliseconds)
+ .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS);
+ assertThat(keyValueBackupFuzzMilliseconds)
+ .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS);
+ assertThat(keyValueBackupRequireCharging)
+ .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_REQUIRE_CHARGING);
+ assertThat(keyValueBackupRequiredNetworkType)
+ .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE);
+ assertThat(fullBackupIntervalMilliseconds)
+ .isEqualTo(BackupManagerConstants.DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS);
+ assertThat(fullBackupRequireCharging)
+ .isEqualTo(BackupManagerConstants.DEFAULT_FULL_BACKUP_REQUIRE_CHARGING);
+ assertThat(fullBackupRequiredNetworkType)
+ .isEqualTo(BackupManagerConstants.DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE);
+ assertThat(backupFinishedNotificationReceivers).isEqualTo(new String[0]);
+ }
- final BackupManagerConstants constants =
- new BackupManagerConstants(handler, context.getContentResolver());
+ /**
+ * Tests that if there is a setting change when we are not currently observing the setting, that
+ * once we start observing again, we receive the most up-to-date value.
+ */
+ @Test
+ public void testGetConstant_withSettingChangeBeforeStart_updatesValues() {
+ mConstants.stop();
+ long testInterval =
+ BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS * 2;
+ final String setting =
+ BackupManagerConstants.KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS + "=" + testInterval;
+ putStringAndNotify(setting);
- assertThat(constants.getKeyValueBackupIntervalMilliseconds())
- .isEqualTo(4 * AlarmManager.INTERVAL_HOUR);
- assertThat(constants.getKeyValueBackupFuzzMilliseconds()).isEqualTo(10 * 60 * 1000);
- assertThat(constants.getKeyValueBackupRequireCharging()).isEqualTo(true);
- assertThat(constants.getKeyValueBackupRequiredNetworkType()).isEqualTo(1);
+ mConstants.start();
- assertThat(constants.getFullBackupIntervalMilliseconds())
- .isEqualTo(24 * AlarmManager.INTERVAL_HOUR);
- assertThat(constants.getFullBackupRequireCharging()).isEqualTo(true);
- assertThat(constants.getFullBackupRequiredNetworkType()).isEqualTo(2);
- assertThat(constants.getBackupFinishedNotificationReceivers()).isEqualTo(new String[0]);
+ long keyValueBackupIntervalMilliseconds =
+ mConstants.getKeyValueBackupIntervalMilliseconds();
+ assertThat(keyValueBackupIntervalMilliseconds).isEqualTo(testInterval);
}
@Test
- public void testParseNotificationReceivers() throws Exception {
- final Context context = RuntimeEnvironment.application.getApplicationContext();
- final Handler handler = new Handler();
+ public void testGetConstants_whenSettingIsNull_returnsDefaultValues() {
+ putStringAndNotify(null);
- final String recieversSetting =
- "backup_finished_notification_receivers="
+ long keyValueBackupIntervalMilliseconds =
+ mConstants.getKeyValueBackupIntervalMilliseconds();
+ long keyValueBackupFuzzMilliseconds = mConstants.getKeyValueBackupFuzzMilliseconds();
+ boolean keyValueBackupRequireCharging = mConstants.getKeyValueBackupRequireCharging();
+ int keyValueBackupRequiredNetworkType = mConstants.getKeyValueBackupRequiredNetworkType();
+ long fullBackupIntervalMilliseconds = mConstants.getFullBackupIntervalMilliseconds();
+ boolean fullBackupRequireCharging = mConstants.getFullBackupRequireCharging();
+ int fullBackupRequiredNetworkType = mConstants.getFullBackupRequiredNetworkType();
+ String[] backupFinishedNotificationReceivers =
+ mConstants.getBackupFinishedNotificationReceivers();
+
+ assertThat(keyValueBackupIntervalMilliseconds)
+ .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS);
+ assertThat(keyValueBackupFuzzMilliseconds)
+ .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS);
+ assertThat(keyValueBackupRequireCharging)
+ .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_REQUIRE_CHARGING);
+ assertThat(keyValueBackupRequiredNetworkType)
+ .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE);
+ assertThat(fullBackupIntervalMilliseconds)
+ .isEqualTo(BackupManagerConstants.DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS);
+ assertThat(fullBackupRequireCharging)
+ .isEqualTo(BackupManagerConstants.DEFAULT_FULL_BACKUP_REQUIRE_CHARGING);
+ assertThat(fullBackupRequiredNetworkType)
+ .isEqualTo(BackupManagerConstants.DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE);
+ assertThat(backupFinishedNotificationReceivers).isEqualTo(new String[0]);
+ }
+
+ /**
+ * Test passing in a malformed setting string. The setting expects
+ * "key1=value,key2=value,key3=value..." but we pass in "key1=,value"
+ */
+ @Test
+ public void testGetConstant_whenSettingIsMalformed_doesNotUpdateParamsOrThrow() {
+ long testFuzz = BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS * 2;
+ final String invalidSettingFormat =
+ BackupManagerConstants.KEY_VALUE_BACKUP_FUZZ_MILLISECONDS + "=," + testFuzz;
+ putStringAndNotify(invalidSettingFormat);
+
+ long keyValueBackupFuzzMilliseconds = mConstants.getKeyValueBackupFuzzMilliseconds();
+
+ assertThat(keyValueBackupFuzzMilliseconds)
+ .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS);
+ }
+
+ /**
+ * Test passing in an invalid value type. {@link
+ * BackupManagerConstants#KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE} expects an integer, but we
+ * pass in a boolean.
+ */
+ @Test
+ public void testGetConstant_whenSettingHasInvalidType_doesNotUpdateParamsOrThrow() {
+ boolean testValue = true;
+ final String invalidSettingType =
+ BackupManagerConstants.KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE + "=" + testValue;
+ putStringAndNotify(invalidSettingType);
+
+ int keyValueBackupRequiredNetworkType = mConstants.getKeyValueBackupRequiredNetworkType();
+
+ assertThat(keyValueBackupRequiredNetworkType)
+ .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE);
+ }
+
+ @Test
+ public void testGetConstants_afterSettingChange_updatesValues() {
+ long testKVInterval =
+ BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS * 2;
+ long testFullInterval =
+ BackupManagerConstants.DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS * 2;
+ final String intervalSetting =
+ BackupManagerConstants.KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS
+ + "="
+ + testKVInterval
+ + ","
+ + BackupManagerConstants.FULL_BACKUP_INTERVAL_MILLISECONDS
+ + "="
+ + testFullInterval;
+ putStringAndNotify(intervalSetting);
+
+ long keyValueBackupIntervalMilliseconds =
+ mConstants.getKeyValueBackupIntervalMilliseconds();
+ long fullBackupIntervalMilliseconds = mConstants.getFullBackupIntervalMilliseconds();
+
+ assertThat(keyValueBackupIntervalMilliseconds).isEqualTo(testKVInterval);
+ assertThat(fullBackupIntervalMilliseconds).isEqualTo(testFullInterval);
+ }
+
+ @Test
+ public void testBackupNotificationReceivers_afterSetting_updatesAndParsesCorrectly() {
+ final String receiversSetting =
+ BackupManagerConstants.BACKUP_FINISHED_NOTIFICATION_RECEIVERS
+ + "="
+ PACKAGE_NAME
+ ':'
+ ANOTHER_PACKAGE_NAME;
- Settings.Secure.putString(
- context.getContentResolver(),
- Settings.Secure.BACKUP_MANAGER_CONSTANTS,
- recieversSetting);
+ putStringAndNotify(receiversSetting);
- final BackupManagerConstants constants =
- new BackupManagerConstants(handler, context.getContentResolver());
-
- assertThat(constants.getBackupFinishedNotificationReceivers())
+ String[] backupFinishedNotificationReceivers =
+ mConstants.getBackupFinishedNotificationReceivers();
+ assertThat(backupFinishedNotificationReceivers)
.isEqualTo(new String[] {PACKAGE_NAME, ANOTHER_PACKAGE_NAME});
}
+
+ /**
+ * Robolectric does not notify observers of changes to settings so we have to trigger it here.
+ * Currently, the mock of {@link Settings.Secure#putString(ContentResolver, String, String)}
+ * only stores the value. TODO: Implement properly in ShadowSettings.
+ */
+ private void putStringAndNotify(String value) {
+ Settings.Secure.putString(
+ mContentResolver, Settings.Secure.BACKUP_MANAGER_CONSTANTS, value);
+
+ // We pass null as the observer since notifyChange iterates over all available observers and
+ // we don't have access to the local observer.
+ mContentResolver.notifyChange(
+ Settings.Secure.getUriFor(Settings.Secure.BACKUP_MANAGER_CONSTANTS),
+ /*observer*/ null);
+ }
}
diff --git a/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java b/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java
index 3d2d8af..bbec7af 100644
--- a/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java
+++ b/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java
@@ -60,7 +60,7 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
- mTransportClientManager = new TransportClientManager(mContext);
+ mTransportClientManager = new TransportClientManager(mContext, new TransportStats());
mTransportComponent = new ComponentName(PACKAGE_NAME, CLASS_NAME);
mBindIntent = new Intent(SERVICE_ACTION_TRANSPORT_HOST).setComponent(mTransportComponent);
diff --git a/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java b/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
index 5b65473..49ef581f 100644
--- a/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
+++ b/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
@@ -88,6 +88,7 @@
@Mock private TransportConnectionListener mTransportConnectionListener;
@Mock private TransportConnectionListener mTransportConnectionListener2;
@Mock private IBackupTransport.Stub mTransportBinder;
+ private TransportStats mTransportStats;
private TransportClient mTransportClient;
private ComponentName mTransportComponent;
private String mTransportString;
@@ -105,10 +106,12 @@
mTransportComponent =
new ComponentName(PACKAGE_NAME, PACKAGE_NAME + ".transport.Transport");
mTransportString = mTransportComponent.flattenToShortString();
+ mTransportStats = new TransportStats();
mBindIntent = new Intent(SERVICE_ACTION_TRANSPORT_HOST).setComponent(mTransportComponent);
mTransportClient =
new TransportClient(
mContext,
+ mTransportStats,
mBindIntent,
mTransportComponent,
"1",
diff --git a/services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java b/services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java
new file mode 100644
index 0000000..322db85c
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.transport;
+
+import static com.android.server.backup.testing.TransportData.backupTransport;
+import static com.android.server.backup.testing.TransportData.d2dTransport;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.ComponentName;
+import android.platform.test.annotations.Presubmit;
+
+import com.android.server.backup.transport.TransportStats.Stats;
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class TransportStatsTest {
+ private static final double TOLERANCE = 0.0001;
+
+ private TransportStats mTransportStats;
+ private ComponentName mTransportComponent1;
+ private ComponentName mTransportComponent2;
+
+ @Before
+ public void setUp() throws Exception {
+ mTransportStats = new TransportStats();
+ mTransportComponent1 = backupTransport().getTransportComponent();
+ mTransportComponent2 = d2dTransport().getTransportComponent();
+ }
+
+ @Test
+ public void testRegisterConnectionTime() {
+ mTransportStats.registerConnectionTime(mTransportComponent1, 50L);
+
+ Stats stats = mTransportStats.getStatsForTransport(mTransportComponent1);
+ assertThat(stats.average).isWithin(TOLERANCE).of(50);
+ assertThat(stats.max).isEqualTo(50L);
+ assertThat(stats.min).isEqualTo(50L);
+ assertThat(stats.n).isEqualTo(1);
+ }
+
+ @Test
+ public void testRegisterConnectionTime_whenHasAlreadyOneSample() {
+ mTransportStats.registerConnectionTime(mTransportComponent1, 50L);
+
+ mTransportStats.registerConnectionTime(mTransportComponent1, 100L);
+
+ Stats stats = mTransportStats.getStatsForTransport(mTransportComponent1);
+ assertThat(stats.average).isWithin(TOLERANCE).of(75);
+ assertThat(stats.max).isEqualTo(100L);
+ assertThat(stats.min).isEqualTo(50L);
+ assertThat(stats.n).isEqualTo(2);
+ }
+
+ @Test
+ public void testGetStatsForTransport() {
+ mTransportStats.registerConnectionTime(mTransportComponent1, 10L);
+ mTransportStats.registerConnectionTime(mTransportComponent2, 20L);
+
+ Stats stats = mTransportStats.getStatsForTransport(mTransportComponent1);
+
+ assertThat(stats.average).isWithin(TOLERANCE).of(10);
+ assertThat(stats.max).isEqualTo(10L);
+ assertThat(stats.min).isEqualTo(10L);
+ assertThat(stats.n).isEqualTo(1);
+ }
+
+ @Test
+ public void testMerge() {
+ mTransportStats.registerConnectionTime(mTransportComponent1, 10L);
+ mTransportStats.registerConnectionTime(mTransportComponent2, 20L);
+ Stats stats1 = mTransportStats.getStatsForTransport(mTransportComponent1);
+ Stats stats2 = mTransportStats.getStatsForTransport(mTransportComponent2);
+
+ Stats stats = Stats.merge(stats1, stats2);
+
+ assertThat(stats.average).isWithin(TOLERANCE).of(15);
+ assertThat(stats.max).isEqualTo(20L);
+ assertThat(stats.min).isEqualTo(10L);
+ assertThat(stats.n).isEqualTo(2);
+ }
+}
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 356e64b..0ca0a1a 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -15,6 +15,7 @@
frameworks-base-testutils \
services.accessibility \
services.appwidget \
+ services.autofill \
services.backup \
services.core \
services.devicepolicy \
diff --git a/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java b/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
index b62f1ce..5daacd7 100644
--- a/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
@@ -25,6 +25,7 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
@@ -729,8 +730,8 @@
private void assertNoCallbacks(Listener l) throws Exception {
waitUntilMainHandlerDrain();
verify(l, times(0)).updateAllJobs();
- verify(l, times(0)).updateJobsForUid(anyInt());
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -752,8 +753,8 @@
waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
- verify(l, times(0)).updateJobsForUid(anyInt());
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -766,8 +767,8 @@
waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
- verify(l, times(0)).updateJobsForUid(anyInt());
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(1)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -796,8 +797,8 @@
waitUntilMainHandlerDrain();
verify(l, times(0)).updateAllJobs();
- verify(l, times(0)).updateJobsForUid(anyInt());
- verify(l, times(1)).updateJobsForUidPackage(eq(UID_10_2), eq(PACKAGE_2));
+ verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
+ verify(l, times(1)).updateJobsForUidPackage(eq(UID_10_2), eq(PACKAGE_2), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -808,8 +809,8 @@
waitUntilMainHandlerDrain();
verify(l, times(0)).updateAllJobs();
- verify(l, times(0)).updateJobsForUid(anyInt());
- verify(l, times(1)).updateJobsForUidPackage(eq(UID_10_2), eq(PACKAGE_2));
+ verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
+ verify(l, times(1)).updateJobsForUidPackage(eq(UID_10_2), eq(PACKAGE_2), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -819,8 +820,8 @@
setAppOps(UID_10_2, PACKAGE_2, false);
verify(l, times(0)).updateAllJobs();
- verify(l, times(0)).updateJobsForUid(anyInt());
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -835,8 +836,8 @@
waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
- verify(l, times(0)).updateJobsForUid(anyInt());
- verify(l, times(1)).updateJobsForUidPackage(eq(UID_10_2), eq(PACKAGE_2));
+ verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
+ verify(l, times(1)).updateJobsForUidPackage(eq(UID_10_2), eq(PACKAGE_2), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -849,8 +850,8 @@
waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
- verify(l, times(0)).updateJobsForUid(anyInt());
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(1)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -864,8 +865,8 @@
waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
- verify(l, times(0)).updateJobsForUid(anyInt());
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -876,8 +877,8 @@
waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
- verify(l, times(0)).updateJobsForUid(anyInt());
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(1)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -889,8 +890,8 @@
waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
- verify(l, times(0)).updateJobsForUid(anyInt());
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -901,8 +902,8 @@
waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
- verify(l, times(0)).updateJobsForUid(anyInt());
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -915,8 +916,8 @@
waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
- verify(l, times(0)).updateJobsForUid(anyInt());
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -928,8 +929,8 @@
waitUntilMainHandlerDrain();
// Called once for updating all whitelist and once for updating temp whitelist
verify(l, times(2)).updateAllJobs();
- verify(l, times(0)).updateJobsForUid(anyInt());
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -940,8 +941,8 @@
waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
- verify(l, times(0)).updateJobsForUid(anyInt());
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(1)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -953,8 +954,8 @@
waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
- verify(l, times(0)).updateJobsForUid(anyInt());
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -965,8 +966,8 @@
waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
- verify(l, times(0)).updateJobsForUid(anyInt());
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -985,8 +986,8 @@
waitUntilMainHandlerDrain();
verify(l, times(0)).updateAllJobs();
- verify(l, times(1)).updateJobsForUid(eq(UID_10_1));
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
@@ -997,8 +998,8 @@
waitUntilMainHandlerDrain();
verify(l, times(0)).updateAllJobs();
- verify(l, times(1)).updateJobsForUid(eq(UID_10_1));
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -1009,8 +1010,8 @@
waitUntilMainHandlerDrain();
verify(l, times(0)).updateAllJobs();
- verify(l, times(1)).updateJobsForUid(eq(UID_10_1));
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
@@ -1021,8 +1022,8 @@
waitUntilMainHandlerDrain();
verify(l, times(0)).updateAllJobs();
- verify(l, times(1)).updateJobsForUid(eq(UID_10_1));
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -1035,8 +1036,8 @@
waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
- verify(l, times(0)).updateJobsForUid(eq(UID_10_1));
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(0)).updateJobsForUid(eq(UID_10_1), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(1)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -1047,8 +1048,8 @@
waitUntilMainHandlerDrain();
verify(l, times(0)).updateAllJobs();
- verify(l, times(1)).updateJobsForUid(eq(UID_10_1));
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
@@ -1059,8 +1060,8 @@
waitUntilMainHandlerDrain();
verify(l, times(0)).updateAllJobs();
- verify(l, times(1)).updateJobsForUid(eq(UID_10_1));
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -1071,8 +1072,8 @@
waitUntilMainHandlerDrain();
verify(l, times(0)).updateAllJobs();
- verify(l, times(1)).updateJobsForUid(eq(UID_10_1));
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
@@ -1083,8 +1084,8 @@
waitUntilMainHandlerDrain();
verify(l, times(0)).updateAllJobs();
- verify(l, times(1)).updateJobsForUid(eq(UID_10_1));
- verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+ verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean());
+ verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index 5b1f5c1..03e870a 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -123,12 +123,20 @@
}
return null;
}).when(mActivity.app.thread).scheduleTransaction(any());
+
mActivity.setState(STOPPED, "testPausingWhenVisibleFromStopped");
+ // The activity is in the focused stack so it should not move to paused.
mActivity.makeVisibleIfNeeded(null /* starting */);
+ assertTrue(mActivity.isState(STOPPED));
+ assertFalse(pauseFound.value);
+ // Clear focused stack
+ mActivity.mStackSupervisor.mFocusedStack = null;
+
+ // In the unfocused stack, the activity should move to paused.
+ mActivity.makeVisibleIfNeeded(null /* starting */);
assertTrue(mActivity.isState(PAUSING));
-
assertTrue(pauseFound.value);
// Make sure that the state does not change for current non-stopping states.
@@ -214,35 +222,4 @@
verify(mService.mStackSupervisor, times(1)).canPlaceEntityOnDisplay(anyInt(), eq(expected),
anyInt(), anyInt(), eq(record.info));
}
-
- @Test
- public void testFinishingAfterDestroying() throws Exception {
- assertFalse(mActivity.finishing);
- mActivity.setState(DESTROYING, "testFinishingAfterDestroying");
- assertTrue(mActivity.isState(DESTROYING));
- assertTrue(mActivity.finishing);
- }
-
- @Test
- public void testFinishingAfterDestroyed() throws Exception {
- assertFalse(mActivity.finishing);
- mActivity.setState(DESTROYED, "testFinishingAfterDestroyed");
- assertTrue(mActivity.isState(DESTROYED));
- assertTrue(mActivity.finishing);
- }
-
- @Test
- public void testSetInvalidState() throws Exception {
- mActivity.setState(DESTROYED, "testInvalidState");
-
- boolean exceptionEncountered = false;
-
- try {
- mActivity.setState(FINISHING, "testInvalidState");
- } catch (IllegalArgumentException e) {
- exceptionEncountered = true;
- }
-
- assertTrue(exceptionEncountered);
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index bda68d1..f17bfa4 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -479,28 +479,6 @@
}
@Test
- public void testSuppressMultipleDestroy() throws Exception {
- final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
- final ClientLifecycleManager lifecycleManager = mock(ClientLifecycleManager.class);
- final ProcessRecord app = r.app;
-
- // The mocked lifecycle manager must be set on the ActivityStackSupervisor's reference to
- // the service rather than mService as mService is a spy and setting the value will not
- // propagate as ActivityManagerService hands its own reference to the
- // ActivityStackSupervisor during construction.
- ((TestActivityManagerService) mSupervisor.mService).setLifecycleManager(lifecycleManager);
-
- mStack.destroyActivityLocked(r, true, "first invocation");
- verify(lifecycleManager, times(1)).scheduleTransaction(eq(app.thread),
- eq(r.appToken), any(DestroyActivityItem.class));
- assertTrue(r.isState(DESTROYED, DESTROYING));
-
- mStack.destroyActivityLocked(r, true, "second invocation");
- verify(lifecycleManager, times(1)).scheduleTransaction(eq(app.thread),
- eq(r.appToken), any(DestroyActivityItem.class));
- }
-
- @Test
public void testFinishDisabledPackageActivities() throws Exception {
final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build();
final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask).build();
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
index fdabfb4..5906db3 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
@@ -30,6 +30,7 @@
import android.app.IApplicationThread;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.content.pm.ActivityInfo.WindowLayout;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.graphics.Rect;
@@ -39,6 +40,7 @@
import android.service.voice.IVoiceInteractionSession;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import android.view.Gravity;
import org.junit.runner.RunWith;
import org.junit.Test;
@@ -52,6 +54,7 @@
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyObject;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
@@ -64,6 +67,8 @@
import com.android.internal.os.BatteryStatsImpl;
import com.android.server.am.ActivityStarter.Factory;
+import com.android.server.am.LaunchParamsController.LaunchParamsModifier;
+import com.android.server.am.TaskRecord.TaskRecordFactory;
/**
* Tests for the {@link ActivityStarter} class.
@@ -207,7 +212,8 @@
if (aInfo != null) {
aInfo.applicationInfo = new ApplicationInfo();
- aInfo.applicationInfo.packageName = builder.getDefaultComponentPackageName();
+ aInfo.applicationInfo.packageName =
+ ActivityBuilder.getDefaultComponent().getPackageName();
}
// Offset uid by one from {@link ActivityInfo} to simulate different uids.
@@ -284,9 +290,85 @@
}
}
-// TODO(b/69270257): Add test to verify task layout is passed additional data such as activity and
-// source.
-// @Test
-// public void testCreateTaskLayout() {
-// }
+ private ActivityStarter prepareStarter() {
+ // always allow test to start activity.
+ doReturn(true).when(mService.mStackSupervisor).checkStartAnyActivityPermission(
+ any(), any(), any(), anyInt(), anyInt(), anyInt(), any(),
+ anyBoolean(), any(), any(), any());
+
+ // instrument the stack and task used.
+ final ActivityStack stack = spy(mService.mStackSupervisor.getDefaultDisplay().createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */));
+ final TaskRecord task =
+ spy(new TaskBuilder(mService.mStackSupervisor).setStack(stack).build());
+
+ // supervisor needs a focused stack.
+ mService.mStackSupervisor.mFocusedStack = task.getStack();
+
+ // use factory that only returns spy task.
+ final TaskRecordFactory factory = mock(TaskRecordFactory.class);
+ TaskRecord.setTaskRecordFactory(factory);
+
+ // return task when created.
+ doReturn(task).when(factory).create(any(), anyInt(), any(), any(), any(), any());
+
+ // direct starter to use spy stack.
+ doReturn(stack).when(mService.mStackSupervisor)
+ .getLaunchStack(any(), any(), any(), anyBoolean());
+ doReturn(stack).when(mService.mStackSupervisor)
+ .getLaunchStack(any(), any(), any(), anyBoolean(), anyInt());
+
+ // ignore the start request.
+ doNothing().when(stack)
+ .startActivityLocked(any(), any(), anyBoolean(), anyBoolean(), any());
+
+ // ignore requests to create window container.
+ doNothing().when(task).createWindowContainer(anyBoolean(), anyBoolean());
+
+ return new ActivityStarter(mController, mService,
+ mService.mStackSupervisor, mock(ActivityStartInterceptor.class));
+ }
+
+ /**
+ * Ensures that values specified at launch time are passed to {@link LaunchParamsModifier}
+ * when we are laying out a new task.
+ */
+ @Test
+ public void testCreateTaskLayout() {
+ // modifier for validating passed values.
+ final LaunchParamsModifier modifier = mock(LaunchParamsModifier.class);
+ mService.mStackSupervisor.getLaunchParamsController().registerModifier(modifier);
+
+ // add custom values to activity info to make unique.
+ final ActivityInfo info = new ActivityInfo();
+ final Rect launchBounds = new Rect(0, 0, 20, 30);
+ final Intent intent = new Intent();
+
+ intent.setComponent(ActivityBuilder.getDefaultComponent());
+
+ final WindowLayout windowLayout =
+ new WindowLayout(10, .5f, 20, 1.0f, Gravity.NO_GRAVITY, 1, 1);
+
+ info.windowLayout = windowLayout;
+ info.applicationInfo = new ApplicationInfo();
+ info.applicationInfo.packageName = ActivityBuilder.getDefaultComponent().getPackageName();
+
+ // create starter.
+ final ActivityStarter optionStarter = prepareStarter();
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchBounds(launchBounds);
+
+ // run starter.
+ optionStarter
+ .setIntent(intent)
+ .setReason("testCreateTaskLayout")
+ .setActivityInfo(info)
+ .setActivityOptions(new SafeActivityOptions(options))
+ .execute();
+
+ // verify that values are passed to the modifier.
+ verify(modifier, times(1)).onCalculate(any(), eq(windowLayout), any(), any(), eq(options),
+ any(), any());
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index 1195188..3041a5f 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -101,6 +101,7 @@
protected ActivityManagerService setupActivityManagerService(ActivityManagerService service) {
service = spy(service);
doReturn(mock(IPackageManager.class)).when(service).getPackageManager();
+ doNothing().when(service).grantEphemeralAccessLocked(anyInt(), any(), anyInt(), anyInt());
service.mWindowManager = prepareMockWindowManager();
return service;
}
@@ -131,6 +132,11 @@
return this;
}
+ static ComponentName getDefaultComponent() {
+ return ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME,
+ DEFAULT_COMPONENT_PACKAGE_NAME);
+ }
+
ActivityBuilder setTask(TaskRecord task) {
mTaskRecord = task;
return this;
@@ -151,10 +157,6 @@
return this;
}
- String getDefaultComponentPackageName() {
- return DEFAULT_COMPONENT_PACKAGE_NAME;
- }
-
ActivityRecord build() {
if (mComponent == null) {
final int id = sCurrentActivityId++;
@@ -371,7 +373,8 @@
// Just return the current front task. This is called internally so we cannot use spy to mock this out.
@Override
- ActivityStack getNextFocusableStackLocked(ActivityStack currentFocus) {
+ ActivityStack getNextFocusableStackLocked(ActivityStack currentFocus,
+ boolean ignoreCurrent) {
return mFocusedStack;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
index 24566fc..376f5b1 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -24,6 +25,7 @@
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.view.Display.DEFAULT_DISPLAY;
import static org.junit.Assert.assertFalse;
@@ -74,7 +76,7 @@
import java.util.Set;
/**
- * runtest --path frameworks/base/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+ * atest FrameworksServicesTests:RecentTasksTest
*/
@MediumTest
@Presubmit
@@ -145,7 +147,7 @@
mRecentTasks = (TestRecentTasks) mService.getRecentTasks();
mRecentTasks.loadParametersFromResources(mContext.getResources());
mHomeStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
((MyTestActivityStackSupervisor) mService.mStackSupervisor).setHomeStack(mHomeStack);
@@ -236,7 +238,7 @@
}
@Test
- public void testAddTasksMultipleTasks_expectNoTrim() throws Exception {
+ public void testAddTasksMultipleDocumentTasks_expectNoTrim() throws Exception {
// Add same multiple-task document tasks does not trim the first tasks
TaskRecord documentTask1 = createDocumentTask(".DocumentTask1",
FLAG_ACTIVITY_MULTIPLE_TASK);
@@ -252,6 +254,50 @@
}
@Test
+ public void testAddTasksMultipleTasks_expectRemovedNoTrim() throws Exception {
+ // Add multiple same-affinity non-document tasks, ensure that it removes the other task,
+ // but that it does not trim it
+ TaskRecord task1 = createTaskBuilder(".Task1")
+ .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
+ .build();
+ TaskRecord task2 = createTaskBuilder(".Task1")
+ .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
+ .build();
+ mRecentTasks.add(task1);
+ assertTrue(mCallbacksRecorder.added.size() == 1);
+ assertTrue(mCallbacksRecorder.added.contains(task1));
+ assertTrue(mCallbacksRecorder.trimmed.isEmpty());
+ assertTrue(mCallbacksRecorder.removed.isEmpty());
+ mCallbacksRecorder.clear();
+ mRecentTasks.add(task2);
+ assertTrue(mCallbacksRecorder.added.size() == 1);
+ assertTrue(mCallbacksRecorder.added.contains(task2));
+ assertTrue(mCallbacksRecorder.trimmed.isEmpty());
+ assertTrue(mCallbacksRecorder.removed.size() == 1);
+ assertTrue(mCallbacksRecorder.removed.contains(task1));
+ }
+
+ @Test
+ public void testAddTasksDifferentStacks_expectNoRemove() throws Exception {
+ // Adding the same task with different activity types should not trigger removal of the
+ // other task
+ TaskRecord task1 = createTaskBuilder(".Task1")
+ .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
+ .setStack(mHomeStack).build();
+ TaskRecord task2 = createTaskBuilder(".Task1")
+ .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
+ .setStack(mStack).build();
+ mRecentTasks.add(task1);
+ mRecentTasks.add(task2);
+ assertTrue(mCallbacksRecorder.added.size() == 2);
+ assertTrue(mCallbacksRecorder.added.contains(task1));
+ assertTrue(mCallbacksRecorder.added.contains(task2));
+ assertTrue(mCallbacksRecorder.trimmed.isEmpty());
+ assertTrue(mCallbacksRecorder.removed.isEmpty());
+
+ }
+
+ @Test
public void testUsersTasks() throws Exception {
mRecentTasks.setOnlyTestVisibleRange();
diff --git a/services/tests/servicestests/src/com/android/server/autofill/AutofillManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/autofill/AutofillManagerServiceTest.java
new file mode 100644
index 0000000..c348e70
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/autofill/AutofillManagerServiceTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.autofill;
+
+import static com.android.server.autofill.AutofillManagerService.getWhitelistedCompatModePackages;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Map;
+
+@RunWith(JUnit4.class)
+public class AutofillManagerServiceTest {
+ // TODO(b/74445943): temporary work around until P Development Preview 3 is branched
+ private static final boolean ADDS_DEFAULT_BUTTON = true;
+
+ @Test
+ public void testGetWhitelistedCompatModePackages_null() {
+ assertThat(getWhitelistedCompatModePackages(null)).isNull();
+ }
+
+ @Test
+ public void testGetWhitelistedCompatModePackages_empty() {
+ assertThat(getWhitelistedCompatModePackages("")).isNull();
+ }
+
+ @Test
+ public void testGetWhitelistedCompatModePackages_onePackageNoUrls() {
+ if (ADDS_DEFAULT_BUTTON) {
+ final Map<String, String[]> result =
+ getWhitelistedCompatModePackages("one_is_the_loniest_package");
+ assertThat(result).hasSize(1);
+ assertThat(result.get("one_is_the_loniest_package")).asList()
+ .containsExactly("url_bar", "location_bar_edit_text");
+ } else {
+ assertThat(getWhitelistedCompatModePackages("one_is_the_loniest_package"))
+ .containsExactly("one_is_the_loniest_package", null);
+ }
+ }
+
+ @Test
+ public void testGetWhitelistedCompatModePackages_onePackageMissingEndDelimiter() {
+ assertThat(getWhitelistedCompatModePackages("one_is_the_loniest_package[")).isEmpty();
+ }
+
+ @Test
+ public void testGetWhitelistedCompatModePackages_onePackageOneUrl() {
+ final Map<String, String[]> result =
+ getWhitelistedCompatModePackages("one_is_the_loniest_package[url]");
+ assertThat(result).hasSize(1);
+ assertThat(result.get("one_is_the_loniest_package")).asList().containsExactly("url");
+ }
+
+ @Test
+ public void testGetWhitelistedCompatModePackages_onePackageMultipleUrls() {
+ final Map<String, String[]> result =
+ getWhitelistedCompatModePackages("one_is_the_loniest_package[4,5,8,15,16,23,42]");
+ assertThat(result).hasSize(1);
+ assertThat(result.get("one_is_the_loniest_package")).asList()
+ .containsExactly("4", "5", "8", "15", "16", "23", "42");
+ }
+
+ @Test
+ public void testGetWhitelistedCompatModePackages_multiplePackagesOneInvalid() {
+ final Map<String, String[]> result = getWhitelistedCompatModePackages("one:two[");
+ assertThat(result).hasSize(1);
+ if (ADDS_DEFAULT_BUTTON) {
+ assertThat(result.get("one")).asList()
+ .containsExactly("url_bar", "location_bar_edit_text");
+ } else {
+ assertThat(result.get("one")).isNull();
+ }
+ }
+
+ @Test
+ public void testGetWhitelistedCompatModePackages_multiplePackagesMultipleUrls() {
+ final Map<String, String[]> result =
+ getWhitelistedCompatModePackages("p1[p1u1]:p2:p3[p3u1,p3u2]");
+ assertThat(result).hasSize(3);
+ assertThat(result.get("p1")).asList().containsExactly("p1u1");
+ if (ADDS_DEFAULT_BUTTON) {
+ assertThat(result.get("p2")).asList()
+ .containsExactly("url_bar", "location_bar_edit_text");
+ } else {
+ assertThat(result.get("p2")).isNull();
+ }
+ assertThat(result.get("p3")).asList().containsExactly("p3u1", "p3u2");
+ }
+
+ @Test
+ public void testGetWhitelistedCompatModePackages_threePackagesOneInvalid() {
+ final Map<String, String[]> result =
+ getWhitelistedCompatModePackages("p1[p1u1]:p2[:p3[p3u1,p3u2]");
+ assertThat(result).hasSize(2);
+ assertThat(result.get("p1")).asList().containsExactly("p1u1");
+ assertThat(result.get("p3")).asList().containsExactly("p3u1", "p3u2");
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
index e864870..96f8160 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -43,6 +43,7 @@
import com.android.internal.widget.ILockSettings;
import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockSettingsInternal;
import com.android.server.LocalServices;
import org.mockito.invocation.InvocationOnMock;
@@ -67,6 +68,7 @@
private ArrayList<UserInfo> mPrimaryUserProfiles = new ArrayList<>();
LockSettingsService mService;
+ LockSettingsInternal mLocalService;
MockLockSettingsContext mContext;
LockSettingsStorageTestable mStorage;
@@ -95,6 +97,7 @@
mDevicePolicyManager = mock(DevicePolicyManager.class);
mDevicePolicyManagerInternal = mock(DevicePolicyManagerInternal.class);
+ LocalServices.removeServiceForTest(LockSettingsInternal.class);
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
LocalServices.addService(DevicePolicyManagerInternal.class, mDevicePolicyManagerInternal);
@@ -146,6 +149,7 @@
// Adding a fake Device Owner app which will enable escrow token support in LSS.
when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(
new ComponentName("com.dummy.package", ".FakeDeviceOwner"));
+ mLocalService = LocalServices.getService(LockSettingsInternal.class);
}
private UserInfo installChildProfile(int profileId) {
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index 294c3e9..e9f9800 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -300,14 +300,14 @@
initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
- long handle = mService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
- assertFalse(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
+ long handle = mLocalService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
+ assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
PRIMARY_USER_ID).getResponseCode();
- assertTrue(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
+ assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
- mService.setLockCredentialWithToken(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
+ mLocalService.setLockCredentialWithToken(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
handle, TOKEN.getBytes(), PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
// Verify DPM gets notified about new device lock
@@ -329,16 +329,16 @@
initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
- long handle = mService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
- assertFalse(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
+ long handle = mLocalService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
+ assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
0, PRIMARY_USER_ID).getResponseCode();
- assertTrue(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
+ assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
- mService.setLockCredentialWithToken(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, handle,
- TOKEN.getBytes(), PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID);
- mService.setLockCredentialWithToken(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
+ mLocalService.setLockCredentialWithToken(null, LockPatternUtils.CREDENTIAL_TYPE_NONE,
+ handle, TOKEN.getBytes(), PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID);
+ mLocalService.setLockCredentialWithToken(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
handle, TOKEN.getBytes(), PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
@@ -355,18 +355,19 @@
initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
- long handle = mService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
- assertFalse(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
+ long handle = mLocalService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
+ assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
0, PRIMARY_USER_ID).getResponseCode();
- assertTrue(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
+ assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
mService.setLockCredential(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, PASSWORD,
PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
- mService.setLockCredentialWithToken(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
- handle, TOKEN.getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
+ mLocalService.setLockCredentialWithToken(NEWPASSWORD,
+ LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, handle, TOKEN.getBytes(),
+ PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
@@ -378,8 +379,8 @@
throws RemoteException {
final String TOKEN = "some-high-entropy-secure-token";
enableSyntheticPassword();
- long handle = mService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
- assertTrue(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
+ long handle = mLocalService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
+ assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
}
@@ -388,8 +389,8 @@
throws RemoteException {
final String TOKEN = "some-high-entropy-secure-token";
initializeCredentialUnderSP(null, PRIMARY_USER_ID);
- long handle = mService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
- assertTrue(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
+ long handle = mLocalService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
+ assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
}
@@ -404,15 +405,15 @@
PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
enableSyntheticPassword();
- long handle = mService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
+ long handle = mLocalService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
// Token not activated immediately since user password exists
- assertFalse(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
+ assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
// Activate token (password gets migrated to SP at the same time)
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
.getResponseCode());
// Verify token is activated
- assertTrue(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
+ assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
}
public void testPasswordData_serializeDeserialize() {
diff --git a/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java b/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java
index 5de393c..f3539fe 100644
--- a/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java
+++ b/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java
@@ -25,6 +25,8 @@
import android.view.IApplicationToken;
import android.view.WindowManager;
+import com.android.server.wm.utils.WmDisplayCutout;
+
public class FakeWindowState implements WindowManagerPolicy.WindowState {
public final Rect parentFrame = new Rect();
@@ -36,7 +38,7 @@
public final Rect stableFrame = new Rect();
public Rect outsetFrame = new Rect();
- public DisplayCutout displayCutout;
+ public WmDisplayCutout displayCutout;
public WindowManager.LayoutParams attrs;
public int displayId;
@@ -61,7 +63,7 @@
@Override
public void computeFrameLw(Rect parentFrame, Rect displayFrame, Rect overlayFrame,
Rect contentFrame, Rect visibleFrame, Rect decorFrame, Rect stableFrame,
- @Nullable Rect outsetFrame, DisplayCutout displayCutout) {
+ @Nullable Rect outsetFrame, WmDisplayCutout displayCutout) {
this.parentFrame.set(parentFrame);
this.displayFrame.set(displayFrame);
this.overscanFrame.set(overlayFrame);
diff --git a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java
index 1d4348c..195dd39 100644
--- a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java
@@ -41,6 +41,7 @@
import android.os.UserHandle;
import android.support.test.InstrumentationRegistry;
import android.testing.TestableResources;
+import android.util.Pair;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
@@ -53,6 +54,7 @@
import com.android.server.policy.keyguard.KeyguardServiceDelegate;
import com.android.server.wm.DisplayFrames;
+import com.android.server.wm.utils.WmDisplayCutout;
import org.junit.Before;
@@ -98,8 +100,9 @@
}
private void updateDisplayFrames() {
- DisplayInfo info = displayInfoForRotation(mRotation, mHasDisplayCutout);
- mFrames = new DisplayFrames(Display.DEFAULT_DISPLAY, info);
+ Pair<DisplayInfo, WmDisplayCutout> info = displayInfoAndCutoutForRotation(mRotation,
+ mHasDisplayCutout);
+ mFrames = new DisplayFrames(Display.DEFAULT_DISPLAY, info.first, info.second);
}
public void addStatusBar() {
@@ -146,19 +149,26 @@
}
public static DisplayInfo displayInfoForRotation(int rotation, boolean withDisplayCutout) {
+ return displayInfoAndCutoutForRotation(rotation, withDisplayCutout).first;
+ }
+ public static Pair<DisplayInfo, WmDisplayCutout> displayInfoAndCutoutForRotation(int rotation,
+ boolean withDisplayCutout) {
DisplayInfo info = new DisplayInfo();
+ WmDisplayCutout cutout = null;
final boolean flippedDimensions = rotation == ROTATION_90 || rotation == ROTATION_270;
info.logicalWidth = flippedDimensions ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
info.logicalHeight = flippedDimensions ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
info.rotation = rotation;
if (withDisplayCutout) {
- info.displayCutout = displayCutoutForRotation(rotation)
- .computeSafeInsets(info.logicalWidth, info.logicalHeight);
+ cutout = WmDisplayCutout.computeSafeInsets(
+ displayCutoutForRotation(rotation), info.logicalWidth,
+ info.logicalHeight);
+ info.displayCutout = cutout.getDisplayCutout();
} else {
info.displayCutout = null;
}
- return info;
+ return Pair.create(info, cutout);
}
private static DisplayCutout displayCutoutForRotation(int rotation) {
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
index 76e4e89..e0645b1 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
@@ -20,11 +20,9 @@
import org.junit.Test;
import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.SecurityTest;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.view.WindowManager;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -36,13 +34,12 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
-import java.util.function.Consumer;
+import com.android.server.wm.WindowTestUtils.TestTaskWindowContainerController;
/**
* Test class for {@link AppWindowContainerController}.
*
- * Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.wm.AppWindowContainerControllerTests
+ * atest FrameworksServicesTests:com.android.server.wm.AppWindowContainerControllerTests
*/
@SmallTest
@Presubmit
@@ -176,6 +173,33 @@
}
@Test
+ public void testTryTransferStartingWindowFromHiddenAboveToken() throws Exception {
+
+ // Add two tasks on top of each other.
+ TestTaskWindowContainerController taskController =
+ new WindowTestUtils.TestTaskWindowContainerController(this);
+ final WindowTestUtils.TestAppWindowContainerController controllerTop =
+ createAppWindowController(taskController);
+ final WindowTestUtils.TestAppWindowContainerController controllerBottom =
+ createAppWindowController(taskController);
+
+ // Add a starting window.
+ controllerTop.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
+ android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
+ false, false);
+ waitUntilHandlersIdle();
+
+ // Make the top one invisible, and try transfering the starting window from the top to the
+ // bottom one.
+ controllerTop.setVisibility(false, false);
+ controllerBottom.mContainer.transferStartingWindowFromHiddenAboveTokenIfNeeded();
+
+ // Assert that the bottom window now has the starting window.
+ assertNoStartingWindow(controllerTop.getAppWindowToken(mDisplayContent));
+ assertHasStartingWindow(controllerBottom.getAppWindowToken(mDisplayContent));
+ }
+
+ @Test
public void testReparent() throws Exception {
final StackWindowController stackController =
createStackControllerOnDisplay(mDisplayContent);
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index e31e20c..ccde049 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -33,7 +33,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import org.junit.Ignore;
+import android.support.test.filters.FlakyTest;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -50,6 +50,8 @@
import android.view.MotionEvent;
import android.view.Surface;
+import com.android.server.wm.utils.WmDisplayCutout;
+
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
@@ -300,7 +302,7 @@
}
@Test
- @Ignore
+ @FlakyTest(bugId = 37908381)
public void testFocusedWindowMultipleDisplays() throws Exception {
// Create a focusable window and check that focus is calculated correctly
final WindowState window1 =
@@ -398,8 +400,9 @@
dc.mInitialDisplayWidth = 200;
dc.mInitialDisplayHeight = 400;
Rect r = new Rect(80, 0, 120, 10);
- final DisplayCutout cutout = fromBoundingRect(r.left, r.top, r.right, r.bottom)
- .computeSafeInsets(200, 400);
+ final DisplayCutout cutout = new WmDisplayCutout(
+ fromBoundingRect(r.left, r.top, r.right, r.bottom), null)
+ .computeSafeInsets(200, 400).getDisplayCutout();
dc.mInitialDisplayCutout = cutout;
dc.setRotation(Surface.ROTATION_0);
@@ -416,16 +419,18 @@
dc.mInitialDisplayWidth = 200;
dc.mInitialDisplayHeight = 400;
Rect r1 = new Rect(80, 0, 120, 10);
- final DisplayCutout cutout = fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom)
- .computeSafeInsets(200, 400);
+ final DisplayCutout cutout = new WmDisplayCutout(
+ fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom), null)
+ .computeSafeInsets(200, 400).getDisplayCutout();
dc.mInitialDisplayCutout = cutout;
dc.setRotation(Surface.ROTATION_90);
dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
final Rect r = new Rect(0, 80, 10, 120);
- assertEquals(fromBoundingRect(r.left, r.top, r.right, r.bottom)
- .computeSafeInsets(400, 200), dc.getDisplayInfo().displayCutout);
+ assertEquals(new WmDisplayCutout(
+ fromBoundingRect(r.left, r.top, r.right, r.bottom), null)
+ .computeSafeInsets(400, 200).getDisplayCutout(), dc.getDisplayInfo().displayCutout);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
index 96fbc14..80cbf2a 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
@@ -42,7 +42,7 @@
/**
* Test class for {@link TaskSnapshotPersister} and {@link TaskSnapshotLoader}
*
- * runtest frameworks-services -c com.android.server.wm.TaskSnapshotPersisterLoaderTest
+ * atest FrameworksServicesTests:TaskSnapshotPersisterLoaderTest
*/
@MediumTest
@Presubmit
@@ -163,6 +163,23 @@
}
@Test
+ public void testIsRealSnapshotPersistAndLoadSnapshot() {
+ TaskSnapshot a = createSnapshot(1f /* scale */, true /* isRealSnapshot */);
+ TaskSnapshot b = createSnapshot(1f /* scale */, false /* isRealSnapshot */);
+ assertTrue(a.isRealSnapshot());
+ assertFalse(b.isRealSnapshot());
+ mPersister.persistSnapshot(1, mTestUserId, a);
+ mPersister.persistSnapshot(2, mTestUserId, b);
+ mPersister.waitForQueueEmpty();
+ final TaskSnapshot snapshotA = mLoader.loadTask(1, mTestUserId, false /* reduced */);
+ final TaskSnapshot snapshotB = mLoader.loadTask(2, mTestUserId, false /* reduced */);
+ assertNotNull(snapshotA);
+ assertNotNull(snapshotB);
+ assertTrue(snapshotA.isRealSnapshot());
+ assertFalse(snapshotB.isRealSnapshot());
+ }
+
+ @Test
public void testRemoveObsoleteFiles() {
mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
mPersister.persistSnapshot(2, mTestUserId, createSnapshot());
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index b49a0fd..2ad5bf4 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -84,12 +84,16 @@
}
TaskSnapshot createSnapshot(float scale) {
+ return createSnapshot(scale, true /* isRealSnapshot */);
+ }
+
+ TaskSnapshot createSnapshot(float scale, boolean isRealSnapshot) {
final GraphicBuffer buffer = GraphicBuffer.create(100, 100, PixelFormat.RGBA_8888,
USAGE_HW_TEXTURE | USAGE_SW_READ_RARELY | USAGE_SW_READ_RARELY);
Canvas c = buffer.lockCanvas();
c.drawColor(Color.RED);
buffer.unlockCanvasAndPost(c);
return new TaskSnapshot(buffer, ORIENTATION_PORTRAIT, TEST_INSETS,
- scale < 1f /* reducedResolution */, scale);
+ scale < 1f /* reducedResolution */, scale, isRealSnapshot);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index 4288eac..d5334ba 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -60,7 +60,7 @@
final GraphicBuffer buffer = GraphicBuffer.create(width, height, PixelFormat.RGBA_8888,
GraphicBuffer.USAGE_SW_READ_NEVER | GraphicBuffer.USAGE_SW_WRITE_NEVER);
final TaskSnapshot snapshot = new TaskSnapshot(buffer,
- ORIENTATION_PORTRAIT, contentInsets, false, 1.0f);
+ ORIENTATION_PORTRAIT, contentInsets, false, 1.0f, true /* isRealSnapshot */);
mSurface = new TaskSnapshotSurface(sWm, new Window(), new Surface(), snapshot, "Test",
Color.WHITE, Color.RED, Color.BLUE, sysuiVis, windowFlags, 0, taskBounds,
ORIENTATION_PORTRAIT);
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 6784e30..6d9167f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -656,4 +656,8 @@
@Override
public void requestUserActivityNotification() {
}
+
+ @Override
+ public void onLockTaskStateChangedLw(int lockTaskState) {
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
index b5d5fc6..bd212a9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -26,7 +26,6 @@
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.IWindow;
@@ -38,6 +37,8 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import com.android.server.wm.utils.WmDisplayCutout;
+
/**
* Tests for the {@link WindowState#computeFrameLw} method and other window frame machinery.
*
@@ -159,7 +160,7 @@
// When mFrame extends past cf, the content insets are
// the difference between mFrame and ContentFrame. Visible
// and stable frames work the same way.
- w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, DisplayCutout.NO_CUTOUT);
+ w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, WmDisplayCutout.NO_CUTOUT);
assertRect(w.mFrame,0, 0, 1000, 1000);
assertRect(w.mContentInsets, 0, topContentInset, 0, bottomContentInset);
assertRect(w.mVisibleInsets, 0, topVisibleInset, 0, bottomVisibleInset);
@@ -174,7 +175,7 @@
w.mAttrs.width = 100; w.mAttrs.height = 100; //have to clear MATCH_PARENT
w.mRequestedWidth = 100;
w.mRequestedHeight = 100;
- w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, DisplayCutout.NO_CUTOUT);
+ w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, WmDisplayCutout.NO_CUTOUT);
assertRect(w.mFrame, 100, 100, 200, 200);
assertRect(w.mContentInsets, 0, 0, 0, 0);
// In this case the frames are shrunk to the window frame.
@@ -195,7 +196,7 @@
// Here the window has FILL_PARENT, FILL_PARENT
// so we expect it to fill the entire available frame.
- w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, DisplayCutout.NO_CUTOUT);
+ w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
assertRect(w.mFrame, 0, 0, 1000, 1000);
// It can select various widths and heights within the bounds.
@@ -203,14 +204,14 @@
// and we use mRequestedWidth/mRequestedHeight
w.mAttrs.width = 300;
w.mAttrs.height = 300;
- w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, DisplayCutout.NO_CUTOUT);
+ w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
// Explicit width and height without requested width/height
// gets us nothing.
assertRect(w.mFrame, 0, 0, 0, 0);
w.mRequestedWidth = 300;
w.mRequestedHeight = 300;
- w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, DisplayCutout.NO_CUTOUT);
+ w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
// With requestedWidth/Height we can freely choose our size within the
// parent bounds.
assertRect(w.mFrame, 0, 0, 300, 300);
@@ -223,14 +224,14 @@
w.mRequestedWidth = -1;
w.mAttrs.width = 100;
w.mAttrs.height = 100;
- w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, DisplayCutout.NO_CUTOUT);
+ w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
assertRect(w.mFrame, 0, 0, 100, 100);
w.mAttrs.flags = 0;
// But sizes too large will be clipped to the containing frame
w.mRequestedWidth = 1200;
w.mRequestedHeight = 1200;
- w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, DisplayCutout.NO_CUTOUT);
+ w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
assertRect(w.mFrame, 0, 0, 1000, 1000);
// Before they are clipped though windows will be shifted
@@ -238,7 +239,7 @@
w.mAttrs.y = 300;
w.mRequestedWidth = 1000;
w.mRequestedHeight = 1000;
- w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, DisplayCutout.NO_CUTOUT);
+ w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
assertRect(w.mFrame, 0, 0, 1000, 1000);
// If there is room to move around in the parent frame the window will be shifted according
@@ -248,16 +249,16 @@
w.mRequestedWidth = 300;
w.mRequestedHeight = 300;
w.mAttrs.gravity = Gravity.RIGHT | Gravity.TOP;
- w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, DisplayCutout.NO_CUTOUT);
+ w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
assertRect(w.mFrame, 700, 0, 1000, 300);
w.mAttrs.gravity = Gravity.RIGHT | Gravity.BOTTOM;
- w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, DisplayCutout.NO_CUTOUT);
+ w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
assertRect(w.mFrame, 700, 700, 1000, 1000);
// Window specified x and y are interpreted as offsets in the opposite
// direction of gravity
w.mAttrs.x = 100;
w.mAttrs.y = 100;
- w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, DisplayCutout.NO_CUTOUT);
+ w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
assertRect(w.mFrame, 600, 600, 900, 900);
}
@@ -278,7 +279,7 @@
w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
- w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, null, DisplayCutout.NO_CUTOUT);
+ w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, null, WmDisplayCutout.NO_CUTOUT);
// For non fullscreen tasks the containing frame is based off the
// task bounds not the parent frame.
assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
@@ -290,7 +291,7 @@
final int cfRight = logicalWidth / 2;
final int cfBottom = logicalHeight / 2;
final Rect cf = new Rect(0, 0, cfRight, cfBottom);
- w.computeFrameLw(pf, pf, pf, cf, cf, pf, cf, null, DisplayCutout.NO_CUTOUT);
+ w.computeFrameLw(pf, pf, pf, cf, cf, pf, cf, null, WmDisplayCutout.NO_CUTOUT);
assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
int contentInsetRight = taskRight - cfRight;
int contentInsetBottom = taskBottom - cfBottom;
@@ -307,7 +308,7 @@
final int insetRight = insetLeft + (taskRight - taskLeft);
final int insetBottom = insetTop + (taskBottom - taskTop);
task.mInsetBounds.set(insetLeft, insetTop, insetRight, insetBottom);
- w.computeFrameLw(pf, pf, pf, cf, cf, pf, cf, null, DisplayCutout.NO_CUTOUT);
+ w.computeFrameLw(pf, pf, pf, cf, cf, pf, cf, null, WmDisplayCutout.NO_CUTOUT);
assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
contentInsetRight = insetRight - cfRight;
contentInsetBottom = insetBottom - cfBottom;
@@ -339,13 +340,13 @@
final Rect policyCrop = new Rect();
- w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, DisplayCutout.NO_CUTOUT);
+ w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, WmDisplayCutout.NO_CUTOUT);
w.calculatePolicyCrop(policyCrop);
assertRect(policyCrop, 0, cf.top, logicalWidth, cf.bottom);
dcf.setEmpty();
// Likewise with no decor frame we would get no crop
- w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, DisplayCutout.NO_CUTOUT);
+ w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, WmDisplayCutout.NO_CUTOUT);
w.calculatePolicyCrop(policyCrop);
assertRect(policyCrop, 0, 0, logicalWidth, logicalHeight);
@@ -358,7 +359,7 @@
w.mAttrs.height = logicalHeight / 2;
w.mRequestedWidth = logicalWidth / 2;
w.mRequestedHeight = logicalHeight / 2;
- w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, DisplayCutout.NO_CUTOUT);
+ w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
w.calculatePolicyCrop(policyCrop);
// Normally the crop is shrunk from the decor frame
@@ -395,7 +396,7 @@
final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
w.computeFrameLw(pf /* parentFrame */, pf /* displayFrame */, pf /* overscanFrame */,
pf /* contentFrame */, pf /* visibleFrame */, pf /* decorFrame */,
- pf /* stableFrame */, null /* outsetFrame */, DisplayCutout.NO_CUTOUT);
+ pf /* stableFrame */, null /* outsetFrame */, WmDisplayCutout.NO_CUTOUT);
// For non fullscreen tasks the containing frame is based off the
// task bounds not the parent frame.
assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
@@ -414,7 +415,7 @@
w.computeFrameLw(pf /* parentFrame */, pf /* displayFrame */, pf /* overscanFrame */,
cf /* contentFrame */, cf /* visibleFrame */, pf /* decorFrame */,
- cf /* stableFrame */, null /* outsetFrame */, DisplayCutout.NO_CUTOUT);
+ cf /* stableFrame */, null /* outsetFrame */, WmDisplayCutout.NO_CUTOUT);
assertEquals(cf, w.mFrame);
assertEquals(cf, w.getContentFrameLw());
assertRect(w.mContentInsets, 0, 0, 0, 0);
@@ -427,17 +428,17 @@
WindowState w = createWindow(task, FILL_PARENT, FILL_PARENT);
w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
- final Rect pf = new Rect(0, 0, 1000, 1000);
+ final Rect pf = new Rect(0, 0, 1000, 2000);
// Create a display cutout of size 50x50, aligned top-center
- final DisplayCutout cutout = fromBoundingRect(500, 0, 550, 50)
- .computeSafeInsets(pf.width(), pf.height());
+ final WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets(
+ fromBoundingRect(500, 0, 550, 50), pf.width(), pf.height());
w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, cutout);
- assertEquals(w.mDisplayCutout.getSafeInsetTop(), 50);
- assertEquals(w.mDisplayCutout.getSafeInsetBottom(), 0);
- assertEquals(w.mDisplayCutout.getSafeInsetLeft(), 0);
- assertEquals(w.mDisplayCutout.getSafeInsetRight(), 0);
+ assertEquals(w.mDisplayCutout.getDisplayCutout().getSafeInsetTop(), 50);
+ assertEquals(w.mDisplayCutout.getDisplayCutout().getSafeInsetBottom(), 0);
+ assertEquals(w.mDisplayCutout.getDisplayCutout().getSafeInsetLeft(), 0);
+ assertEquals(w.mDisplayCutout.getDisplayCutout().getSafeInsetRight(), 0);
}
private WindowStateWithTask createWindow(Task task, int width, int height) {
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
index cdcb949..56b7d9f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -38,7 +38,6 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
-import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static org.junit.Assert.assertEquals;
@@ -288,6 +287,16 @@
app.mToken.setHidden(false);
app.mAttrs.alpha = 0.0f;
assertFalse(app.canAffectSystemUiFlags());
+
+ }
+
+ @Test
+ public void testCanAffectSystemUiFlags_disallow() throws Exception {
+ final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ app.mToken.setHidden(false);
+ assertTrue(app.canAffectSystemUiFlags());
+ app.getTask().setCanAffectSystemUiFlags(false);
+ assertFalse(app.canAffectSystemUiFlags());
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/wm/utils/WmDisplayCutoutTest.java b/services/tests/servicestests/src/com/android/server/wm/utils/WmDisplayCutoutTest.java
new file mode 100644
index 0000000..f7addf6
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/utils/WmDisplayCutoutTest.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.utils;
+
+
+import static android.view.DisplayCutout.NO_CUTOUT;
+import static android.view.DisplayCutout.fromBoundingRect;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Size;
+import android.view.DisplayCutout;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+/**
+ * Tests for {@link WmDisplayCutout}
+ *
+ * Run with: atest WmDisplayCutoutTest
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class WmDisplayCutoutTest {
+
+ private final DisplayCutout mCutoutTop = new DisplayCutout(
+ new Rect(0, 100, 0, 0),
+ Arrays.asList(new Rect(50, 0, 75, 100)));
+
+ @Test
+ public void calculateRelativeTo_top() {
+ WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets(
+ fromBoundingRect(0, 0, 100, 20), 200, 400)
+ .calculateRelativeTo(new Rect(5, 5, 95, 195));
+
+ assertEquals(new Rect(0, 15, 0, 0), cutout.getDisplayCutout().getSafeInsets());
+ }
+
+ @Test
+ public void calculateRelativeTo_left() {
+ WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets(
+ fromBoundingRect(0, 0, 20, 100), 400, 200)
+ .calculateRelativeTo(new Rect(5, 5, 195, 95));
+
+ assertEquals(new Rect(15, 0, 0, 0), cutout.getDisplayCutout().getSafeInsets());
+ }
+
+ @Test
+ public void calculateRelativeTo_bottom() {
+ WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets(
+ fromBoundingRect(0, 180, 100, 200), 100, 200)
+ .calculateRelativeTo(new Rect(5, 5, 95, 195));
+
+ assertEquals(new Rect(0, 0, 0, 15), cutout.getDisplayCutout().getSafeInsets());
+ }
+
+ @Test
+ public void calculateRelativeTo_right() {
+ WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets(
+ fromBoundingRect(180, 0, 200, 100), 200, 100)
+ .calculateRelativeTo(new Rect(5, 5, 195, 95));
+
+ assertEquals(new Rect(0, 0, 15, 0), cutout.getDisplayCutout().getSafeInsets());
+ }
+
+ @Test
+ public void calculateRelativeTo_bounds() {
+ WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets(
+ fromBoundingRect(0, 0, 100, 20), 200, 400)
+ .calculateRelativeTo(new Rect(5, 10, 95, 180));
+
+ assertEquals(new Rect(-5, -10, 95, 10), cutout.getDisplayCutout().getBounds().getBounds());
+ }
+
+ @Test
+ public void computeSafeInsets_top() {
+ WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets(
+ fromBoundingRect(0, 0, 100, 20), 200, 400);
+
+ assertEquals(new Rect(0, 20, 0, 0), cutout.getDisplayCutout().getSafeInsets());
+ }
+
+ @Test
+ public void computeSafeInsets_left() {
+ WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets(
+ fromBoundingRect(0, 0, 20, 100), 400, 200);
+
+ assertEquals(new Rect(20, 0, 0, 0), cutout.getDisplayCutout().getSafeInsets());
+ }
+
+ @Test
+ public void computeSafeInsets_bottom() {
+ WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets(
+ fromBoundingRect(0, 180, 100, 200), 100, 200);
+
+ assertEquals(new Rect(0, 0, 0, 20), cutout.getDisplayCutout().getSafeInsets());
+ }
+
+ @Test
+ public void computeSafeInsets_right() {
+ WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets(
+ fromBoundingRect(180, 0, 200, 100), 200, 100);
+
+ assertEquals(new Rect(0, 0, 20, 0), cutout.getDisplayCutout().getSafeInsets());
+ }
+
+ @Test
+ public void computeSafeInsets_bounds() {
+ DisplayCutout cutout = WmDisplayCutout.computeSafeInsets(mCutoutTop, 1000,
+ 2000).getDisplayCutout();
+
+ assertEquals(mCutoutTop.getBounds().getBounds(),
+ cutout.getBounds().getBounds());
+ }
+
+ @Test
+ public void test_equals() {
+ assertEquals(new WmDisplayCutout(NO_CUTOUT, null), new WmDisplayCutout(NO_CUTOUT, null));
+ assertEquals(new WmDisplayCutout(mCutoutTop, new Size(1, 2)),
+ new WmDisplayCutout(mCutoutTop, new Size(1, 2)));
+
+ assertNotEquals(new WmDisplayCutout(mCutoutTop, new Size(1, 2)),
+ new WmDisplayCutout(mCutoutTop, new Size(5, 6)));
+ assertNotEquals(new WmDisplayCutout(mCutoutTop, new Size(1, 2)),
+ new WmDisplayCutout(NO_CUTOUT, new Size(1, 2)));
+ }
+
+ @Test
+ public void test_hashCode() {
+ assertEquals(new WmDisplayCutout(NO_CUTOUT, null).hashCode(),
+ new WmDisplayCutout(NO_CUTOUT, null).hashCode());
+ assertEquals(new WmDisplayCutout(mCutoutTop, new Size(1, 2)).hashCode(),
+ new WmDisplayCutout(mCutoutTop, new Size(1, 2)).hashCode());
+ }
+}
\ No newline at end of file
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BadgeExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BadgeExtractorTest.java
index 142041a..cfc7430 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BadgeExtractorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BadgeExtractorTest.java
@@ -18,10 +18,13 @@
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
import android.app.ActivityManager;
import android.app.Notification;
@@ -149,4 +152,52 @@
assertFalse(r.canShowBadge());
}
+
+ @Test
+ public void testDndOverridesYes() {
+ BadgeExtractor extractor = new BadgeExtractor();
+ extractor.setConfig(mConfig);
+
+ when(mConfig.badgingEnabled(mUser)).thenReturn(true);
+ when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
+ NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
+ r.setIntercepted(true);
+ r.setSuppressedVisualEffects(SUPPRESSED_EFFECT_BADGE);
+
+ extractor.process(r);
+
+ assertFalse(r.canShowBadge());
+ }
+
+ @Test
+ public void testDndOConsidersInterception() {
+ BadgeExtractor extractor = new BadgeExtractor();
+ extractor.setConfig(mConfig);
+
+ when(mConfig.badgingEnabled(mUser)).thenReturn(true);
+ when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
+ NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
+ r.setIntercepted(false);
+ r.setSuppressedVisualEffects(SUPPRESSED_EFFECT_BADGE);
+
+ extractor.process(r);
+
+ assertTrue(r.canShowBadge());
+ }
+
+ @Test
+ public void testDndConsidersSuppressedVisualEffects() {
+ BadgeExtractor extractor = new BadgeExtractor();
+ extractor.setConfig(mConfig);
+
+ when(mConfig.badgingEnabled(mUser)).thenReturn(true);
+ when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
+ NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
+ r.setIntercepted(true);
+ r.setSuppressedVisualEffects(SUPPRESSED_EFFECT_LIGHTS);
+
+ extractor.process(r);
+
+ assertTrue(r.canShowBadge());
+ }
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index a92f7e7..cb64c9c 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -21,6 +21,7 @@
import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.NotificationManager.IMPORTANCE_MIN;
+import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
@@ -389,6 +390,7 @@
mService.buzzBeepBlinkLocked(r);
verifyLights();
+ assertTrue(r.isInterruptive());
}
@Test
@@ -400,6 +402,7 @@
verifyBeepLooped();
verifyNeverVibrate();
verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
+ assertTrue(r.isInterruptive());
}
@Test
@@ -409,6 +412,7 @@
mService.buzzBeepBlinkLocked(r);
verifyBeep();
+ assertTrue(r.isInterruptive());
}
@Test
@@ -418,6 +422,7 @@
mService.buzzBeepBlinkLocked(r);
verifyNeverBeep();
+ assertFalse(r.isInterruptive());
}
@Test
@@ -429,6 +434,7 @@
verifyNeverBeep();
verifyNeverVibrate();
+ assertFalse(r.isInterruptive());
}
@Test
@@ -440,6 +446,7 @@
verifyNeverBeep();
verifyNeverVibrate();
+ assertFalse(r.isInterruptive());
}
@Test
@@ -455,6 +462,7 @@
mService.buzzBeepBlinkLocked(r);
verifyBeepLooped();
verify(mAccessibilityService, times(2)).sendAccessibilityEvent(any(), anyInt());
+ assertTrue(r.isInterruptive());
}
@Test
@@ -482,6 +490,7 @@
mService.buzzBeepBlinkLocked(r);
verifyNeverStopAudio();
+ assertTrue(r.isInterruptive());
}
@Test
@@ -494,6 +503,8 @@
mService.buzzBeepBlinkLocked(s);
verifyNeverStopAudio();
+ assertTrue(r.isInterruptive());
+ assertFalse(s.isInterruptive());
}
@Test
@@ -511,6 +522,7 @@
// should not stop noise, since we no longer own it
mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
verifyNeverStopAudio();
+ assertTrue(other.isInterruptive());
}
@Test
@@ -535,11 +547,13 @@
// set up internal state
mService.buzzBeepBlinkLocked(r);
+ assertTrue(r.isInterruptive());
Mockito.reset(mRingtonePlayer);
// quiet update should stop making noise
mService.buzzBeepBlinkLocked(s);
verifyStopAudio();
+ assertFalse(s.isInterruptive());
}
@Test
@@ -550,11 +564,13 @@
// set up internal state
mService.buzzBeepBlinkLocked(r);
+ assertTrue(r.isInterruptive());
Mockito.reset(mRingtonePlayer);
// stop making noise - this is a weird corner case, but quiet should override once
mService.buzzBeepBlinkLocked(s);
verifyStopAudio();
+ assertFalse(s.isInterruptive());
}
@Test
@@ -570,6 +586,7 @@
verify(mService, times(1)).playInCallNotification();
verifyNeverBeep(); // doesn't play normal beep
+ assertTrue(r.isInterruptive());
}
@Test
@@ -587,6 +604,7 @@
verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
eq(effect), (AudioAttributes) anyObject());
+ assertTrue(r.isInterruptive());
}
@Test
@@ -603,6 +621,7 @@
verifyNeverVibrate();
verifyBeepLooped();
+ assertTrue(r.isInterruptive());
}
@Test
@@ -621,6 +640,7 @@
eq(FALLBACK_VIBRATION), (AudioAttributes) anyObject());
verify(mRingtonePlayer, never()).playAsync
(anyObject(), anyObject(), anyBoolean(), anyObject());
+ assertTrue(r.isInterruptive());
}
@Test
@@ -636,6 +656,7 @@
mService.buzzBeepBlinkLocked(r);
verifyDelayedVibrateLooped();
+ assertTrue(r.isInterruptive());
}
@Test
@@ -646,18 +667,20 @@
verifyNeverBeep();
verifyVibrate();
+ assertTrue(r.isInterruptive());
}
@Test
- public void testInsistentVibrate() throws Exception {
+ public void testInsistentVibrate() {
NotificationRecord r = getInsistentBuzzyNotification();
mService.buzzBeepBlinkLocked(r);
verifyVibrateLooped();
+ assertTrue(r.isInterruptive());
}
@Test
- public void testVibrateTwice() throws Exception {
+ public void testVibrateTwice() {
NotificationRecord r = getBuzzyNotification();
// set up internal state
@@ -668,6 +691,7 @@
r.isUpdate = true;
mService.buzzBeepBlinkLocked(r);
verifyVibrate();
+ assertTrue(r.isInterruptive());
}
@Test
@@ -677,6 +701,7 @@
mService.buzzBeepBlinkLocked(child);
verifyNeverBeep();
+ assertFalse(child.isInterruptive());
}
@Test
@@ -687,6 +712,7 @@
mService.buzzBeepBlinkLocked(summary);
verifyBeepLooped();
+ assertTrue(summary.isInterruptive());
}
@Test
@@ -696,6 +722,7 @@
mService.buzzBeepBlinkLocked(nonGroup);
verifyBeepLooped();
+ assertTrue(nonGroup.isInterruptive());
}
@Test
@@ -706,6 +733,7 @@
mService.buzzBeepBlinkLocked(summary);
verifyNeverBeep();
+ assertFalse(summary.isInterruptive());
}
@Test
@@ -715,6 +743,7 @@
mService.buzzBeepBlinkLocked(child);
verifyBeepLooped();
+ assertTrue(child.isInterruptive());
}
@Test
@@ -724,6 +753,7 @@
mService.buzzBeepBlinkLocked(nonGroup);
verifyBeepLooped();
+ assertTrue(nonGroup.isInterruptive());
}
@Test
@@ -733,6 +763,7 @@
mService.buzzBeepBlinkLocked(group);
verifyBeepLooped();
+ assertTrue(group.isInterruptive());
}
@Test
@@ -744,10 +775,12 @@
// set up internal state
mService.buzzBeepBlinkLocked(r);
Mockito.reset(mVibrator);
+ assertTrue(r.isInterruptive());
// update should not beep
mService.buzzBeepBlinkLocked(s);
verifyNeverVibrate();
+ assertFalse(s.isInterruptive());
}
@Test
@@ -759,6 +792,7 @@
mService.buzzBeepBlinkLocked(r);
verifyNeverStopVibrate();
+ assertTrue(r.isInterruptive());
}
@Test
@@ -771,6 +805,8 @@
mService.buzzBeepBlinkLocked(s);
verifyNeverStopVibrate();
+ assertTrue(r.isInterruptive());
+ assertFalse(s.isInterruptive());
}
@Test
@@ -788,6 +824,9 @@
// should not stop vibrate, since we no longer own it
mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
verifyNeverStopVibrate();
+ assertTrue(r.isInterruptive());
+ assertTrue(other.isInterruptive());
+ assertFalse(s.isInterruptive());
}
@Test
@@ -802,10 +841,11 @@
// should not stop noise, since it does not own it
mService.buzzBeepBlinkLocked(other);
verifyNeverStopVibrate();
+ assertFalse(other.isInterruptive());
}
@Test
- public void testQuietUpdateCancelsVibrate() throws Exception {
+ public void testQuietUpdateCancelsVibrate() {
NotificationRecord r = getBuzzyNotification();
NotificationRecord s = getQuietNotification();
s.isUpdate = true;
@@ -817,6 +857,8 @@
// quiet update should stop making noise
mService.buzzBeepBlinkLocked(s);
verifyStopVibrate();
+ assertTrue(r.isInterruptive());
+ assertFalse(s.isInterruptive());
}
@Test
@@ -832,6 +874,8 @@
// stop making noise - this is a weird corner case, but quiet should override once
mService.buzzBeepBlinkLocked(s);
verifyStopVibrate();
+ assertTrue(r.isInterruptive());
+ assertFalse(s.isInterruptive());
}
@Test
@@ -848,6 +892,8 @@
// quiet update should stop making noise
mService.buzzBeepBlinkLocked(s);
verifyStopVibrate();
+ assertTrue(r.isInterruptive());
+ assertFalse(s.isInterruptive());
}
@Test
@@ -864,6 +910,7 @@
mService.buzzBeepBlinkLocked(r);
verifyNeverBeep();
+ assertFalse(r.isInterruptive());
}
@Test
@@ -874,6 +921,7 @@
mService.buzzBeepBlinkLocked(r);
verifyNeverBeep();
+ assertFalse(r.isInterruptive());
}
@Test
@@ -906,6 +954,7 @@
mService.buzzBeepBlinkLocked(r);
verifyNeverBeep();
+ assertFalse(r.isInterruptive());
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 7b2c040..4fe54b9 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -22,8 +22,19 @@
import static android.app.NotificationManager.IMPORTANCE_MAX;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
import static android.content.pm.PackageManager.FEATURE_WATCH;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
+import static android.os.Build.VERSION_CODES.O_MR1;
+import static android.os.Build.VERSION_CODES.P;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -2530,4 +2541,125 @@
verify(mAm, times(1)).revokeUriPermissionFromOwner(any(), eq(message1.getDataUri()),
anyInt(), anyInt());
}
+
+ @Test
+ public void testSetNotificationPolicy_preP_setOldFields() {
+ ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
+ mService.mZenModeHelper = mZenModeHelper;
+ NotificationManager.Policy userPolicy =
+ new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
+ when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
+
+ NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
+ SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
+
+ int expected = SUPPRESSED_EFFECT_BADGE
+ | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
+ | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
+ | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
+ int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testSetNotificationPolicy_preP_setNewFields() {
+ ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
+ mService.mZenModeHelper = mZenModeHelper;
+ NotificationManager.Policy userPolicy =
+ new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
+ when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
+
+ NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
+ SUPPRESSED_EFFECT_NOTIFICATION_LIST);
+
+ int expected = SUPPRESSED_EFFECT_BADGE;
+ int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testSetNotificationPolicy_preP_setOldNewFields() {
+ ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
+ mService.mZenModeHelper = mZenModeHelper;
+ NotificationManager.Policy userPolicy =
+ new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
+ when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
+
+ NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
+ SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
+
+ int expected =
+ SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK;
+ int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testSetNotificationPolicy_P_setOldFields() {
+ ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
+ mService.mZenModeHelper = mZenModeHelper;
+ NotificationManager.Policy userPolicy =
+ new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
+ when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
+
+ NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
+ SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
+
+ int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
+ | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
+ | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
+ int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testSetNotificationPolicy_P_setNewFields() {
+ ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
+ mService.mZenModeHelper = mZenModeHelper;
+ NotificationManager.Policy userPolicy =
+ new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
+ when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
+
+ NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
+ SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT
+ | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
+
+ int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF
+ | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS
+ | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
+ int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testSetNotificationPolicy_P_setOldNewFields() {
+ ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
+ mService.mZenModeHelper = mZenModeHelper;
+ NotificationManager.Policy userPolicy =
+ new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
+ when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
+
+ NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
+ SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
+
+ int expected = SUPPRESSED_EFFECT_STATUS_BAR;
+ int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
+
+ assertEquals(expected, actual);
+
+ appPolicy = new NotificationManager.Policy(0, 0, 0,
+ SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT
+ | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
+
+ expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT
+ | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
+ actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
+
+ assertEquals(expected, actual);
+ }
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeExtractorTest.java
index faba6b6..beff0d1 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeExtractorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeExtractorTest.java
@@ -17,6 +17,8 @@
package com.android.server.notification;
import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -57,6 +59,8 @@
assertFalse(r.isIntercepted());
when(mZenModeHelper.shouldIntercept(any())).thenReturn(true);
+ when(mZenModeHelper.getNotificationPolicy()).thenReturn(
+ new NotificationManager.Policy(0,0,0));
extractor.process(r);
@@ -70,7 +74,8 @@
NotificationRecord r = generateRecord();
when(mZenModeHelper.shouldIntercept(any())).thenReturn(false);
- when(mZenModeHelper.shouldSuppressWhenScreenOff()).thenReturn(false);
+ when(mZenModeHelper.getNotificationPolicy()).thenReturn(
+ new NotificationManager.Policy(0,0,0));
extractor.process(r);
@@ -84,13 +89,14 @@
NotificationRecord r = generateRecord();
when(mZenModeHelper.shouldIntercept(any())).thenReturn(true);
- when(mZenModeHelper.shouldSuppressWhenScreenOff()).thenReturn(true);
- when(mZenModeHelper.shouldSuppressWhenScreenOn()).thenReturn(true);
+ when(mZenModeHelper.getNotificationPolicy()).thenReturn(
+ new NotificationManager.Policy(0,0,0, SUPPRESSED_EFFECT_PEEK
+ | SUPPRESSED_EFFECT_NOTIFICATION_LIST));
extractor.process(r);
- assertEquals(NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF
- | NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON,
+ assertEquals(NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK
+ | NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST,
r.getSuppressedVisualEffects());
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
new file mode 100644
index 0000000..c0bd7cc
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2018 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 distriZenbuted on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification;
+
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
+import static android.provider.Settings.Global.ZEN_MODE_ALARMS;
+import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+import static android.provider.Settings.Global.ZEN_MODE_NO_INTERRUPTIONS;
+import static android.provider.Settings.Global.ZEN_MODE_OFF;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.media.AudioAttributes;
+import android.service.notification.StatusBarNotification;
+import android.service.notification.ZenModeConfig;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.util.NotificationMessagingUtil;
+import com.android.server.UiServiceTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class ZenModeFilteringTest extends UiServiceTestCase {
+
+ @Mock
+ private NotificationMessagingUtil mMessagingUtil;
+ private ZenModeFiltering mZenModeFiltering;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mZenModeFiltering = new ZenModeFiltering(mContext, mMessagingUtil);
+ }
+
+ private NotificationRecord getNotificationRecord() {
+ return getNotificationRecord(mock(NotificationChannel.class));
+ }
+
+ private NotificationRecord getNotificationRecord(NotificationChannel c) {
+ StatusBarNotification sbn = mock(StatusBarNotification.class);
+ when(sbn.getNotification()).thenReturn(mock(Notification.class));
+ return new NotificationRecord(mContext, sbn, c);
+ }
+
+ @Test
+ public void testIsMessage() {
+ NotificationRecord r = getNotificationRecord();
+
+ when(mMessagingUtil.isMessaging(any())).thenReturn(true);
+ assertTrue(mZenModeFiltering.isMessage(r));
+
+ when(mMessagingUtil.isMessaging(any())).thenReturn(false);
+ assertFalse(mZenModeFiltering.isMessage(r));
+ }
+
+ @Test
+ public void testIsAlarm() {
+ NotificationChannel c = mock(NotificationChannel.class);
+ when(c.getAudioAttributes()).thenReturn(new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_ALARM)
+ .build());
+ NotificationRecord r = getNotificationRecord(c);
+ assertTrue(mZenModeFiltering.isAlarm(r));
+
+ r = getNotificationRecord();
+ r.sbn.getNotification().category = Notification.CATEGORY_ALARM;
+ assertTrue(mZenModeFiltering.isAlarm(r));
+ }
+
+ @Test
+ public void testIsAlarm_wrongCategory() {
+ NotificationRecord r = getNotificationRecord();
+ r.sbn.getNotification().category = Notification.CATEGORY_CALL;
+ assertFalse(mZenModeFiltering.isAlarm(r));
+ }
+
+ @Test
+ public void testIsAlarm_wrongUsage() {
+ NotificationChannel c = mock(NotificationChannel.class);
+ when(c.getAudioAttributes()).thenReturn(new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_NOTIFICATION)
+ .build());
+ NotificationRecord r = getNotificationRecord(c);
+ assertFalse(mZenModeFiltering.isAlarm(r));
+ }
+
+ @Test
+ public void testSuppressDNDInfo_yes_VisEffectsAllowed() {
+ NotificationRecord r = getNotificationRecord();
+ when(r.sbn.getPackageName()).thenReturn("android");
+ when(r.sbn.getId()).thenReturn(SystemMessage.NOTE_ZEN_UPGRADE);
+ ZenModeConfig config = mock(ZenModeConfig.class);
+ config.suppressedVisualEffects = NotificationManager.Policy.getAllSuppressedVisualEffects()
+ - SUPPRESSED_EFFECT_STATUS_BAR;
+
+ assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config, r));
+ }
+
+ @Test
+ public void testSuppressDNDInfo_yes_WrongId() {
+ NotificationRecord r = getNotificationRecord();
+ when(r.sbn.getPackageName()).thenReturn("android");
+ when(r.sbn.getId()).thenReturn(SystemMessage.NOTE_ACCOUNT_CREDENTIAL_PERMISSION);
+ ZenModeConfig config = mock(ZenModeConfig.class);
+ config.suppressedVisualEffects = NotificationManager.Policy.getAllSuppressedVisualEffects();
+
+ assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config, r));
+ }
+
+ @Test
+ public void testSuppressDNDInfo_yes_WrongPackage() {
+ NotificationRecord r = getNotificationRecord();
+ when(r.sbn.getPackageName()).thenReturn("android2");
+ when(r.sbn.getId()).thenReturn(SystemMessage.NOTE_ZEN_UPGRADE);
+ ZenModeConfig config = mock(ZenModeConfig.class);
+ config.suppressedVisualEffects = NotificationManager.Policy.getAllSuppressedVisualEffects();
+
+ assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config, r));
+ }
+
+ @Test
+ public void testSuppressDNDInfo_no() {
+ NotificationRecord r = getNotificationRecord();
+ when(r.sbn.getPackageName()).thenReturn("android");
+ when(r.sbn.getId()).thenReturn(SystemMessage.NOTE_ZEN_UPGRADE);
+ ZenModeConfig config = mock(ZenModeConfig.class);
+ config.suppressedVisualEffects = NotificationManager.Policy.getAllSuppressedVisualEffects();
+
+ assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config, r));
+ assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_ALARMS, config, r));
+ assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_NO_INTERRUPTIONS, config, r));
+ }
+
+ @Test
+ public void testSuppressAnything_yes_ZenModeOff() {
+ NotificationRecord r = getNotificationRecord();
+ when(r.sbn.getPackageName()).thenReturn("bananas");
+ ZenModeConfig config = mock(ZenModeConfig.class);
+
+ assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_OFF, config, r));
+ }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 5bfa15a..be58fd2 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -16,6 +16,8 @@
package com.android.server.notification;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
+
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertEquals;
import static junit.framework.TestCase.assertTrue;
@@ -33,7 +35,9 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.AppOpsManager;
import android.app.NotificationManager;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
@@ -48,8 +52,11 @@
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.util.Xml;
+import com.android.internal.R;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.util.FastXmlSerializer;
import com.android.server.UiServiceTestCase;
import android.util.Slog;
@@ -58,6 +65,13 @@
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -80,12 +94,27 @@
mContext = spy(getContext());
mContentResolver = mContext.getContentResolver();
when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getString(R.string.zen_mode_default_every_night_name)).thenReturn("night");
+ when(mResources.getString(R.string.zen_mode_default_events_name)).thenReturn("events");
when(mContext.getSystemService(NotificationManager.class)).thenReturn(mNotificationManager);
mZenModeHelperSpy = spy(new ZenModeHelper(mContext, mTestableLooper.getLooper(),
mConditionProviders));
}
+ private ByteArrayOutputStream writeXmlAndPurge(boolean forBackup)
+ throws Exception {
+ XmlSerializer serializer = new FastXmlSerializer();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
+ serializer.startDocument(null, true);
+ mZenModeHelperSpy.writeXml(serializer, forBackup);
+ serializer.endDocument();
+ serializer.flush();
+ mZenModeHelperSpy.setConfig(new ZenModeConfig(), "writing xml");
+ return baos;
+ }
+
@Test
public void testZenOff_NoMuteApplied() {
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_OFF;
@@ -132,6 +161,26 @@
}
@Test
+ public void testTotalSilence() {
+ mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_NO_INTERRUPTIONS;
+ mZenModeHelperSpy.applyRestrictions();
+
+ // Total silence will silence alarms, media and system noises (but not vibrations)
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ AudioAttributes.USAGE_ALARM);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ AudioAttributes.USAGE_MEDIA);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ AudioAttributes.USAGE_GAME);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ AudioAttributes.USAGE_ASSISTANCE_SONIFICATION, AppOpsManager.OP_PLAY_AUDIO);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ AudioAttributes.USAGE_ASSISTANCE_SONIFICATION, AppOpsManager.OP_VIBRATE);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ AudioAttributes.USAGE_UNKNOWN);
+ }
+
+ @Test
public void testAlarmsOnly_alarmMediaMuteNotApplied() {
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_ALARMS;
mZenModeHelperSpy.mConfig.allowAlarms = false;
@@ -151,9 +200,9 @@
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
AudioAttributes.USAGE_GAME);
- // Alarms only will silence system noises
+ // Alarms only will silence system noises (but not vibrations)
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
- AudioAttributes.USAGE_ASSISTANCE_SONIFICATION);
+ AudioAttributes.USAGE_ASSISTANCE_SONIFICATION, AppOpsManager.OP_PLAY_AUDIO);
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
AudioAttributes.USAGE_UNKNOWN);
}
@@ -200,6 +249,7 @@
@Test
public void testZenAllCannotBypass() {
// Only audio attributes with SUPPRESIBLE_NEVER can bypass
+ // with special case USAGE_ASSISTANCE_SONIFICATION
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowAlarms = false;
mZenModeHelperSpy.mConfig.allowMedia = false;
@@ -219,9 +269,17 @@
mZenModeHelperSpy.applyRestrictions();
for (int usage : AudioAttributes.SDK_USAGES) {
- boolean shouldMute = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage)
- != AudioAttributes.SUPPRESSIBLE_NEVER;
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(shouldMute, usage);
+ if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
+ // only mute audio, not vibrations
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, usage,
+ AppOpsManager.OP_PLAY_AUDIO);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, usage,
+ AppOpsManager.OP_VIBRATE);
+ } else {
+ boolean shouldMute = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage)
+ != AudioAttributes.SUPPRESSIBLE_NEVER;
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(shouldMute, usage);
+ }
}
}
@@ -497,4 +555,71 @@
verify(mAudioManager, never()).setRingerModeInternal(AudioManager.RINGER_MODE_NORMAL,
mZenModeHelperSpy.TAG);
}
+
+ @Test
+ public void testParcelConfig() {
+ mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mConfig.allowAlarms = false;
+ mZenModeHelperSpy.mConfig.allowMedia = false;
+ mZenModeHelperSpy.mConfig.allowSystem = false;
+ mZenModeHelperSpy.mConfig.allowReminders = true;
+ mZenModeHelperSpy.mConfig.allowCalls = true;
+ mZenModeHelperSpy.mConfig.allowMessages = true;
+ mZenModeHelperSpy.mConfig.allowEvents = true;
+ mZenModeHelperSpy.mConfig.allowRepeatCallers= true;
+ mZenModeHelperSpy.mConfig.allowWhenScreenOff = true;
+ mZenModeHelperSpy.mConfig.allowWhenScreenOn = true;
+ mZenModeHelperSpy.mConfig.suppressedVisualEffects = SUPPRESSED_EFFECT_BADGE;
+ mZenModeHelperSpy.mConfig.manualRule = new ZenModeConfig.ZenRule();
+ mZenModeHelperSpy.mConfig.manualRule.component = new ComponentName("a", "a");
+ mZenModeHelperSpy.mConfig.manualRule.enabled = true;
+ mZenModeHelperSpy.mConfig.manualRule.snoozing = true;
+
+ ZenModeConfig actual = mZenModeHelperSpy.mConfig.copy();
+
+ assertEquals(mZenModeHelperSpy.mConfig, actual);
+ }
+
+ @Test
+ public void testWriteXml() throws Exception {
+ mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mConfig.allowAlarms = false;
+ mZenModeHelperSpy.mConfig.allowMedia = false;
+ mZenModeHelperSpy.mConfig.allowSystem = false;
+ mZenModeHelperSpy.mConfig.allowReminders = true;
+ mZenModeHelperSpy.mConfig.allowCalls = true;
+ mZenModeHelperSpy.mConfig.allowMessages = true;
+ mZenModeHelperSpy.mConfig.allowEvents = true;
+ mZenModeHelperSpy.mConfig.allowRepeatCallers= true;
+ mZenModeHelperSpy.mConfig.allowWhenScreenOff = true;
+ mZenModeHelperSpy.mConfig.allowWhenScreenOn = true;
+ mZenModeHelperSpy.mConfig.suppressedVisualEffects = SUPPRESSED_EFFECT_BADGE;
+ mZenModeHelperSpy.mConfig.manualRule = new ZenModeConfig.ZenRule();
+ mZenModeHelperSpy.mConfig.manualRule.zenMode =
+ Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mConfig.manualRule.component = new ComponentName("a", "a");
+ mZenModeHelperSpy.mConfig.manualRule.enabled = true;
+ mZenModeHelperSpy.mConfig.manualRule.snoozing = true;
+
+ ZenModeConfig expected = mZenModeHelperSpy.mConfig.copy();
+
+ ByteArrayOutputStream baos = writeXmlAndPurge(false);
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(new BufferedInputStream(
+ new ByteArrayInputStream(baos.toByteArray())), null);
+ parser.nextTag();
+ mZenModeHelperSpy.readXml(parser, false);
+
+ assertEquals(expected, mZenModeHelperSpy.mConfig);
+ }
+
+ @Test
+ public void testPolicyReadsSuppressedEffects() {
+ mZenModeHelperSpy.mConfig.allowWhenScreenOff = true;
+ mZenModeHelperSpy.mConfig.allowWhenScreenOn = true;
+ mZenModeHelperSpy.mConfig.suppressedVisualEffects = SUPPRESSED_EFFECT_BADGE;
+
+ NotificationManager.Policy policy = mZenModeHelperSpy.getNotificationPolicy();
+ assertEquals(SUPPRESSED_EFFECT_BADGE, policy.suppressedVisualEffects);
+ }
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index a302578..9be9f3f 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -506,6 +506,7 @@
IndentingPrintWriter idpw = new IndentingPrintWriter(pw, " ");
boolean checkin = false;
+ boolean compact = false;
String pkg = null;
if (args != null) {
@@ -513,6 +514,9 @@
String arg = args[i];
if ("--checkin".equals(arg)) {
checkin = true;
+ } else
+ if ("-c".equals(arg)) {
+ compact = true;
} else if ("flush".equals(arg)) {
flushToDiskLocked();
pw.println("Flushed stats to disk");
@@ -534,7 +538,7 @@
if (checkin) {
mUserState.valueAt(i).checkin(idpw);
} else {
- mUserState.valueAt(i).dump(idpw, pkg);
+ mUserState.valueAt(i).dump(idpw, pkg, compact);
idpw.println();
}
mAppStandby.dumpUser(idpw, userId, pkg);
@@ -986,6 +990,25 @@
}
@Override
+ public void reportInterruptiveNotification(String packageName, String channelId,
+ int userId) {
+ if (packageName == null || channelId == null) {
+ Slog.w(TAG, "Event reported without a package name or a channel ID");
+ return;
+ }
+
+ UsageEvents.Event event = new UsageEvents.Event();
+ event.mPackage = packageName.intern();
+ event.mNotificationChannelId = channelId.intern();
+
+ // This will later be converted to system time.
+ event.mTimeStamp = SystemClock.elapsedRealtime();
+
+ event.mEventType = Event.NOTIFICATION_INTERRUPTION;
+ mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
+ }
+
+ @Override
public void reportShortcutUsage(String packageName, String shortcutId, int userId) {
if (packageName == null || shortcutId == null) {
Slog.w(TAG, "Event reported without a package name or a shortcut ID");
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 29c5ee8..d974282 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -47,7 +47,7 @@
class UserUsageStatsService {
private static final String TAG = "UsageStatsService";
private static final boolean DEBUG = UsageStatsService.DEBUG;
- private static final SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd/HH:mm:ss");
+ private static final SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final int sDateFormatFlags =
DateUtils.FORMAT_SHOW_DATE
| DateUtils.FORMAT_SHOW_TIME
@@ -516,25 +516,28 @@
mDatabase.checkinDailyFiles(new UsageStatsDatabase.CheckinAction() {
@Override
public boolean checkin(IntervalStats stats) {
- printIntervalStats(pw, stats, true, null);
+ printIntervalStats(pw, stats, false, false, null);
return true;
}
});
}
void dump(IndentingPrintWriter pw, String pkg) {
- printLast24HrEvents(pw, true, pkg);
+ dump(pw, pkg, false);
+ }
+ void dump(IndentingPrintWriter pw, String pkg, boolean compact) {
+ printLast24HrEvents(pw, !compact, pkg);
for (int interval = 0; interval < mCurrentStats.length; interval++) {
pw.print("In-memory ");
pw.print(intervalToString(interval));
pw.println(" stats");
- printIntervalStats(pw, mCurrentStats[interval], false, pkg);
+ printIntervalStats(pw, mCurrentStats[interval], !compact, true, pkg);
}
}
private String formatDateTime(long dateTime, boolean pretty) {
if (pretty) {
- return "\"" + DateFormat.format("yyyy-MM-dd HH:mm:ss", dateTime).toString() + "\"";
+ return "\"" + sDateFormat.format(dateTime)+ "\"";
}
return Long.toString(dateTime);
}
@@ -623,8 +626,7 @@
}
void printIntervalStats(IndentingPrintWriter pw, IntervalStats stats,
- boolean checkin, String pkg) {
- boolean prettyDates = !checkin;
+ boolean prettyDates, boolean skipEvents, String pkg) {
if (prettyDates) {
pw.printPair("timeRange", "\"" + DateUtils.formatDateRange(mContext,
stats.beginTime, stats.endTime, sDateFormatFlags) + "\"");
@@ -699,7 +701,7 @@
// The last 24 hours of events is already printed in the non checkin dump
// No need to repeat here.
- if (checkin) {
+ if (!skipEvents) {
pw.println("events");
pw.increaseIndent();
final TimeSparseArray<UsageEvents.Event> events = stats.events;
@@ -757,6 +759,8 @@
return "NOTIFICATION_SEEN";
case UsageEvents.Event.STANDBY_BUCKET_CHANGED:
return "STANDBY_BUCKET_CHANGED";
+ case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+ return "NOTIFICATION_INTERRUPTION";
default:
return "UNKNOWN";
}
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index fb52ff7..4f78c4c 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -3380,7 +3380,7 @@
* on the given subscriptionId
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
- * carrier identity {@link TelephonyManager#getAndroidCarrierIdForSubscription()}
+ * carrier identity {@link TelephonyManager#getSimCarrierId()}
* while your app is running. You can also use a {@link JobService} to ensure your app
* is notified of changes to the {@link Uri} even when it is not running.
* Note, however, that using a {@link JobService} does not guarantee timely delivery of
@@ -3396,14 +3396,14 @@
/**
* A user facing carrier name.
- * @see TelephonyManager#getAndroidCarrierNameForSubscription()
+ * @see TelephonyManager#getSimCarrierIdName()
* <P>Type: TEXT </P>
*/
public static final String CARRIER_NAME = "carrier_name";
/**
* A unique carrier id
- * @see TelephonyManager#getAndroidCarrierIdForSubscription()
+ * @see TelephonyManager#getSimCarrierId()
* <P>Type: INTEGER </P>
*/
public static final String CARRIER_ID = "carrier_id";
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index 7cd16128..cac9f2b 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -30,6 +30,9 @@
public static final int EUTRAN = 3;
public static final int CDMA2000 = 4;
public static final int IWLAN = 5;
+
+ /** @hide */
+ private AccessNetworkType() {};
}
/**
@@ -42,6 +45,9 @@
public static final int WWAN = 1;
/** Wireless Local Area Networks (i.e. Wifi) */
public static final int WLAN = 2;
+
+ /** @hide */
+ private TransportType() {};
}
/**
@@ -63,6 +69,9 @@
public static final int BAND_DCS1800 = 12;
public static final int BAND_PCS1900 = 13;
public static final int BAND_ER900 = 14;
+
+ /** @hide */
+ private GeranBand() {};
}
/**
@@ -92,6 +101,9 @@
/** band 23, 24 are reserved */
public static final int BAND_25 = 25;
public static final int BAND_26 = 26;
+
+ /** @hide */
+ private UtranBand() {};
}
/**
@@ -147,6 +159,9 @@
public static final int BAND_66 = 66;
public static final int BAND_68 = 68;
public static final int BAND_70 = 70;
+
+ /** @hide */
+ private EutranBand() {};
}
/**
@@ -179,5 +194,11 @@
public static final int BAND_19 = 20;
public static final int BAND_20 = 21;
public static final int BAND_21 = 22;
+
+ /** @hide */
+ private CdmaBands() {};
}
+
+ /** @hide */
+ private AccessNetworkConstants() {};
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index d43db32..eebe2a1 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1285,13 +1285,38 @@
/**
* The duration in seconds that platform call and message blocking is disabled after the user
- * contacts emergency services. Platform considers values in the range 0 to 604800 (one week) as
- * valid. See {@link android.provider.BlockedNumberContract#isBlocked(Context, String)}).
+ * contacts emergency services. Platform considers values for below cases:
+ * 1) 0 <= VALUE <= 604800(one week): the value will be used as the duration directly.
+ * 2) VALUE > 604800(one week): will use the default value as duration instead.
+ * 3) VALUE < 0: block will be disabled forever until user re-eanble block manually,
+ * the suggested value to disable forever is -1.
+ * See {@code android.provider.BlockedNumberContract#notifyEmergencyContact(Context)}
+ * See {@code android.provider.BlockedNumberContract#isBlocked(Context, String)}.
*/
public static final String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT =
"duration_blocking_disabled_after_emergency_int";
/**
+ * Determines whether to enable enhanced call blocking feature on the device.
+ * @see SystemContract#ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED
+ * @see SystemContract#ENHANCED_SETTING_KEY_BLOCK_PRIVATE
+ * @see SystemContract#ENHANCED_SETTING_KEY_BLOCK_PAYPHONE
+ * @see SystemContract#ENHANCED_SETTING_KEY_BLOCK_UNKNOWN
+ *
+ * <p>
+ * 1. For Single SIM(SS) device, it can be customized in both carrier_config_mccmnc.xml
+ * and vendor.xml.
+ * <p>
+ * 2. For Dual SIM(DS) device, it should be customized in vendor.xml, since call blocking
+ * function is used regardless of SIM.
+ * <p>
+ * If {@code true} enable enhanced call blocking feature on the device, {@code false} otherwise.
+ * @hide
+ */
+ public static final String KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL =
+ "support_enhanced_call_blocking_bool";
+
+ /**
* For carriers which require an empty flash to be sent before sending the normal 3-way calling
* flash, the duration in milliseconds of the empty flash to send. When {@code 0}, no empty
* flash is sent.
@@ -2052,6 +2077,7 @@
sDefaults.putBoolean(KEY_SUPPORT_DIRECT_FDN_DIALING_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL, false);
sDefaults.putBoolean(KEY_SKIP_CF_FAIL_TO_DISABLE_DIALOG_BOOL, false);
+ sDefaults.putBoolean(KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL, false);
// MMS defaults
sDefaults.putBoolean(KEY_MMS_ALIAS_ENABLED_BOOL, false);
diff --git a/telephony/java/android/telephony/MbmsDownloadSession.java b/telephony/java/android/telephony/MbmsDownloadSession.java
index ce1b80c..81a966b 100644
--- a/telephony/java/android/telephony/MbmsDownloadSession.java
+++ b/telephony/java/android/telephony/MbmsDownloadSession.java
@@ -131,6 +131,14 @@
*/
public static final String DEFAULT_TOP_LEVEL_TEMP_DIRECTORY = "androidMbmsTempFileRoot";
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {RESULT_SUCCESSFUL, RESULT_CANCELLED, RESULT_EXPIRED, RESULT_IO_ERROR,
+ RESULT_SERVICE_ID_NOT_DEFINED, RESULT_DOWNLOAD_FAILURE, RESULT_OUT_OF_STORAGE,
+ RESULT_FILE_ROOT_UNREACHABLE}, prefix = { "RESULT_" })
+ public @interface DownloadResultCode{}
+
/**
* Indicates that the download was successful.
*/
diff --git a/telephony/java/android/telephony/NetworkScan.java b/telephony/java/android/telephony/NetworkScan.java
index a277212..073c313 100644
--- a/telephony/java/android/telephony/NetworkScan.java
+++ b/telephony/java/android/telephony/NetworkScan.java
@@ -29,9 +29,9 @@
/**
* The caller of
- * {@link TelephonyManager#requestNetworkScan(NetworkScanRequest, NetworkScanCallback)}
+ * {@link TelephonyManager#requestNetworkScan(NetworkScanRequest, Executor, NetworkScanCallback)}
* will receive an instance of {@link NetworkScan}, which contains a callback method
- * {@link #stop()} for stopping the in-progress scan.
+ * {@link #stopScan()} for stopping the in-progress scan.
*/
public class NetworkScan {
@@ -106,16 +106,26 @@
* Use this method to stop an ongoing scan. When user requests a new scan, a {@link NetworkScan}
* object will be returned, and the user can stop the scan by calling this method.
*/
- public void stop() throws RemoteException {
+ public void stopScan() {
+ ITelephony telephony = getITelephony();
+ if (telephony == null) {
+ Rlog.e(TAG, "Failed to get the ITelephony instance.");
+ }
try {
- ITelephony telephony = getITelephony();
- if (telephony != null) {
- telephony.stopNetworkScan(mSubId, mScanId);
- } else {
- throw new RemoteException("Failed to get the ITelephony instance.");
- }
+ telephony.stopNetworkScan(mSubId, mScanId);
} catch (RemoteException ex) {
Rlog.e(TAG, "stopNetworkScan RemoteException", ex);
+ } catch (RuntimeException ex) {
+ Rlog.e(TAG, "stopNetworkScan RuntimeException", ex);
+ }
+ }
+
+ /** @deprecated Use {@link #stopScan()} */
+ @Deprecated
+ public void stop() throws RemoteException {
+ try {
+ stopScan();
+ } catch (RuntimeException ex) {
throw new RemoteException("Failed to stop the network scan with id " + mScanId);
}
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 4a61437..ef66ed7 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -25,6 +25,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressAutoDoc;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.app.BroadcastOptions;
@@ -42,7 +43,6 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.ServiceManager.ServiceNotFoundException;
import android.util.DisplayMetrics;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
@@ -59,9 +59,6 @@
/**
* SubscriptionManager is the application interface to SubscriptionController
* and provides information about the current Telephony Subscriptions.
- * <p>
- * All SDK public methods require android.Manifest.permission.READ_PHONE_STATE unless otherwise
- * specified.
*/
@SystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)
public class SubscriptionManager {
@@ -612,6 +609,8 @@
* @param listener an instance of {@link OnSubscriptionsChangedListener} with
* onSubscriptionsChanged overridden.
*/
+ // TODO(b/70041899): Find a way to extend this to carrier-privileged apps.
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) {
String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>";
if (DBG) {
@@ -660,9 +659,15 @@
/**
* Get the active SubscriptionInfo with the input subId.
*
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges}).
+ *
* @param subId The unique SubscriptionInfo key in database.
* @return SubscriptionInfo, maybe null if its not active.
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public SubscriptionInfo getActiveSubscriptionInfo(int subId) {
if (VDBG) logd("[getActiveSubscriptionInfo]+ subId=" + subId);
if (!isValidSubscriptionId(subId)) {
@@ -716,9 +721,16 @@
/**
* Get the active SubscriptionInfo associated with the slotIndex
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges}).
+ *
* @param slotIndex the slot which the subscription is inserted
* @return SubscriptionInfo, maybe null if its not active
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex) {
if (VDBG) logd("[getActiveSubscriptionInfoForSimSlotIndex]+ slotIndex=" + slotIndex);
if (!isValidSlotIndex(slotIndex)) {
@@ -770,6 +782,11 @@
* Get the SubscriptionInfo(s) of the currently inserted SIM(s). The records will be sorted
* by {@link SubscriptionInfo#getSimSlotIndex} then by {@link SubscriptionInfo#getSubscriptionId}.
*
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, only records accessible
+ * to the calling app are returned.
+ *
* @return Sorted list of the currently {@link SubscriptionInfo} records available on the device.
* <ul>
* <li>
@@ -786,6 +803,8 @@
* </li>
* </ul>
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public List<SubscriptionInfo> getActiveSubscriptionInfoList() {
List<SubscriptionInfo> result = null;
@@ -928,10 +947,18 @@
}
/**
+ *
+ * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, the count will include
+ * only those subscriptions accessible to the caller.
+ *
* @return the current number of active subscriptions. There is no guarantee the value
* returned by this method will be the same as the length of the list returned by
* {@link #getActiveSubscriptionInfoList}.
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public int getActiveSubscriptionInfoCount() {
int result = 0;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index af3a0bb..7add893 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -23,6 +23,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressAutoDoc;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
@@ -34,6 +35,7 @@
import android.net.ConnectivityManager;
import android.net.NetworkStats;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.BatteryStats;
import android.os.Bundle;
import android.os.Handler;
@@ -52,7 +54,6 @@
import android.telephony.ims.aidl.IImsMmTelFeature;
import android.telephony.ims.aidl.IImsRcsFeature;
import android.telephony.ims.aidl.IImsRegistration;
-import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.Log;
@@ -74,6 +75,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.Executor;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -1080,7 +1082,7 @@
/**
* An int extra used with {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} which indicates
- * the updated carrier id {@link TelephonyManager#getAndroidCarrierIdForSubscription()} of
+ * the updated carrier id {@link TelephonyManager#getSimCarrierId()} of
* the current subscription.
* <p>Will be {@link TelephonyManager#UNKNOWN_CARRIER_ID} if the subscription is unavailable or
* the carrier cannot be identified.
@@ -1090,7 +1092,7 @@
/**
* An string extra used with {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} which
* indicates the updated carrier name of the current subscription.
- * {@see TelephonyManager#getSubscriptionCarrierName()}
+ * {@see TelephonyManager#getSimCarrierIdName()}
* <p>Carrier name is a user-facing name of the carrier id {@link #EXTRA_CARRIER_ID},
* usually the brand name of the subsidiary (e.g. T-Mobile).
*/
@@ -1112,7 +1114,11 @@
* Returns the software version number for the device, for example,
* the IMEI/SV for GSM phones. Return null if the software version is
* not available.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getDeviceSoftwareVersion() {
return getDeviceSoftwareVersion(getSlotIndex());
@@ -1144,10 +1150,14 @@
* Returns the unique device ID, for example, the IMEI for GSM and the MEID
* or ESN for CDMA phones. Return null if device ID is not available.
*
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
* @deprecated Use (@link getImei} which returns IMEI for GSM or (@link getMeid} which returns
* MEID for CDMA.
*/
@Deprecated
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getDeviceId() {
try {
@@ -1166,12 +1176,16 @@
* Returns the unique device ID of a subscription, for example, the IMEI for
* GSM and the MEID for CDMA phones. Return null if device ID is not available.
*
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
* @param slotIndex of which deviceID is returned
*
* @deprecated Use (@link getImei} which returns IMEI for GSM or (@link getMeid} which returns
* MEID for CDMA.
*/
@Deprecated
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getDeviceId(int slotIndex) {
// FIXME this assumes phoneId == slotIndex
@@ -1190,7 +1204,11 @@
/**
* Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not
* available.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getImei() {
return getImei(getSlotIndex());
@@ -1200,8 +1218,12 @@
* Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not
* available.
*
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
* @param slotIndex of which IMEI is returned
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getImei(int slotIndex) {
ITelephony telephony = getITelephony();
@@ -1218,7 +1240,11 @@
/**
* Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getMeid() {
return getMeid(getSlotIndex());
@@ -1227,8 +1253,12 @@
/**
* Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available.
*
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
* @param slotIndex of which MEID is returned
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getMeid(int slotIndex) {
ITelephony telephony = getITelephony();
@@ -1245,10 +1275,11 @@
/**
* Returns the Network Access Identifier (NAI). Return null if NAI is not available.
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getNai() {
return getNaiBySubscriberId(getSubId());
@@ -1749,6 +1780,7 @@
* @see #createForSubscriptionId(int)
* @see #createForPhoneAccountHandle(PhoneAccountHandle)
*/
+ // TODO(b/73136824, b/70041899): Permit carrier-privileged callers as well.
@WorkerThread
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public PersistableBundle getCarrierConfig() {
@@ -1947,6 +1979,9 @@
* If this object has been created with {@link #createForSubscriptionId}, applies to the given
* subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
*
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
* @return the network type
*
* @see #NETWORK_TYPE_UNKNOWN
@@ -1966,6 +2001,7 @@
* @see #NETWORK_TYPE_EHRPD
* @see #NETWORK_TYPE_HSPAP
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public int getDataNetworkType() {
return getDataNetworkType(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
@@ -2000,7 +2036,11 @@
/**
* Returns the NETWORK_TYPE_xxxx for voice
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public int getVoiceNetworkType() {
return getVoiceNetworkType(getSubId());
@@ -2586,7 +2626,11 @@
/**
* Returns the serial number of the SIM, if applicable. Return null if it is
* unavailable.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getSimSerialNumber() {
return getSimSerialNumber(getSubId());
@@ -2711,7 +2755,11 @@
/**
* Returns the unique subscriber ID, for example, the IMSI for a GSM phone.
* Return null if it is unavailable.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getSubscriberId() {
return getSubscriberId(getSubId());
@@ -2754,18 +2802,17 @@
* @return ImsiEncryptionInfo Carrier specific information that will be used to encrypt the
* IMSI and IMPI. This includes the public key and the key identifier. This information
* will be stored in the device keystore. The system will return a null when no key was
- * found, and the carrier does not require a key. The system will throw the following
- * exceptions:
- * 1. IllegalArgumentException when an invalid key is sent.
- * 2. RuntimeException if the key is required but not found; and also if there was an
- * internal exception.
+ * found, and the carrier does not require a key. The system will throw
+ * IllegalArgumentException when an invalid key is sent or when key is required but
+ * not found.
* @hide
*/
public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType) {
try {
IPhoneSubInfo info = getSubscriberInfo();
if (info == null) {
- throw new RuntimeException("IMSI error: Subscriber Info is null");
+ Rlog.e(TAG,"IMSI error: Subscriber Info is null");
+ return null;
}
int subId = getSubId(SubscriptionManager.getDefaultDataSubscriptionId());
if (keyType != KEY_TYPE_EPDG && keyType != KEY_TYPE_WLAN) {
@@ -2773,20 +2820,18 @@
}
ImsiEncryptionInfo imsiEncryptionInfo = info.getCarrierInfoForImsiEncryption(
subId, keyType, mContext.getOpPackageName());
- if (imsiEncryptionInfo == null
- && isImsiEncryptionRequired(subId, keyType)) {
+ if (imsiEncryptionInfo == null && isImsiEncryptionRequired(subId, keyType)) {
Rlog.e(TAG, "IMSI error: key is required but not found");
- throw new RuntimeException("IMSI error: key is required but not found");
+ throw new IllegalArgumentException("IMSI error: key is required but not found");
}
return imsiEncryptionInfo;
} catch (RemoteException ex) {
Rlog.e(TAG, "getCarrierInfoForImsiEncryption RemoteException" + ex);
- throw new RuntimeException("IMSI error: Remote Exception");
} catch (NullPointerException ex) {
// This could happen before phone restarts due to crashing
Rlog.e(TAG, "getCarrierInfoForImsiEncryption NullPointerException" + ex);
- throw new RuntimeException("IMSI error: Null Pointer exception");
}
+ return null;
}
/**
@@ -2802,17 +2847,16 @@
try {
IPhoneSubInfo info = getSubscriberInfo();
if (info == null) {
- throw new RuntimeException("IMSI error: Subscriber Info is null");
+ Rlog.e(TAG, "IMSI error: Subscriber Info is null");
+ return;
}
int subId = getSubId(SubscriptionManager.getDefaultDataSubscriptionId());
info.resetCarrierKeysForImsiEncryption(subId, mContext.getOpPackageName());
} catch (RemoteException ex) {
Rlog.e(TAG, "getCarrierInfoForImsiEncryption RemoteException" + ex);
- throw new RuntimeException("IMSI error: Remote Exception");
} catch (NullPointerException ex) {
// This could happen before phone restarts due to crashing
Rlog.e(TAG, "getCarrierInfoForImsiEncryption NullPointerException" + ex);
- throw new RuntimeException("IMSI error: Null Pointer exception");
}
}
@@ -2879,7 +2923,11 @@
/**
* Returns the Group Identifier Level1 for a GSM phone.
* Return null if it is unavailable.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getGroupIdLevel1() {
try {
@@ -2920,9 +2968,15 @@
/**
* Returns the phone number string for line 1, for example, the MSISDN
* for a GSM phone. Return null if it is unavailable.
- * <p>
- * The default SMS app can also use this.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE},
+ * {@link android.Manifest.permission#READ_SMS READ_SMS},
+ * {@link android.Manifest.permission#READ_PHONE_NUMBERS READ_PHONE_NUMBERS},
+ * that the caller is the default SMS app,
+ * or that the caller has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges or default SMS app
@RequiresPermission(anyOf = {
android.Manifest.permission.READ_PHONE_STATE,
android.Manifest.permission.READ_SMS,
@@ -2977,8 +3031,7 @@
* change the actual MSISDN/MDN. To unset alphatag or number, pass in a null
* value.
*
- * <p>Requires that the calling app has carrier privileges.
- * @see #hasCarrierPrivileges
+ * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param alphaTag alpha-tagging of the dailing nubmer
* @param number The dialing number
@@ -2994,8 +3047,7 @@
* change the actual MSISDN/MDN. To unset alphatag or number, pass in a null
* value.
*
- * <p>Requires that the calling app has carrier privileges.
- * @see #hasCarrierPrivileges
+ * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId the subscriber that the alphatag and dialing number belongs to.
* @param alphaTag alpha-tagging of the dailing nubmer
@@ -3114,7 +3166,11 @@
/**
* Returns the voice mail number. Return null if it is unavailable.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getVoiceMailNumber() {
return getVoiceMailNumber(getSubId());
@@ -3175,8 +3231,7 @@
/**
* Sets the voice mail number.
*
- * <p>Requires that the calling app has carrier privileges.
- * @see #hasCarrierPrivileges
+ * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param alphaTag The alpha tag to display.
* @param number The voicemail number.
@@ -3188,8 +3243,7 @@
/**
* Sets the voicemail number for the given subscriber.
*
- * <p>Requires that the calling app has carrier privileges.
- * @see #hasCarrierPrivileges
+ * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription id.
* @param alphaTag The alpha tag to display.
@@ -3210,9 +3264,9 @@
/**
* Enables or disables the visual voicemail client for a phone account.
*
- * <p>Requires that the calling app is the default dialer, or has carrier privileges, or
- * has permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
- * @see #hasCarrierPrivileges
+ * <p>Requires that the calling app is the default dialer, or has carrier privileges (see
+ * {@link #hasCarrierPrivileges}), or has permission
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
*
* @param phoneAccountHandle the phone account to change the client state
* @param enabled the new state of the client
@@ -3275,11 +3329,15 @@
* to the TelephonyManager. Returns {@code null} when there is no package responsible for
* processing visual voicemail for the subscription.
*
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
* @see #createForSubscriptionId(int)
* @see #createForPhoneAccountHandle(PhoneAccountHandle)
* @see VisualVoicemailService
*/
@Nullable
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getVisualVoicemailPackageName() {
try {
@@ -3522,15 +3580,14 @@
* Sets the voice activation state
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges.
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
+ * calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param activationState The voice activation state
* @see #SIM_ACTIVATION_STATE_UNKNOWN
* @see #SIM_ACTIVATION_STATE_ACTIVATING
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
- * @see #hasCarrierPrivileges
* @hide
*/
@SystemApi
@@ -3543,8 +3600,8 @@
* Sets the voice activation state for the given subscriber.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges.
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
+ * calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription id.
* @param activationState The voice activation state of the given subscriber.
@@ -3552,7 +3609,6 @@
* @see #SIM_ACTIVATION_STATE_ACTIVATING
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
- * @see #hasCarrierPrivileges
* @hide
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -3570,8 +3626,8 @@
* Sets the data activation state
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges.
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
+ * calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param activationState The data activation state
* @see #SIM_ACTIVATION_STATE_UNKNOWN
@@ -3579,7 +3635,6 @@
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
* @see #SIM_ACTIVATION_STATE_RESTRICTED
- * @see #hasCarrierPrivileges
* @hide
*/
@SystemApi
@@ -3592,8 +3647,8 @@
* Sets the data activation state for the given subscriber.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges.
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
+ * calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription id.
* @param activationState The data activation state of the given subscriber.
@@ -3602,7 +3657,6 @@
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
* @see #SIM_ACTIVATION_STATE_RESTRICTED
- * @see #hasCarrierPrivileges
* @hide
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -3620,15 +3674,14 @@
* Returns the voice activation state
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
- * Or the calling app has carrier privileges.
+ * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @return voiceActivationState
* @see #SIM_ACTIVATION_STATE_UNKNOWN
* @see #SIM_ACTIVATION_STATE_ACTIVATING
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
- * @see #hasCarrierPrivileges
* @hide
*/
@SystemApi
@@ -3641,8 +3694,8 @@
* Returns the voice activation state for the given subscriber.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
- * Or the calling app has carrier privileges.
+ * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription id.
*
@@ -3651,7 +3704,6 @@
* @see #SIM_ACTIVATION_STATE_ACTIVATING
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
- * @see #hasCarrierPrivileges
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -3670,8 +3722,8 @@
* Returns the data activation state
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
- * Or the calling app has carrier privileges.
+ * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @return dataActivationState for the given subscriber
* @see #SIM_ACTIVATION_STATE_UNKNOWN
@@ -3679,7 +3731,6 @@
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
* @see #SIM_ACTIVATION_STATE_RESTRICTED
- * @see #hasCarrierPrivileges
* @hide
*/
@SystemApi
@@ -3692,8 +3743,8 @@
* Returns the data activation state for the given subscriber.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
- * Or the calling app has carrier privileges.
+ * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription id.
*
@@ -3703,7 +3754,6 @@
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
* @see #SIM_ACTIVATION_STATE_RESTRICTED
- * @see #hasCarrierPrivileges
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -3751,7 +3801,11 @@
/**
* Retrieves the alphabetic identifier associated with the voice
* mail number.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getVoiceMailAlphaTag() {
return getVoiceMailAlphaTag(getSubId());
@@ -3780,16 +3834,13 @@
}
/**
- * Send the special dialer code. The IPC caller must be the current default dialer or has
- * carrier privileges.
- * @see #hasCarrierPrivileges
+ * Send the special dialer code. The IPC caller must be the current default dialer or have
+ * carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param inputCode The special dialer code to send
*
* @throws SecurityException if the caller does not have carrier privileges or is not the
* current default dialer
- *
- * @throws IllegalStateException if telephony service is unavailable.
*/
public void sendDialerSpecialCode(String inputCode) {
try {
@@ -3797,10 +3848,8 @@
telephony.sendDialerSpecialCode(mContext.getOpPackageName(), inputCode);
} catch (RemoteException ex) {
// This could happen if binder process crashes.
- ex.rethrowFromSystemServer();
} catch (NullPointerException ex) {
// This could happen before phone restarts due to crashing
- throw new IllegalStateException("Telephony service unavailable");
}
}
@@ -4310,8 +4359,8 @@
* Input parameters equivalent to TS 27.007 AT+CCHO command.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param AID Application id. See ETSI 102.221 and 101.220.
* @return an IccOpenLogicalChannelResponse object.
@@ -4328,8 +4377,8 @@
* Input parameters equivalent to TS 27.007 AT+CCHO command.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param AID Application id. See ETSI 102.221 and 101.220.
* @param p2 P2 parameter (described in ISO 7816-4).
@@ -4345,8 +4394,8 @@
* Input parameters equivalent to TS 27.007 AT+CCHO command.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription to use.
* @param AID Application id. See ETSI 102.221 and 101.220.
@@ -4371,8 +4420,8 @@
* Input parameters equivalent to TS 27.007 AT+CCHC command.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param channel is the channel id to be closed as retruned by a successful
* iccOpenLogicalChannel.
@@ -4388,8 +4437,8 @@
* Input parameters equivalent to TS 27.007 AT+CCHC command.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription to use.
* @param channel is the channel id to be closed as retruned by a successful
@@ -4414,8 +4463,8 @@
* Input parameters equivalent to TS 27.007 AT+CGLA command.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param channel is the channel id to be closed as returned by a successful
* iccOpenLogicalChannel.
@@ -4441,8 +4490,8 @@
* Input parameters equivalent to TS 27.007 AT+CGLA command.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription to use.
* @param channel is the channel id to be closed as returned by a successful
@@ -4477,8 +4526,8 @@
* Input parameters equivalent to TS 27.007 AT+CSIM command.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param cla Class of the APDU command.
* @param instruction Instruction of the APDU command.
@@ -4502,8 +4551,8 @@
* Input parameters equivalent to TS 27.007 AT+CSIM command.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription to use.
* @param cla Class of the APDU command.
@@ -4534,8 +4583,8 @@
* Returns the response APDU for a command APDU sent through SIM_IO.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param fileID
* @param command
@@ -4554,8 +4603,8 @@
* Returns the response APDU for a command APDU sent through SIM_IO.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription to use.
* @param fileID
@@ -4583,8 +4632,8 @@
* Send ENVELOPE to the SIM and return the response.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param content String containing SAT/USAT response in hexadecimal
* format starting with command tag. See TS 102 223 for
@@ -4601,8 +4650,8 @@
* Send ENVELOPE to the SIM and return the response.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription to use.
* @param content String containing SAT/USAT response in hexadecimal
@@ -4627,10 +4676,10 @@
/**
* Read one of the NV items defined in com.android.internal.telephony.RadioNVItems.
* Used for device configuration by some CDMA operators.
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param itemID the ID of the item to read.
* @return the NV item as a String, or null on any failure.
@@ -4653,10 +4702,10 @@
/**
* Write one of the NV items defined in com.android.internal.telephony.RadioNVItems.
* Used for device configuration by some CDMA operators.
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param itemID the ID of the item to read.
* @param itemValue the value to write, as a String.
@@ -4680,10 +4729,10 @@
/**
* Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
* Used for device configuration by some CDMA operators.
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param preferredRoamingList byte array containing the new PRL.
* @return true on success; false on any failure.
@@ -4707,10 +4756,10 @@
* Perform the specified type of NV config reset. The radio will be taken offline
* and the device must be rebooted after the operation. Used for device
* configuration by some CDMA operators.
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param resetType reset type: 1: reload NV reset, 2: erase NV reset, 3: factory NV reset
* @return true on success; false on any failure.
@@ -4925,10 +4974,10 @@
String v = android.provider.Settings.Global.getString(cr, name);
if (index == Integer.MAX_VALUE) {
- throw new RuntimeException("putIntAtIndex index == MAX_VALUE index=" + index);
+ throw new IllegalArgumentException("putIntAtIndex index == MAX_VALUE index=" + index);
}
if (index < 0) {
- throw new RuntimeException("putIntAtIndex index < 0 index=" + index);
+ throw new IllegalArgumentException("putIntAtIndex index < 0 index=" + index);
}
if (v != null) {
valArray = v.split(",");
@@ -5058,8 +5107,8 @@
* Returns the response of authentication for the default subscription.
* Returns null if the authentication hasn't been successful
*
- * <p>Requires that the calling app has carrier privileges or READ_PRIVILEGED_PHONE_STATE
- * permission.
+ * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param appType the icc application type, like {@link #APPTYPE_USIM}
* @param authType the authentication type, {@link #AUTHTYPE_EAP_AKA} or
@@ -5067,9 +5116,10 @@
* @param data authentication challenge data, base64 encoded.
* See 3GPP TS 31.102 7.1.2 for more details.
* @return the response of authentication, or null if not available
- *
- * @see #hasCarrierPrivileges
*/
+ // TODO(b/73660190): This should probably require MODIFY_PHONE_STATE, not
+ // READ_PRIVILEGED_PHONE_STATE. It certainly shouldn't reference the permission in Javadoc since
+ // it's not public API.
public String getIccAuthentication(int appType, int authType, String data) {
return getIccAuthentication(getSubId(), appType, authType, data);
}
@@ -5078,7 +5128,7 @@
* Returns the response of USIM Authentication for specified subId.
* Returns null if the authentication hasn't been successful
*
- * <p>Requires that the calling app has carrier privileges.
+ * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId subscription ID used for authentication
* @param appType the icc application type, like {@link #APPTYPE_USIM}
@@ -5087,8 +5137,6 @@
* @param data authentication challenge data, base64 encoded.
* See 3GPP TS 31.102 7.1.2 for more details.
* @return the response of authentication, or null if not available
- *
- * @see #hasCarrierPrivileges
* @hide
*/
public String getIccAuthentication(int subId, int appType, int authType, String data) {
@@ -5109,8 +5157,12 @@
* Returns an array of Forbidden PLMNs from the USIM App
* Returns null if the query fails.
*
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
* @return an array of forbidden PLMNs or null if not available
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String[] getForbiddenPlmns() {
return getForbiddenPlmns(getSubId(), APPTYPE_USIM);
@@ -5299,6 +5351,23 @@
}
/**
+ * @return true if the IMS resolver is busy resolving a binding and should not be considered
+ * available, false if the IMS resolver is idle.
+ * @hide
+ */
+ public boolean isResolvingImsBinding() {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.isResolvingImsBinding();
+ }
+ } catch (RemoteException e) {
+ Rlog.e(TAG, "isResolvingImsBinding, RemoteException: " + e.getMessage());
+ }
+ return false;
+ }
+
+ /**
* Set IMS registration state
*
* @param Registration state
@@ -5316,10 +5385,10 @@
/**
* Get the preferred network type.
* Used for device configuration by some CDMA operators.
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @return the preferred network type, defined in RILConstants.java.
* @hide
@@ -5339,11 +5408,12 @@
/**
* Sets the network selection mode to automatic.
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void setNetworkSelectionModeAutomatic() {
try {
@@ -5359,15 +5429,14 @@
}
/**
- * Perform a radio scan and return the list of avialble networks.
+ * Perform a radio scan and return the list of available networks.
*
* The return value is a list of the OperatorInfo of the networks found. Note that this
* scan can take a long time (sometimes minutes) to happen.
*
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @hide
* TODO: Add an overload that takes no args.
@@ -5391,33 +5460,46 @@
* This method is asynchronous, so the network scan results will be returned by callback.
* The returned NetworkScan will contain a callback method which can be used to stop the scan.
*
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param request Contains all the RAT with bands/channels that need to be scanned.
+ * @param executor The executor through which the callback should be invoked.
* @param callback Returns network scan results or errors.
* @return A NetworkScan obj which contains a callback which can be used to stop the scan.
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public NetworkScan requestNetworkScan(
- NetworkScanRequest request, TelephonyScanManager.NetworkScanCallback callback) {
+ NetworkScanRequest request, Executor executor,
+ TelephonyScanManager.NetworkScanCallback callback) {
synchronized (this) {
if (mTelephonyScanManager == null) {
mTelephonyScanManager = new TelephonyScanManager();
}
}
- return mTelephonyScanManager.requestNetworkScan(getSubId(), request, callback);
+ return mTelephonyScanManager.requestNetworkScan(getSubId(), request, executor, callback);
+ }
+
+ /**
+ * @deprecated
+ * Use {@link
+ * #requestNetworkScan(NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}
+ */
+ @Deprecated
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public NetworkScan requestNetworkScan(
+ NetworkScanRequest request, TelephonyScanManager.NetworkScanCallback callback) {
+ return requestNetworkScan(request, AsyncTask.THREAD_POOL_EXECUTOR, callback);
}
/**
* Ask the radio to connect to the input network and change selection mode to manual.
*
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param operatorNumeric the PLMN ID of the network to select.
* @param persistSelection whether the selection will persist until reboot. If true, only allows
@@ -5425,6 +5507,7 @@
* normal network selection next time.
* @return true on success; false on any failure.
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public boolean setNetworkSelectionModeManual(String operatorNumeric, boolean persistSelection) {
try {
@@ -5444,10 +5527,10 @@
/**
* Set the preferred network type.
* Used for device configuration by some CDMA operators.
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId the id of the subscription to set the preferred network type for.
* @param networkType the preferred network type, defined in RILConstants.java.
@@ -5471,9 +5554,7 @@
/**
* Set the preferred network type to global mode which includes LTE, CDMA, EvDo and GSM/WCDMA.
*
- * <p>
- * Requires that the calling app has carrier privileges.
- * @see #hasCarrierPrivileges
+ * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @return true on success; false on any failure.
*/
@@ -5484,9 +5565,7 @@
/**
* Set the preferred network type to global mode which includes LTE, CDMA, EvDo and GSM/WCDMA.
*
- * <p>
- * Requires that the calling app has carrier privileges.
- * @see #hasCarrierPrivileges
+ * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @return true on success; false on any failure.
* @hide
@@ -5576,8 +5655,7 @@
* brand value input. To unset the value, the same function should be
* called with a null brand value.
*
- * <p>Requires that the calling app has carrier privileges.
- * @see #hasCarrierPrivileges
+ * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param brand The brand name to display/set.
* @return true if the operation was executed correctly.
@@ -5594,8 +5672,7 @@
* brand value input. To unset the value, the same function should be
* called with a null brand value.
*
- * <p>Requires that the calling app has carrier privileges.
- * @see #hasCarrierPrivileges
+ * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param subId The subscription to use.
* @param brand The brand name to display/set.
@@ -6249,15 +6326,15 @@
* subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
- * calling app has carrier privileges.
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param enable Whether to enable mobile data.
*
- * @see #hasCarrierPrivileges
* @deprecated use {@link #setUserMobileDataEnabled(boolean)} instead.
*/
@Deprecated
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void setDataEnabled(boolean enable) {
setUserMobileDataEnabled(enable);
@@ -6294,7 +6371,7 @@
* <p>Requires one of the following permissions:
* {@link android.Manifest.permission#ACCESS_NETWORK_STATE ACCESS_NETWORK_STATE},
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}, or that the
- * calling app has carrier privileges.
+ * calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* <p>Note that this does not take into account any data restrictions that may be present on the
* calling app. Such restrictions may be inspected with
@@ -6302,7 +6379,6 @@
*
* @return true if mobile data is enabled.
*
- * @see #hasCarrierPrivileges
* @deprecated use {@link #isUserMobileDataEnabled()} instead.
*/
@Deprecated
@@ -7073,7 +7149,11 @@
/**
* Returns the current {@link ServiceState} information.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*/
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public ServiceState getServiceState() {
return getServiceStateForSubscriber(getSubId());
@@ -7119,14 +7199,14 @@
/**
* Sets the per-account voicemail ringtone.
*
- * <p>Requires that the calling app is the default dialer, or has carrier privileges, or has
- * permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+ * <p>Requires that the calling app is the default dialer, or has carrier privileges (see
+ * {@link #hasCarrierPrivileges}, or has permission
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
*
* @param phoneAccountHandle The handle for the {@link PhoneAccount} for which to set the
* voicemail ringtone.
* @param uri The URI for the ringtone to play when receiving a voicemail from a specific
* PhoneAccount.
- * @see #hasCarrierPrivileges
*
* @deprecated Use {@link android.provider.Settings#ACTION_CHANNEL_NOTIFICATION_SETTINGS}
* instead.
@@ -7164,14 +7244,14 @@
/**
* Sets the per-account preference whether vibration is enabled for voicemail notifications.
*
- * <p>Requires that the calling app is the default dialer, or has carrier privileges, or has
- * permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+ * <p>Requires that the calling app is the default dialer, or has carrier privileges (see
+ * {@link #hasCarrierPrivileges}, or has permission
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
*
* @param phoneAccountHandle The handle for the {@link PhoneAccount} for which to set the
* voicemail vibration setting.
* @param enabled Whether to enable or disable vibration for voicemail notifications from a
* specific PhoneAccount.
- * @see #hasCarrierPrivileges
*
* @deprecated Use {@link android.provider.Settings#ACTION_CHANNEL_NOTIFICATION_SETTINGS}
* instead.
@@ -7192,8 +7272,8 @@
/**
* Returns carrier id of the current subscription.
* <p>To recognize a carrier (including MVNO) as a first-class identity, Android assigns each
- * carrier with a canonical integer a.k.a. android carrier id. The Android carrier ID is an
- * Android platform-wide identifier for a carrier. AOSP maintains carrier ID assignments in
+ * carrier with a canonical integer a.k.a. carrier id. The carrier ID is an Android
+ * platform-wide identifier for a carrier. AOSP maintains carrier ID assignments in
* <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/carrier_list.textpb">here</a>
*
* <p>Apps which have carrier-specific configurations or business logic can use the carrier id
@@ -7202,7 +7282,7 @@
* @return Carrier id of the current subscription. Return {@link #UNKNOWN_CARRIER_ID} if the
* subscription is unavailable or the carrier cannot be identified.
*/
- public int getAndroidCarrierIdForSubscription() {
+ public int getSimCarrierId() {
try {
ITelephony service = getITelephony();
if (service != null) {
@@ -7210,24 +7290,23 @@
}
} catch (RemoteException ex) {
// This could happen if binder process crashes.
- ex.rethrowAsRuntimeException();
}
return UNKNOWN_CARRIER_ID;
}
/**
- * Returns carrier name of the current subscription.
- * <p>Carrier name is a user-facing name of carrier id
- * {@link #getAndroidCarrierIdForSubscription()}, usually the brand name of the subsidiary
+ * Returns carrier id name of the current subscription.
+ * <p>Carrier id name is a user-facing name of carrier id
+ * {@link #getSimCarrierId()}, usually the brand name of the subsidiary
* (e.g. T-Mobile). Each carrier could configure multiple {@link #getSimOperatorName() SPN} but
* should have a single carrier name. Carrier name is not a canonical identity,
- * use {@link #getAndroidCarrierIdForSubscription()} instead.
+ * use {@link #getSimCarrierId()} instead.
* <p>The returned carrier name is unlocalized.
*
* @return Carrier name of the current subscription. Return {@code null} if the subscription is
* unavailable or the carrier cannot be identified.
*/
- public CharSequence getAndroidCarrierNameForSubscription() {
+ public CharSequence getSimCarrierIdName() {
try {
ITelephony service = getITelephony();
if (service != null) {
@@ -7235,7 +7314,6 @@
}
} catch (RemoteException ex) {
// This could happen if binder process crashes.
- ex.rethrowAsRuntimeException();
}
return null;
}
@@ -7594,12 +7672,10 @@
* Otherwise, it applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
- * calling app has carrier privileges.
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}.
*
* @param enable Whether to enable mobile data.
- *
- * @see #hasCarrierPrivileges
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void setUserMobileDataEnabled(boolean enable) {
@@ -7617,15 +7693,13 @@
* <p>Requires one of the following permissions:
* {@link android.Manifest.permission#ACCESS_NETWORK_STATE ACCESS_NETWORK_STATE},
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}, or that the
- * calling app has carrier privileges.
+ * calling app has carrier privileges (see {@link #hasCarrierPrivileges}.
*
* <p>Note that this does not take into account any data restrictions that may be present on the
* calling app. Such restrictions may be inspected with
* {@link ConnectivityManager#getRestrictBackgroundStatus}.
*
* @return true if mobile data is enabled.
- *
- * @see #hasCarrierPrivileges
*/
@RequiresPermission(anyOf = {
android.Manifest.permission.ACCESS_NETWORK_STATE,
@@ -7759,7 +7833,6 @@
}
} catch (RemoteException ex) {
// This could happen if binder process crashes.
- ex.rethrowAsRuntimeException();
}
}
}
diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java
index c182e34..99e2db8 100644
--- a/telephony/java/android/telephony/TelephonyScanManager.java
+++ b/telephony/java/android/telephony/TelephonyScanManager.java
@@ -33,6 +33,7 @@
import android.util.SparseArray;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.Executor;
import com.android.internal.telephony.ITelephony;
@@ -55,8 +56,10 @@
/**
* The caller of
- * {@link TelephonyManager#requestNetworkScan(NetworkScanRequest, NetworkScanCallback)} should
- * implement and provide this callback so that the scan results or errors can be returned.
+ * {@link
+ * TelephonyManager#requestNetworkScan(NetworkScanRequest, Executor, NetworkScanCallback)}
+ * should implement and provide this callback so that the scan results or errors can be
+ * returned.
*/
public static abstract class NetworkScanCallback {
/** Returns the scan results to the user, this callback will be called multiple times. */
@@ -83,10 +86,13 @@
private static class NetworkScanInfo {
private final NetworkScanRequest mRequest;
+ private final Executor mExecutor;
private final NetworkScanCallback mCallback;
- NetworkScanInfo(NetworkScanRequest request, NetworkScanCallback callback) {
+ NetworkScanInfo(
+ NetworkScanRequest request, Executor executor, NetworkScanCallback callback) {
mRequest = request;
+ mExecutor = executor;
mCallback = callback;
}
}
@@ -112,10 +118,15 @@
"Failed to find NetworkScanInfo with id " + message.arg2);
}
NetworkScanCallback callback = nsi.mCallback;
+ Executor executor = nsi.mExecutor;
if (callback == null) {
throw new RuntimeException(
"Failed to find NetworkScanCallback with id " + message.arg2);
}
+ if (executor == null) {
+ throw new RuntimeException(
+ "Failed to find Executor with id " + message.arg2);
+ }
switch (message.what) {
case CALLBACK_SCAN_RESULTS:
@@ -126,21 +137,23 @@
for (int i = 0; i < parcelables.length; i++) {
ci[i] = (CellInfo) parcelables[i];
}
- callback.onResults((List<CellInfo>) Arrays.asList(ci));
+ executor.execute(() ->
+ callback.onResults((List<CellInfo>) Arrays.asList(ci)));
} catch (Exception e) {
Rlog.e(TAG, "Exception in networkscan callback onResults", e);
}
break;
case CALLBACK_SCAN_ERROR:
try {
- callback.onError(message.arg1);
+ final int errorCode = message.arg1;
+ executor.execute(() -> callback.onError(errorCode));
} catch (Exception e) {
Rlog.e(TAG, "Exception in networkscan callback onError", e);
}
break;
case CALLBACK_SCAN_COMPLETE:
try {
- callback.onComplete();
+ executor.execute(() -> callback.onComplete());
mScanInfo.remove(message.arg2);
} catch (Exception e) {
Rlog.e(TAG, "Exception in networkscan callback onComplete", e);
@@ -171,12 +184,12 @@
* @hide
*/
public NetworkScan requestNetworkScan(int subId,
- NetworkScanRequest request, NetworkScanCallback callback) {
+ NetworkScanRequest request, Executor executor, NetworkScanCallback callback) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
int scanId = telephony.requestNetworkScan(subId, request, mMessenger, new Binder());
- saveScanInfo(scanId, request, callback);
+ saveScanInfo(scanId, request, executor, callback);
return new NetworkScan(scanId, subId);
}
} catch (RemoteException ex) {
@@ -187,9 +200,10 @@
return null;
}
- private void saveScanInfo(int id, NetworkScanRequest request, NetworkScanCallback callback) {
+ private void saveScanInfo(
+ int id, NetworkScanRequest request, Executor executor, NetworkScanCallback callback) {
synchronized (mScanInfo) {
- mScanInfo.put(id, new NetworkScanInfo(request, callback));
+ mScanInfo.put(id, new NetworkScanInfo(request, executor, callback));
}
}
diff --git a/telephony/java/android/telephony/UiccSlotInfo.java b/telephony/java/android/telephony/UiccSlotInfo.java
index 0c17147..125161d 100644
--- a/telephony/java/android/telephony/UiccSlotInfo.java
+++ b/telephony/java/android/telephony/UiccSlotInfo.java
@@ -60,6 +60,7 @@
private final String mCardId;
private final @CardStateInfo int mCardStateInfo;
private final int mLogicalSlotIdx;
+ private final boolean mIsExtendedApduSupported;
public static final Creator<UiccSlotInfo> CREATOR = new Creator<UiccSlotInfo>() {
@Override
@@ -79,6 +80,7 @@
mCardId = in.readString();
mCardStateInfo = in.readInt();
mLogicalSlotIdx = in.readInt();
+ mIsExtendedApduSupported = in.readByte() != 0;
}
@Override
@@ -88,6 +90,7 @@
dest.writeString(mCardId);
dest.writeInt(mCardStateInfo);
dest.writeInt(mLogicalSlotIdx);
+ dest.writeByte((byte) (mIsExtendedApduSupported ? 1 : 0));
}
@Override
@@ -96,12 +99,13 @@
}
public UiccSlotInfo(boolean isActive, boolean isEuicc, String cardId,
- @CardStateInfo int cardStateInfo, int logicalSlotIdx) {
+ @CardStateInfo int cardStateInfo, int logicalSlotIdx, boolean isExtendedApduSupported) {
this.mIsActive = isActive;
this.mIsEuicc = isEuicc;
this.mCardId = cardId;
this.mCardStateInfo = cardStateInfo;
this.mLogicalSlotIdx = logicalSlotIdx;
+ this.mIsExtendedApduSupported = isExtendedApduSupported;
}
public boolean getIsActive() {
@@ -125,6 +129,13 @@
return mLogicalSlotIdx;
}
+ /**
+ * @return {@code true} if this slot supports extended APDU from ATR, {@code false} otherwise.
+ */
+ public boolean getIsExtendedApduSupported() {
+ return mIsExtendedApduSupported;
+ }
+
@Override
public boolean equals(Object obj) {
if (this == obj) {
@@ -139,7 +150,8 @@
&& (mIsEuicc == that.mIsEuicc)
&& (mCardId == that.mCardId)
&& (mCardStateInfo == that.mCardStateInfo)
- && (mLogicalSlotIdx == that.mLogicalSlotIdx);
+ && (mLogicalSlotIdx == that.mLogicalSlotIdx)
+ && (mIsExtendedApduSupported == that.mIsExtendedApduSupported);
}
@Override
@@ -150,6 +162,7 @@
result = 31 * result + Objects.hashCode(mCardId);
result = 31 * result + mCardStateInfo;
result = 31 * result + mLogicalSlotIdx;
+ result = 31 * result + (mIsExtendedApduSupported ? 1 : 0);
return result;
}
@@ -165,6 +178,8 @@
+ mCardStateInfo
+ ", phoneId="
+ mLogicalSlotIdx
+ + ", mIsExtendedApduSupported="
+ + mIsExtendedApduSupported
+ ")";
}
}
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 27e5f94..350dfe3 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -296,7 +296,10 @@
readFromParcel(in);
}
- /** @hide */
+ /**
+ * Default Constructor that initializes the call profile with service type
+ * {@link #SERVICE_TYPE_NORMAL} and call type {@link #CALL_TYPE_VIDEO_N_VOICE}
+ */
public ImsCallProfile() {
mServiceType = SERVICE_TYPE_NORMAL;
mCallType = CALL_TYPE_VOICE_N_VIDEO;
@@ -304,7 +307,25 @@
mMediaProfile = new ImsStreamMediaProfile();
}
- /** @hide */
+ /**
+ * Constructor.
+ *
+ * @param serviceType the service type for the call. Can be one of the following:
+ * {@link #SERVICE_TYPE_NONE},
+ * {@link #SERVICE_TYPE_NORMAL},
+ * {@link #SERVICE_TYPE_EMERGENCY}
+ * @param callType the call type. Can be one of the following:
+ * {@link #CALL_TYPE_VOICE_N_VIDEO},
+ * {@link #CALL_TYPE_VOICE},
+ * {@link #CALL_TYPE_VIDEO_N_VOICE},
+ * {@link #CALL_TYPE_VT},
+ * {@link #CALL_TYPE_VT_TX},
+ * {@link #CALL_TYPE_VT_RX},
+ * {@link #CALL_TYPE_VT_NODIR},
+ * {@link #CALL_TYPE_VS},
+ * {@link #CALL_TYPE_VS_TX},
+ * {@link #CALL_TYPE_VS_RX}
+ */
public ImsCallProfile(int serviceType, int callType) {
mServiceType = serviceType;
mCallType = callType;
@@ -312,6 +333,35 @@
mMediaProfile = new ImsStreamMediaProfile();
}
+ /**
+ * Constructor.
+ *
+ * @param serviceType the service type for the call. Can be one of the following:
+ * {@link #SERVICE_TYPE_NONE},
+ * {@link #SERVICE_TYPE_NORMAL},
+ * {@link #SERVICE_TYPE_EMERGENCY}
+ * @param callType the call type. Can be one of the following:
+ * {@link #CALL_TYPE_VOICE_N_VIDEO},
+ * {@link #CALL_TYPE_VOICE},
+ * {@link #CALL_TYPE_VIDEO_N_VOICE},
+ * {@link #CALL_TYPE_VT},
+ * {@link #CALL_TYPE_VT_TX},
+ * {@link #CALL_TYPE_VT_RX},
+ * {@link #CALL_TYPE_VT_NODIR},
+ * {@link #CALL_TYPE_VS},
+ * {@link #CALL_TYPE_VS_TX},
+ * {@link #CALL_TYPE_VS_RX}
+ * @param callExtras A bundle with the call extras.
+ * @param mediaProfile The IMS stream media profile.
+ */
+ public ImsCallProfile(int serviceType, int callType, Bundle callExtras,
+ ImsStreamMediaProfile mediaProfile) {
+ mServiceType = serviceType;
+ mCallType = callType;
+ mCallExtras = callExtras;
+ mMediaProfile = mediaProfile;
+ }
+
public String getCallExtra(String name) {
return getCallExtra(name, "");
}
@@ -375,6 +425,16 @@
mCallExtras = (Bundle) profile.mCallExtras.clone();
}
+ /**
+ * Updates the media profile for the call.
+ *
+ * @param profile Call profile with new media profile.
+ */
+ public void updateMediaProfile(ImsCallProfile profile) {
+ mMediaProfile = profile.mMediaProfile;
+ }
+
+
@Override
public String toString() {
return "{ serviceType=" + mServiceType +
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index 2748cb5..c008711 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -161,11 +161,6 @@
}
@Override
- public void notifyImsFeatureReady(int slotId, int featureType) {
- ImsService.this.notifyImsFeatureReady(slotId, featureType);
- }
-
- @Override
public IImsConfig getConfig(int slotId) {
ImsConfigImplBase c = ImsService.this.getConfig(slotId);
return c != null ? c.getIImsConfig() : null;
@@ -274,25 +269,6 @@
}
}
- private void notifyImsFeatureReady(int slotId, int featureType) {
- synchronized (mFeaturesBySlot) {
- // get ImsFeature associated with the slot/feature
- SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
- if (features == null) {
- Log.w(LOG_TAG, "Can not notify ImsFeature ready. No ImsFeatures exist on " +
- "slot " + slotId);
- return;
- }
- ImsFeature f = features.get(featureType);
- if (f == null) {
- Log.w(LOG_TAG, "Can not notify ImsFeature ready. No feature with type "
- + featureType + " exists on slot " + slotId);
- return;
- }
- f.onFeatureReady();
- }
- }
-
/**
* When called, provide the {@link ImsFeatureConfiguration} that this {@link ImsService}
* currently supports. This will trigger the framework to set up the {@link ImsFeature}s that
diff --git a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
index 243352b..137106a 100644
--- a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
+++ b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
@@ -99,6 +99,62 @@
readFromParcel(in);
}
+ /**
+ * Constructor.
+ *
+ * @param audioQuality The audio quality. Can be one of the following:
+ * {@link #AUDIO_QUALITY_AMR},
+ * {@link #AUDIO_QUALITY_AMR_WB},
+ * {@link #AUDIO_QUALITY_QCELP13K},
+ * {@link #AUDIO_QUALITY_EVRC},
+ * {@link #AUDIO_QUALITY_EVRC_B},
+ * {@link #AUDIO_QUALITY_EVRC_WB},
+ * {@link #AUDIO_QUALITY_EVRC_NW},
+ * {@link #AUDIO_QUALITY_GSM_EFR},
+ * {@link #AUDIO_QUALITY_GSM_FR},
+ * {@link #AUDIO_QUALITY_GSM_HR},
+ * {@link #AUDIO_QUALITY_G711U},
+ * {@link #AUDIO_QUALITY_G723},
+ * {@link #AUDIO_QUALITY_G711A},
+ * {@link #AUDIO_QUALITY_G722},
+ * {@link #AUDIO_QUALITY_G711AB},
+ * {@link #AUDIO_QUALITY_G729},
+ * {@link #AUDIO_QUALITY_EVS_NB},
+ * {@link #AUDIO_QUALITY_EVS_WB},
+ * {@link #AUDIO_QUALITY_EVS_SWB},
+ * {@link #AUDIO_QUALITY_EVS_FB},
+ * @param audioDirection The audio direction. Can be one of the following:
+ * {@link #DIRECTION_INVALID},
+ * {@link #DIRECTION_INACTIVE},
+ * {@link #DIRECTION_RECEIVE},
+ * {@link #DIRECTION_SEND},
+ * {@link #DIRECTION_SEND_RECEIVE},
+ * @param videoQuality The video quality. Can be one of the following:
+ * {@link #VIDEO_QUALITY_NONE},
+ * {@link #VIDEO_QUALITY_QCIF},
+ * {@link #VIDEO_QUALITY_QVGA_LANDSCAPE},
+ * {@link #VIDEO_QUALITY_QVGA_PORTRAIT},
+ * {@link #VIDEO_QUALITY_VGA_LANDSCAPE},
+ * {@link #VIDEO_QUALITY_VGA_PORTRAIT},
+ * @param videoDirection The video direction. Can be one of the following:
+ * {@link #DIRECTION_INVALID},
+ * {@link #DIRECTION_INACTIVE},
+ * {@link #DIRECTION_RECEIVE},
+ * {@link #DIRECTION_SEND},
+ * {@link #DIRECTION_SEND_RECEIVE},
+ * @param rttMode The rtt mode. Can be one of the following:
+ * {@link #RTT_MODE_DISABLED},
+ * {@link #RTT_MODE_FULL}
+ */
+ public ImsStreamMediaProfile(int audioQuality, int audioDirection,
+ int videoQuality, int videoDirection, int rttMode) {
+ mAudioQuality = audioQuality;
+ mAudioDirection = audioDirection;
+ mVideoQuality = videoQuality;
+ mVideoDirection = videoDirection;
+ mRttMode = rttMode;
+ }
+
/** @hide */
public ImsStreamMediaProfile() {
mAudioQuality = AUDIO_QUALITY_NONE;
diff --git a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
index 86f8606..c7da681 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
@@ -36,8 +36,6 @@
ImsFeatureConfiguration querySupportedImsFeatures();
// Synchronous call to ensure the ImsService is ready before continuing with feature creation.
void notifyImsServiceReadyForFeatureCreation();
- // Synchronous call to ensure the new ImsFeature is ready before using the Feature.
- void notifyImsFeatureReady(int slotId, int featureType);
void removeImsFeature(int slotId, int featureType, in IImsFeatureStatusCallback c);
IImsConfig getConfig(int slotId);
IImsRegistration getRegistration(int slotId);
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index 2fffd36..c073d1a 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -575,7 +575,7 @@
*/
public ImsUtImplBase getUt() {
// Base Implementation - Should be overridden
- return null;
+ return new ImsUtImplBase();
}
/**
@@ -584,7 +584,7 @@
*/
public ImsEcbmImplBase getEcbm() {
// Base Implementation - Should be overridden
- return null;
+ return new ImsEcbmImplBase();
}
/**
@@ -593,7 +593,7 @@
*/
public ImsMultiEndpointImplBase getMultiEndpoint() {
// Base Implementation - Should be overridden
- return null;
+ return new ImsMultiEndpointImplBase();
}
/**
diff --git a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
index 98b67c3..2f52c0a 100644
--- a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
+++ b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
@@ -21,6 +21,7 @@
import android.os.Parcelable;
import android.telephony.ims.feature.ImsFeature;
import android.util.ArraySet;
+import android.util.Pair;
import java.util.Set;
@@ -34,14 +35,57 @@
*/
@SystemApi
public final class ImsFeatureConfiguration implements Parcelable {
+
+ public static final class FeatureSlotPair {
+ /**
+ * SIM slot that this feature is associated with.
+ */
+ public final int slotId;
+ /**
+ * The feature that this slotId supports. Supported values are
+ * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
+ * {@link ImsFeature#FEATURE_RCS}.
+ */
+ public final @ImsFeature.FeatureType int featureType;
+
+ /**
+ * A mapping from slotId to IMS Feature type.
+ * @param slotId the SIM slot ID associated with this feature.
+ * @param featureType The feature that this slotId supports. Supported values are
+ * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
+ * {@link ImsFeature#FEATURE_RCS}.
+ */
+ public FeatureSlotPair(int slotId, @ImsFeature.FeatureType int featureType) {
+ this.slotId = slotId;
+ this.featureType = featureType;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ FeatureSlotPair that = (FeatureSlotPair) o;
+
+ if (slotId != that.slotId) return false;
+ return featureType == that.featureType;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = slotId;
+ result = 31 * result + featureType;
+ return result;
+ }
+ }
+
/**
* Features that this ImsService supports.
*/
- private final Set<Integer> mFeatures;
+ private final Set<FeatureSlotPair> mFeatures;
/**
- * Builder for {@link ImsFeatureConfiguration} that makes adding supported {@link ImsFeature}s
- * easier.
+ * Builder for {@link ImsFeatureConfiguration}.
*/
public static class Builder {
ImsFeatureConfiguration mConfig;
@@ -50,12 +94,15 @@
}
/**
- * @param feature A feature defined in {@link ImsFeature.FeatureType} that this service
- * supports.
+ * Adds an IMS feature associated with a SIM slot ID.
+ * @param slotId The slot ID associated with the IMS feature.
+ * @param featureType The feature that the slot ID supports. Supported values are
+ * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
+ * {@link ImsFeature#FEATURE_RCS}.
* @return a {@link Builder} to continue constructing the ImsFeatureConfiguration.
*/
- public Builder addFeature(@ImsFeature.FeatureType int feature) {
- mConfig.addFeature(feature);
+ public Builder addFeature(int slotId, @ImsFeature.FeatureType int featureType) {
+ mConfig.addFeature(slotId, featureType);
return this;
}
@@ -66,8 +113,7 @@
/**
* Creates with all registration features empty.
- *
- * Consider using the provided {@link Builder} to create this configuration instead.
+ * @hide
*/
public ImsFeatureConfiguration() {
mFeatures = new ArraySet<>();
@@ -76,45 +122,41 @@
/**
* Configuration of the ImsService, which describes which features the ImsService supports
* (for registration).
- * @param features an array of feature integers defined in {@link ImsFeature} that describe
- * which features this ImsService supports. Supported values are
- * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
- * {@link ImsFeature#FEATURE_RCS}.
+ * @param features a set of {@link FeatureSlotPair}s that describe which features this
+ * ImsService supports.
* @hide
*/
- public ImsFeatureConfiguration(int[] features) {
+ public ImsFeatureConfiguration(Set<FeatureSlotPair> features) {
mFeatures = new ArraySet<>();
if (features != null) {
- for (int i : features) {
- mFeatures.add(i);
- }
+ mFeatures.addAll(features);
}
}
/**
- * @return an int[] containing the features that this ImsService supports. Supported values are
- * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
- * {@link ImsFeature#FEATURE_RCS}.
+ * @return a set of supported slot ID to feature type pairs contained within a
+ * {@link FeatureSlotPair}.
*/
- public int[] getServiceFeatures() {
- return mFeatures.stream().mapToInt(i->i).toArray();
+ public Set<FeatureSlotPair> getServiceFeatures() {
+ return new ArraySet<>(mFeatures);
}
- void addFeature(int feature) {
- mFeatures.add(feature);
+ /**
+ * @hide
+ */
+ void addFeature(int slotId, int feature) {
+ mFeatures.add(new FeatureSlotPair(slotId, feature));
}
/** @hide */
protected ImsFeatureConfiguration(Parcel in) {
- int[] features = in.createIntArray();
- if (features != null) {
- mFeatures = new ArraySet<>(features.length);
- for(Integer i : features) {
- mFeatures.add(i);
- }
- } else {
- mFeatures = new ArraySet<>();
+ int featurePairLength = in.readInt();
+ // length
+ mFeatures = new ArraySet<>(featurePairLength);
+ for (int i = 0; i < featurePairLength; i++) {
+ // pair of reads for each entry (slotId->featureType)
+ mFeatures.add(new FeatureSlotPair(in.readInt(), in.readInt()));
}
}
@@ -138,7 +180,15 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeIntArray(mFeatures.stream().mapToInt(i->i).toArray());
+ FeatureSlotPair[] featureSlotPairs = new FeatureSlotPair[mFeatures.size()];
+ mFeatures.toArray(featureSlotPairs);
+ // length of list
+ dest.writeInt(featureSlotPairs.length);
+ // then pairs of integers for each entry (slotId->featureType).
+ for (FeatureSlotPair featureSlotPair : featureSlotPairs) {
+ dest.writeInt(featureSlotPair.slotId);
+ dest.writeInt(featureSlotPair.featureType);
+ }
}
/**
diff --git a/telephony/java/com/android/internal/telephony/DcParamObject.java b/telephony/java/com/android/internal/telephony/DcParamObject.java
index 139939c..fc6b610 100644
--- a/telephony/java/com/android/internal/telephony/DcParamObject.java
+++ b/telephony/java/com/android/internal/telephony/DcParamObject.java
@@ -36,7 +36,7 @@
}
public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(mSubId);
+ dest.writeInt(mSubId);
}
private void readFromParcel(Parcel in) {
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index a941a56..afbb947 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -829,6 +829,12 @@
boolean isEmergencyMmTelAvailable(int slotId);
/**
+ * @return true if the IMS resolver is busy resolving a binding and should not be considered
+ * available, false if the IMS resolver is idle.
+ */
+ boolean isResolvingImsBinding();
+
+ /**
* Set the network selection mode to automatic.
*
* @param subId the id of the subscription to update.
@@ -1358,10 +1364,10 @@
/**
* Returns carrier name of the given subscription.
- * <p>Carrier name is a user-facing name of carrier id {@link #getSubscriptionCarrierId(int)},
+ * <p>Carrier name is a user-facing name of carrier id {@link #getSimCarrierId(int)},
* usually the brand name of the subsidiary (e.g. T-Mobile). Each carrier could configure
* multiple {@link #getSimOperatorName() SPN} but should have a single carrier name.
- * Carrier name is not canonical identity, use {@link #getSubscriptionCarrierId(int)} instead.
+ * Carrier name is not canonical identity, use {@link #getSimCarrierId(int)} instead.
* <p>Returned carrier name is unlocalized.
*
* @return Carrier name of given subscription id. return {@code null} if subscription is
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index da8471f..a182f2b 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -26,7 +26,8 @@
import android.telephony.TelephonyManager;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.ITelephony;
+
+import java.util.function.Supplier;
/** Utility class for Telephony permission enforcement. */
public final class TelephonyPermissions {
@@ -34,6 +35,9 @@
private static final boolean DBG = false;
+ private static final Supplier<ITelephony> TELEPHONY_SUPPLIER = () ->
+ ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
+
private TelephonyPermissions() {}
/**
@@ -41,8 +45,8 @@
*
* <p>This method behaves in one of the following ways:
* <ul>
- * <li>return true: if the caller has either the READ_PRIVILEGED_PHONE_STATE permission or the
- * READ_PHONE_STATE runtime permission.
+ * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the
+ * READ_PHONE_STATE runtime permission, or carrier privileges on the given subId.
* <li>throw SecurityException: if the caller didn't declare any of these permissions, or, for
* apps which support runtime permissions, if the caller does not currently have any of
* these permissions.
@@ -51,20 +55,30 @@
* manually (via AppOps). In this case we can't throw as it would break app compatibility,
* so we return false to indicate that the calling function should return dummy data.
* </ul>
+ *
+ * <p>Note: for simplicity, this method always returns false for callers using legacy
+ * permissions and who have had READ_PHONE_STATE revoked, even if they are carrier-privileged.
+ * Such apps should migrate to runtime permissions or stop requiring READ_PHONE_STATE on P+
+ * devices.
+ *
+ * @param subId the subId of the relevant subscription; used to check carrier privileges. May be
+ * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} to skip this check for cases
+ * where it isn't relevant (hidden APIs, or APIs which are otherwise okay to leave
+ * inaccesible to carrier-privileged apps).
*/
public static boolean checkCallingOrSelfReadPhoneState(
- Context context, String callingPackage, String message) {
- return checkReadPhoneState(context, Binder.getCallingPid(), Binder.getCallingUid(),
+ Context context, int subId, String callingPackage, String message) {
+ return checkReadPhoneState(context, subId, Binder.getCallingPid(), Binder.getCallingUid(),
callingPackage, message);
}
/**
* Check whether the app with the given pid/uid can read phone state.
*
- * <p>This method behaves in one of the following ways:
+ * <p>This method behaves in one of the following ways:
* <ul>
- * <li>return true: if the caller has either the READ_PRIVILEGED_PHONE_STATE permission or the
- * READ_PHONE_STATE runtime permission.
+ * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the
+ * READ_PHONE_STATE runtime permission, or carrier privileges on the given subId.
* <li>throw SecurityException: if the caller didn't declare any of these permissions, or, for
* apps which support runtime permissions, if the caller does not currently have any of
* these permissions.
@@ -73,9 +87,22 @@
* manually (via AppOps). In this case we can't throw as it would break app compatibility,
* so we return false to indicate that the calling function should return dummy data.
* </ul>
+ *
+ * <p>Note: for simplicity, this method always returns false for callers using legacy
+ * permissions and who have had READ_PHONE_STATE revoked, even if they are carrier-privileged.
+ * Such apps should migrate to runtime permissions or stop requiring READ_PHONE_STATE on P+
+ * devices.
*/
public static boolean checkReadPhoneState(
- Context context, int pid, int uid, String callingPackage, String message) {
+ Context context, int subId, int pid, int uid, String callingPackage, String message) {
+ return checkReadPhoneState(
+ context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, message);
+ }
+
+ @VisibleForTesting
+ public static boolean checkReadPhoneState(
+ Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
+ String callingPackage, String message) {
try {
context.enforcePermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message);
@@ -83,8 +110,18 @@
// SKIP checking for run-time permission since caller has PRIVILEGED permission
return true;
} catch (SecurityException privilegedPhoneStateException) {
- context.enforcePermission(
- android.Manifest.permission.READ_PHONE_STATE, pid, uid, message);
+ try {
+ context.enforcePermission(
+ android.Manifest.permission.READ_PHONE_STATE, pid, uid, message);
+ } catch (SecurityException phoneStateException) {
+ // If we don't have the runtime permission, but do have carrier privileges, that
+ // suffices for reading phone state.
+ if (SubscriptionManager.isValidSubscriptionId(subId)) {
+ enforceCarrierPrivilege(telephonySupplier, subId, uid, message);
+ return true;
+ }
+ throw phoneStateException;
+ }
}
// We have READ_PHONE_STATE permission, so return true as long as the AppOps bit hasn't been
@@ -101,14 +138,16 @@
* default SMS app and apps with READ_SMS or READ_PHONE_NUMBERS can also read phone numbers.
*/
public static boolean checkCallingOrSelfReadPhoneNumber(
- Context context, String callingPackage, String message) {
+ Context context, int subId, String callingPackage, String message) {
return checkReadPhoneNumber(
- context, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message);
+ context, TELEPHONY_SUPPLIER, subId, Binder.getCallingPid(), Binder.getCallingUid(),
+ callingPackage, message);
}
@VisibleForTesting
public static boolean checkReadPhoneNumber(
- Context context, int pid, int uid, String callingPackage, String message) {
+ Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
+ String callingPackage, String message) {
// Default SMS app can always read it.
AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
if (appOps.noteOp(AppOpsManager.OP_WRITE_SMS, uid, callingPackage) ==
@@ -121,7 +160,8 @@
// First, check if we can read the phone state.
try {
- return checkReadPhoneState(context, pid, uid, callingPackage, message);
+ return checkReadPhoneState(
+ context, telephonySupplier, subId, pid, uid, callingPackage, message);
} catch (SecurityException readPhoneStateSecurityException) {
}
// Can be read with READ_SMS too.
@@ -186,16 +226,21 @@
}
private static void enforceCarrierPrivilege(int subId, int uid, String message) {
- if (getCarrierPrivilegeStatus(subId, uid) !=
+ enforceCarrierPrivilege(TELEPHONY_SUPPLIER, subId, uid, message);
+ }
+
+ private static void enforceCarrierPrivilege(
+ Supplier<ITelephony> telephonySupplier, int subId, int uid, String message) {
+ if (getCarrierPrivilegeStatus(telephonySupplier, subId, uid) !=
TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
if (DBG) Rlog.e(LOG_TAG, "No Carrier Privilege.");
throw new SecurityException(message);
}
}
- private static int getCarrierPrivilegeStatus(int subId, int uid) {
- ITelephony telephony =
- ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
+ private static int getCarrierPrivilegeStatus(
+ Supplier<ITelephony> telephonySupplier, int subId, int uid) {
+ ITelephony telephony = telephonySupplier.get();
try {
if (telephony != null) {
return telephony.getCarrierPrivilegeStatusForUid(subId, uid);
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index 494ee65..f4b85b2 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -92,6 +92,7 @@
private static final int INITIAL_LAUNCH_IDLE_TIMEOUT = 5000; // 5s to allow app to idle
private static final int POST_LAUNCH_IDLE_TIMEOUT = 750; // 750ms idle for non initial launches
private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 5000; // 5s between launching apps
+ private static final int PROFILE_SAVE_SLEEP_TIMEOUT = 1000; // Allow 1s for the profile to save
private static final String LAUNCH_SUB_DIRECTORY = "launch_logs";
private static final String LAUNCH_FILE = "applaunch.txt";
private static final String TRACE_SUB_DIRECTORY = "atrace_logs";
@@ -263,6 +264,8 @@
String.format("killall -s SIGUSR1 %s", appPkgName);
getInstrumentation().getUiAutomation().executeShellCommand(
sendSignalCommand);
+ // killall is async, wait one second to let the app save the profile.
+ sleep(PROFILE_SAVE_SLEEP_TIMEOUT);
assertTrue(String.format("Not able to compile the app : %s", appPkgName),
compileApp(launch.getCompilerFilter(), appPkgName));
}
diff --git a/tests/OdmApps/Android.mk b/tests/OdmApps/Android.mk
new file mode 100644
index 0000000..64fa653
--- /dev/null
+++ b/tests/OdmApps/Android.mk
@@ -0,0 +1,26 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := OdmAppsTest
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_JAVA_LIBRARIES := tradefed
+LOCAL_COMPATIBILITY_SUITE := device-tests
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/OdmApps/AndroidTest.xml b/tests/OdmApps/AndroidTest.xml
new file mode 100644
index 0000000..2f12838
--- /dev/null
+++ b/tests/OdmApps/AndroidTest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<configuration description="Config for ODM apps test">
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="remount-system" value="true" />
+ <option name="push" value="TestOdmApp.apk->/odm/app/TestOdmApp/TestOdmApp.apk" />
+ <option name="push" value="TestOdmPrivApp.apk->/odm/priv-app/TestOdmPrivApp/TestOdmPrivApp.apk" />
+ <option name="post-push" value="stop; start; sleep 5" />
+ </target_preparer>
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="OdmAppsTest.jar" />
+ </test>
+</configuration>
diff --git a/tests/OdmApps/app/Android.mk b/tests/OdmApps/app/Android.mk
new file mode 100644
index 0000000..9eec0cc
--- /dev/null
+++ b/tests/OdmApps/app/Android.mk
@@ -0,0 +1,22 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := TestOdmApp
+LOCAL_MODULE_TAGS := tests
+LOCAL_COMPATIBILITY_SUITE := device-tests
+LOCAL_SDK_VERSION := current
+include $(BUILD_PACKAGE)
diff --git a/tests/OdmApps/app/AndroidManifest.xml b/tests/OdmApps/app/AndroidManifest.xml
new file mode 100755
index 0000000..84a9ea8
--- /dev/null
+++ b/tests/OdmApps/app/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.test.odm.app">
+</manifest>
+
diff --git a/tests/OdmApps/priv-app/Android.mk b/tests/OdmApps/priv-app/Android.mk
new file mode 100644
index 0000000..d423133
--- /dev/null
+++ b/tests/OdmApps/priv-app/Android.mk
@@ -0,0 +1,22 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := TestOdmPrivApp
+LOCAL_MODULE_TAGS := tests
+LOCAL_COMPATIBILITY_SUITE := device-tests
+LOCAL_SDK_VERSION := current
+include $(BUILD_PACKAGE)
diff --git a/tests/OdmApps/priv-app/AndroidManifest.xml b/tests/OdmApps/priv-app/AndroidManifest.xml
new file mode 100755
index 0000000..031cf64
--- /dev/null
+++ b/tests/OdmApps/priv-app/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.test.odm.privapp">
+</manifest>
+
diff --git a/tests/OdmApps/src/com/android/test/odm/app/OdmAppsTest.java b/tests/OdmApps/src/com/android/test/odm/app/OdmAppsTest.java
new file mode 100644
index 0000000..de742b8
--- /dev/null
+++ b/tests/OdmApps/src/com/android/test/odm/app/OdmAppsTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.odm.apps;
+
+import com.android.tradefed.testtype.DeviceTestCase;
+
+public class OdmAppsTest extends DeviceTestCase {
+ /**
+ * Test if /odm/app is working
+ */
+ public void testOdmApp() throws Exception {
+ assertNotNull(getDevice().getAppPackageInfo("com.android.test.odm.app"));
+ }
+
+ /**
+ * Test if /odm/priv-app is working
+ */
+ public void testOdmPrivApp() throws Exception {
+ assertNotNull(getDevice().getAppPackageInfo("com.android.test.odm.privapp"));
+ }
+}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index ddcf327..93fa598 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -2076,11 +2076,15 @@
}
/**
- * Set the {@link ProxyInfo} for this WifiConfiguration.
+ * Set the {@link ProxyInfo} for this WifiConfiguration. This method should only be used by a
+ * device owner or profile owner. When other apps attempt to save a {@link WifiConfiguration}
+ * with modified proxy settings, the methods {@link WifiManager#addNetwork} and
+ * {@link WifiManager#updateNetwork} fail and return {@code -1}.
+ *
* @param httpProxy {@link ProxyInfo} representing the httpProxy to be used by this
- * WifiConfiguration. Setting this {@code null} will explicitly set no proxy,
- * removing any proxy that was previously set.
- * @exception throw IllegalArgumentException for invalid httpProxy
+ * WifiConfiguration. Setting this to {@code null} will explicitly set no
+ * proxy, removing any proxy that was previously set.
+ * @exception IllegalArgumentException for invalid httpProxy
*/
public void setHttpProxy(ProxyInfo httpProxy) {
if (httpProxy == null) {
diff --git a/wifi/java/android/net/wifi/aware/SubscribeConfig.java b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
index 2ec3b70..51353c6 100644
--- a/wifi/java/android/net/wifi/aware/SubscribeConfig.java
+++ b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
@@ -418,8 +418,8 @@
* notification. I.e. discovery will be triggered if we've found a matching publisher
* (based on the other criteria in this configuration) <b>and</b> the distance to the
* publisher is larger than the value specified in this API. Can be used in conjunction with
- * {@link #setMaxDistanceMm(int)} to specify a geofence, i.e. discovery with min <
- * distance < max.
+ * {@link #setMaxDistanceMm(int)} to specify a geofence, i.e. discovery with min <=
+ * distance <= max.
* <p>
* For ranging to be used in discovery it must also be enabled on the publisher using
* {@link PublishConfig.Builder#setRangingEnabled(boolean)}. However, ranging may
@@ -453,8 +453,8 @@
* notification. I.e. discovery will be triggered if we've found a matching publisher
* (based on the other criteria in this configuration) <b>and</b> the distance to the
* publisher is smaller than the value specified in this API. Can be used in conjunction
- * with {@link #setMinDistanceMm(int)} to specify a geofence, i.e. discovery with min <
- * distance < max.
+ * with {@link #setMinDistanceMm(int)} to specify a geofence, i.e. discovery with min <=
+ * distance <= max.
* <p>
* For ranging to be used in discovery it must also be enabled on the publisher using
* {@link PublishConfig.Builder#setRangingEnabled(boolean)}. However, ranging may
diff --git a/wifi/java/android/net/wifi/rtt/RangingResult.java b/wifi/java/android/net/wifi/rtt/RangingResult.java
index 936a1f2..4705e1d 100644
--- a/wifi/java/android/net/wifi/rtt/RangingResult.java
+++ b/wifi/java/android/net/wifi/rtt/RangingResult.java
@@ -189,7 +189,8 @@
}
/**
- * @return The Location Configuration Information (LCI) as self-reported by the peer.
+ * @return The Location Configuration Information (LCI) as self-reported by the peer. The format
+ * is specified in the IEEE 802.11-2016 specifications, section 9.4.2.22.10.
* <p>
* Note: the information is NOT validated - use with caution. Consider validating it with
* other sources of information before using it.
@@ -207,7 +208,8 @@
}
/**
- * @return The Location Civic report (LCR) as self-reported by the peer.
+ * @return The Location Civic report (LCR) as self-reported by the peer. The format
+ * is specified in the IEEE 802.11-2016 specifications, section 9.4.2.22.13.
* <p>
* Note: the information is NOT validated - use with caution. Consider validating it with
* other sources of information before using it.
diff --git a/wifi/java/android/net/wifi/rtt/WifiRttManager.java b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
index d119579..457e904 100644
--- a/wifi/java/android/net/wifi/rtt/WifiRttManager.java
+++ b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
@@ -16,7 +16,7 @@
package android.net.wifi.rtt;
-import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.Manifest.permission.ACCESS_WIFI_STATE;
import static android.Manifest.permission.CHANGE_WIFI_STATE;
import static android.Manifest.permission.LOCATION_HARDWARE;
@@ -109,7 +109,7 @@
* @param executor The Executor on which to run the callback.
* @param callback A callback for the result of the ranging request.
*/
- @RequiresPermission(allOf = {ACCESS_COARSE_LOCATION, CHANGE_WIFI_STATE, ACCESS_WIFI_STATE})
+ @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, CHANGE_WIFI_STATE, ACCESS_WIFI_STATE})
public void startRanging(@NonNull RangingRequest request,
@NonNull @CallbackExecutor Executor executor, @NonNull RangingResultCallback callback) {
startRanging(null, request, executor, callback);
@@ -128,7 +128,7 @@
* @hide
*/
@SystemApi
- @RequiresPermission(allOf = {LOCATION_HARDWARE, ACCESS_COARSE_LOCATION, CHANGE_WIFI_STATE,
+ @RequiresPermission(allOf = {LOCATION_HARDWARE, ACCESS_FINE_LOCATION, CHANGE_WIFI_STATE,
ACCESS_WIFI_STATE})
public void startRanging(@Nullable WorkSource workSource, @NonNull RangingRequest request,
@NonNull @CallbackExecutor Executor executor, @NonNull RangingResultCallback callback) {
diff --git a/wifi/java/android/net/wifi/rtt/package.html b/wifi/java/android/net/wifi/rtt/package.html
index 11ac058..e639282 100644
--- a/wifi/java/android/net/wifi/rtt/package.html
+++ b/wifi/java/android/net/wifi/rtt/package.html
@@ -11,7 +11,7 @@
<ul>
<li>{@link android.Manifest.permission#ACCESS_WIFI_STATE}</li>
<li>{@link android.Manifest.permission#CHANGE_WIFI_STATE}</li>
- <li>{@link android.Manifest.permission#ACCESS_COARSE_LOCATION}</li>
+ <li>{@link android.Manifest.permission#ACCESS_FINE_LOCATION}</li>
</ul>
<p>Usage of the API is also gated by the device's Location Mode: whether it permits Wi-Fi based
location to be queried.</p>