diff --git a/Android.bp b/Android.bp index b14f15effcf44f02bcdfeeecbe3d6265550cb658..7f3243f13d197db3242b5057a2039bdd98fb6281 100755 --- a/Android.bp +++ b/Android.bp @@ -356,6 +356,7 @@ java_library { "core/java/android/speech/IRecognitionService.aidl", "core/java/android/speech/tts/ITextToSpeechCallback.aidl", "core/java/android/speech/tts/ITextToSpeechService.aidl", + "core/java/com/android/internal/app/IAppOpsActiveCallback.aidl", "core/java/com/android/internal/app/IAppOpsCallback.aidl", "core/java/com/android/internal/app/IAppOpsService.aidl", "core/java/com/android/internal/app/IBatteryStats.aidl", diff --git a/apct-tests/perftests/core/Android.mk b/apct-tests/perftests/core/Android.mk index 75cb229e36d6fd8e8e7dbe6f9fd33e5a27e30984..b7b87dda1957f4534e50f7cd71f9343a131c6360 100644 --- a/apct-tests/perftests/core/Android.mk +++ b/apct-tests/perftests/core/Android.mk @@ -22,6 +22,8 @@ LOCAL_JNI_SHARED_LIBRARIES := libperftestscore_jni # Use google-fonts/dancing-script for the performance metrics LOCAL_ASSET_DIR := $(TOP)/external/google-fonts/dancing-script +LOCAL_COMPATIBILITY_SUITE += device-tests + include $(BUILD_PACKAGE) include $(call all-makefiles-under, $(LOCAL_PATH)) diff --git a/apct-tests/perftests/core/src/android/text/MeasuredTextMemoryUsageTest.java b/apct-tests/perftests/core/src/android/text/PrecomputedTextMemoryUsageTest.java similarity index 73% rename from apct-tests/perftests/core/src/android/text/MeasuredTextMemoryUsageTest.java rename to apct-tests/perftests/core/src/android/text/PrecomputedTextMemoryUsageTest.java index fc6302ea93942d30532e9d5ae185ead48eb31d78..73e17242ae785749a839fbf1124c072ca3d45284 100644 --- a/apct-tests/perftests/core/src/android/text/MeasuredTextMemoryUsageTest.java +++ b/apct-tests/perftests/core/src/android/text/PrecomputedTextMemoryUsageTest.java @@ -45,7 +45,7 @@ import java.util.Random; @LargeTest @RunWith(AndroidJUnit4.class) -public class MeasuredTextMemoryUsageTest { +public class PrecomputedTextMemoryUsageTest { private static final int WORD_LENGTH = 9; // Random word has 9 characters. private static final boolean NO_STYLE_TEXT = false; @@ -53,7 +53,7 @@ public class MeasuredTextMemoryUsageTest { private static int TRIAL_COUNT = 100; - public MeasuredTextMemoryUsageTest() {} + public PrecomputedTextMemoryUsageTest() {} private TextPerfUtils mTextUtil = new TextPerfUtils(); @@ -77,13 +77,16 @@ public class MeasuredTextMemoryUsageTest { @Test public void testMemoryUsage_NoHyphenation() { int[] memories = new int[TRIAL_COUNT]; - // Report median of randomly generated MeasuredText. - for (int i = 0; i < TRIAL_COUNT; ++i) { - memories[i] = new MeasuredText.Builder( - mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT) + final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT) .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) - .build().getMemoryUsage(); + .build(); + + // Report median of randomly generated PrecomputedText. + for (int i = 0; i < TRIAL_COUNT; ++i) { + memories[i] = PrecomputedText.create( + mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), param) + .getMemoryUsage(); } reportMemoryUsage(median(memories), "MemoryUsage_NoHyphenation"); } @@ -91,13 +94,16 @@ public class MeasuredTextMemoryUsageTest { @Test public void testMemoryUsage_Hyphenation() { int[] memories = new int[TRIAL_COUNT]; - // Report median of randomly generated MeasuredText. - for (int i = 0; i < TRIAL_COUNT; ++i) { - memories[i] = new MeasuredText.Builder( - mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT) + final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT) .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) - .build().getMemoryUsage(); + .build(); + + // Report median of randomly generated PrecomputedText. + for (int i = 0; i < TRIAL_COUNT; ++i) { + memories[i] = PrecomputedText.create( + mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), param) + .getMemoryUsage(); } reportMemoryUsage(median(memories), "MemoryUsage_Hyphenation"); } @@ -105,13 +111,16 @@ public class MeasuredTextMemoryUsageTest { @Test public void testMemoryUsage_NoHyphenation_WidthOnly() { int[] memories = new int[TRIAL_COUNT]; - // Report median of randomly generated MeasuredText. - for (int i = 0; i < TRIAL_COUNT; ++i) { - memories[i] = new MeasuredText.Builder( - mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT) + final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT) .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) - .build(false /* width only */).getMemoryUsage(); + .build(); + + // Report median of randomly generated PrecomputedText. + for (int i = 0; i < TRIAL_COUNT; ++i) { + CharSequence cs = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT); + memories[i] = PrecomputedText.createWidthOnly(cs, param, 0, cs.length()) + .getMemoryUsage(); } reportMemoryUsage(median(memories), "MemoryUsage_NoHyphenation_WidthOnly"); } @@ -119,13 +128,16 @@ public class MeasuredTextMemoryUsageTest { @Test public void testMemoryUsage_Hyphenatation_WidthOnly() { int[] memories = new int[TRIAL_COUNT]; - // Report median of randomly generated MeasuredText. - for (int i = 0; i < TRIAL_COUNT; ++i) { - memories[i] = new MeasuredText.Builder( - mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT) + final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT) .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) - .build(false /* width only */).getMemoryUsage(); + .build(); + + // Report median of randomly generated PrecomputedText. + for (int i = 0; i < TRIAL_COUNT; ++i) { + CharSequence cs = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT); + memories[i] = PrecomputedText.createWidthOnly(cs, param, 0, cs.length()) + .getMemoryUsage(); } reportMemoryUsage(median(memories), "MemoryUsage_Hyphenation_WidthOnly"); } diff --git a/apct-tests/perftests/core/src/android/text/MeasuredTextPerfTest.java b/apct-tests/perftests/core/src/android/text/PrecomputedTextPerfTest.java similarity index 66% rename from apct-tests/perftests/core/src/android/text/MeasuredTextPerfTest.java rename to apct-tests/perftests/core/src/android/text/PrecomputedTextPerfTest.java index 98f2bd5e573652d1feba4220546293bef82d1865..1cd0ae13069bb42f3aefbd2b210ae41546edb25c 100644 --- a/apct-tests/perftests/core/src/android/text/MeasuredTextPerfTest.java +++ b/apct-tests/perftests/core/src/android/text/PrecomputedTextPerfTest.java @@ -42,7 +42,7 @@ import java.util.Random; @LargeTest @RunWith(AndroidJUnit4.class) -public class MeasuredTextPerfTest { +public class PrecomputedTextPerfTest { private static final int WORD_LENGTH = 9; // Random word has 9 characters. private static final int WORDS_IN_LINE = 8; // Roughly, 8 words in a line. private static final boolean NO_STYLE_TEXT = false; @@ -51,7 +51,7 @@ public class MeasuredTextPerfTest { private static TextPaint PAINT = new TextPaint(); private static final int TEXT_WIDTH = WORDS_IN_LINE * WORD_LENGTH * (int) PAINT.getTextSize(); - public MeasuredTextPerfTest() {} + public PrecomputedTextPerfTest() {} @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); @@ -66,120 +66,136 @@ public class MeasuredTextPerfTest { @Test public void testCreate_NoStyled_Hyphenation() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT) + .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) + .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) + .build(); + while (state.keepRunning()) { state.pauseTiming(); final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT); state.resumeTiming(); - new MeasuredText.Builder(text, PAINT) - .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) - .build(true /* do full layout */); + PrecomputedText.create(text, param); } } @Test public void testCreate_NoStyled_NoHyphenation() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT) + .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) + .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) + .build(); + while (state.keepRunning()) { state.pauseTiming(); final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT); state.resumeTiming(); - new MeasuredText.Builder(text, PAINT) - .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) - .build(true /* do full layout */); + PrecomputedText.create(text, param); } } @Test public void testCreate_NoStyled_Hyphenation_WidthOnly() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT) + .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) + .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) + .build(); + while (state.keepRunning()) { state.pauseTiming(); final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT); state.resumeTiming(); - new MeasuredText.Builder(text, PAINT) - .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) - .build(false /* width only */); + PrecomputedText.create(text, param); } } @Test public void testCreate_NoStyled_NoHyphenation_WidthOnly() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT) + .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) + .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) + .build(); + while (state.keepRunning()) { state.pauseTiming(); final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT); state.resumeTiming(); - new MeasuredText.Builder(text, PAINT) - .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) - .build(false /* width only */); + PrecomputedText.create(text, param); } } @Test public void testCreate_Styled_Hyphenation() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT) + .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) + .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) + .build(); + while (state.keepRunning()) { state.pauseTiming(); final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT); state.resumeTiming(); - new MeasuredText.Builder(text, PAINT) - .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) - .build(true /* do full layout */); + PrecomputedText.create(text, param); } } @Test public void testCreate_Styled_NoHyphenation() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT) + .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) + .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) + .build(); + while (state.keepRunning()) { state.pauseTiming(); final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT); state.resumeTiming(); - new MeasuredText.Builder(text, PAINT) - .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) - .build(true /* do full layout */); + PrecomputedText.create(text, param); } } @Test public void testCreate_Styled_Hyphenation_WidthOnly() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT) + .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) + .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) + .build(); + while (state.keepRunning()) { state.pauseTiming(); final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT); state.resumeTiming(); - new MeasuredText.Builder(text, PAINT) - .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) - .build(false /* width only */); + PrecomputedText.create(text, param); } } @Test public void testCreate_Styled_NoHyphenation_WidthOnly() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT) + .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) + .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) + .build(); + while (state.keepRunning()) { state.pauseTiming(); final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT); state.resumeTiming(); - new MeasuredText.Builder(text, PAINT) - .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) - .build(false /* width only */); + PrecomputedText.create(text, param); } } } diff --git a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java index 231aaf2ca074910077c537e634322594a47a8b7f..e1a38a0956d70177a1ccf6374133f55b0c94b4e7 100644 --- a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java +++ b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java @@ -63,6 +63,18 @@ public class StaticLayoutPerfTest { mTextUtil.resetRandom(0 /* seed */); } + private PrecomputedText makeMeasured(CharSequence text, TextPaint paint) { + PrecomputedText.Params param = new PrecomputedText.Params.Builder(paint).build(); + return PrecomputedText.create(text, param); + } + + private PrecomputedText makeMeasured(CharSequence text, TextPaint paint, int strategy, + int frequency) { + PrecomputedText.Params param = new PrecomputedText.Params.Builder(paint) + .setHyphenationFrequency(frequency).setBreakStrategy(strategy).build(); + return PrecomputedText.create(text, param); + } + @Test public void testCreate_FixedText_NoStyle_Greedy_NoHyphenation() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); @@ -151,15 +163,13 @@ public class StaticLayoutPerfTest { } @Test - public void testCreate_MeasuredText_NoStyled_Greedy_NoHyphenation() { + public void testCreate_PrecomputedText_NoStyled_Greedy_NoHyphenation() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { state.pauseTiming(); - final MeasuredText text = new MeasuredText.Builder( - mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT) - .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) - .build(); + final PrecomputedText text = makeMeasured( + mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, + Layout.BREAK_STRATEGY_SIMPLE, Layout.HYPHENATION_FREQUENCY_NONE); state.resumeTiming(); StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) @@ -170,15 +180,13 @@ public class StaticLayoutPerfTest { } @Test - public void testCreate_MeasuredText_NoStyled_Greedy_Hyphenation() { + public void testCreate_PrecomputedText_NoStyled_Greedy_Hyphenation() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { state.pauseTiming(); - final MeasuredText text = new MeasuredText.Builder( - mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT) - .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) - .build(); + final PrecomputedText text = makeMeasured( + mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, + Layout.BREAK_STRATEGY_SIMPLE, Layout.HYPHENATION_FREQUENCY_NORMAL); state.resumeTiming(); StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) @@ -189,15 +197,13 @@ public class StaticLayoutPerfTest { } @Test - public void testCreate_MeasuredText_NoStyled_Balanced_NoHyphenation() { + public void testCreate_PrecomputedText_NoStyled_Balanced_NoHyphenation() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { state.pauseTiming(); - final MeasuredText text = new MeasuredText.Builder( - mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT) - .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) - .build(); + final PrecomputedText text = makeMeasured( + mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, + Layout.BREAK_STRATEGY_BALANCED, Layout.HYPHENATION_FREQUENCY_NONE); state.resumeTiming(); StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) @@ -208,15 +214,13 @@ public class StaticLayoutPerfTest { } @Test - public void testCreate_MeasuredText_NoStyled_Balanced_Hyphenation() { + public void testCreate_PrecomputedText_NoStyled_Balanced_Hyphenation() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { state.pauseTiming(); - final MeasuredText text = new MeasuredText.Builder( - mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT) - .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) - .build(); + final PrecomputedText text = makeMeasured( + mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, + Layout.BREAK_STRATEGY_BALANCED, Layout.HYPHENATION_FREQUENCY_NORMAL); state.resumeTiming(); StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) @@ -227,15 +231,13 @@ public class StaticLayoutPerfTest { } @Test - public void testCreate_MeasuredText_Styled_Greedy_NoHyphenation() { + public void testCreate_PrecomputedText_Styled_Greedy_NoHyphenation() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { state.pauseTiming(); - final MeasuredText text = new MeasuredText.Builder( - mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT) - .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) - .build(); + final PrecomputedText text = makeMeasured( + mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT, + Layout.BREAK_STRATEGY_SIMPLE, Layout.HYPHENATION_FREQUENCY_NONE); state.resumeTiming(); StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) @@ -328,13 +330,13 @@ public class StaticLayoutPerfTest { } @Test - public void testDraw_MeasuredText_Styled() { + public void testDraw_PrecomputedText_Styled() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); final RenderNode node = RenderNode.create("benchmark", null); while (state.keepRunning()) { state.pauseTiming(); - final MeasuredText text = new MeasuredText.Builder( - mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT).build(); + final PrecomputedText text = makeMeasured( + mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT); final StaticLayout layout = StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build(); final DisplayListCanvas c = node.start(1200, 200); @@ -345,13 +347,13 @@ public class StaticLayoutPerfTest { } @Test - public void testDraw_MeasuredText_NoStyled() { + public void testDraw_PrecomputedText_NoStyled() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); final RenderNode node = RenderNode.create("benchmark", null); while (state.keepRunning()) { state.pauseTiming(); - final MeasuredText text = new MeasuredText.Builder( - mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT).build(); + final PrecomputedText text = makeMeasured( + mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT); final StaticLayout layout = StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build(); final DisplayListCanvas c = node.start(1200, 200); @@ -362,13 +364,13 @@ public class StaticLayoutPerfTest { } @Test - public void testDraw_MeasuredText_Styled_WithoutCache() { + public void testDraw_PrecomputedText_Styled_WithoutCache() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); final RenderNode node = RenderNode.create("benchmark", null); while (state.keepRunning()) { state.pauseTiming(); - final MeasuredText text = new MeasuredText.Builder( - mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT).build(); + final PrecomputedText text = makeMeasured( + mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT); final StaticLayout layout = StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build(); final DisplayListCanvas c = node.start(1200, 200); @@ -380,13 +382,13 @@ public class StaticLayoutPerfTest { } @Test - public void testDraw_MeasuredText_NoStyled_WithoutCache() { + public void testDraw_PrecomputedText_NoStyled_WithoutCache() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); final RenderNode node = RenderNode.create("benchmark", null); while (state.keepRunning()) { state.pauseTiming(); - final MeasuredText text = new MeasuredText.Builder( - mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT).build(); + final PrecomputedText text = makeMeasured( + mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT); final StaticLayout layout = StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build(); final DisplayListCanvas c = node.start(1200, 200); diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java b/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java index 2c84db18ce54c09676191015c05204b1c0d00a7c..40778de4e521554d7fd25e93d39f81e453b876f4 100644 --- a/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java +++ b/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java @@ -150,6 +150,8 @@ public final class ManualBenchmarkState { final Bundle status = new Bundle(); status.putLong(key + "_median", mStats.getMedian()); status.putLong(key + "_mean", (long) mStats.getMean()); + status.putLong(key + "_percentile90", mStats.getPercentile90()); + status.putLong(key + "_percentile95", mStats.getPercentile95()); status.putLong(key + "_stddev", (long) mStats.getStandardDeviation()); instrumentation.sendStatus(Activity.RESULT_OK, status); } diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/Stats.java b/apct-tests/perftests/utils/src/android/perftests/utils/Stats.java index acc44a8febfcfcf2feb17d40c4436c99209a46ee..5e50073c06744cab7fb9f8a135e05b313994679e 100644 --- a/apct-tests/perftests/utils/src/android/perftests/utils/Stats.java +++ b/apct-tests/perftests/utils/src/android/perftests/utils/Stats.java @@ -21,7 +21,7 @@ import java.util.Collections; import java.util.List; public class Stats { - private long mMedian, mMin, mMax; + private long mMedian, mMin, mMax, mPercentile90, mPercentile95; private double mMean, mStandardDeviation; /* Calculate stats in constructor. */ @@ -35,12 +35,14 @@ public class Stats { Collections.sort(values); - mMedian = size % 2 == 0 ? (values.get(size / 2) + values.get(size / 2 - 1)) / 2 : - values.get(size / 2); - mMin = values.get(0); mMax = values.get(values.size() - 1); + mMedian = size % 2 == 0 ? (values.get(size / 2) + values.get(size / 2 - 1)) / 2 : + values.get(size / 2); + mPercentile90 = getPercentile(values, 90); + mPercentile95 = getPercentile(values, 95); + for (int i = 0; i < size; ++i) { long result = values.get(i); mMean += result; @@ -73,4 +75,21 @@ public class Stats { public double getStandardDeviation() { return mStandardDeviation; } + + public long getPercentile90() { + return mPercentile90; + } + + public long getPercentile95() { + return mPercentile95; + } + + private static long getPercentile(List values, int percentile) { + if (percentile < 0 || percentile > 100) { + throw new IllegalArgumentException( + "invalid percentile " + percentile + ", should be 0-100"); + } + int idx = (values.size() - 1) * percentile / 100; + return values.get(idx); + } } diff --git a/api/current.txt b/api/current.txt index 83a456079d58a8ab72ddff710ad83fb6415807a5..fff502a577db85abf992a9620a93c5b8375493e8 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4070,7 +4070,7 @@ package android.app { method public android.app.ActivityOptions setAppVerificationBundle(android.os.Bundle); method public android.app.ActivityOptions setLaunchBounds(android.graphics.Rect); method public android.app.ActivityOptions setLaunchDisplayId(int); - method public android.app.ActivityOptions setLockTaskMode(boolean); + method public android.app.ActivityOptions setLockTaskEnabled(boolean); method public android.os.Bundle toBundle(); method public void update(android.app.ActivityOptions); field public static final java.lang.String EXTRA_USAGE_TIME_REPORT = "android.activity.usage_time"; @@ -5312,6 +5312,7 @@ package android.app { method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; field public static final int SEMANTIC_ACTION_ARCHIVE = 5; // 0x5 + field public static final int SEMANTIC_ACTION_CALL = 10; // 0xa field public static final int SEMANTIC_ACTION_DELETE = 4; // 0x4 field public static final int SEMANTIC_ACTION_MARK_AS_READ = 2; // 0x2 field public static final int SEMANTIC_ACTION_MARK_AS_UNREAD = 3; // 0x3 @@ -5348,18 +5349,18 @@ package android.app { ctor public Notification.Action.WearableExtender(android.app.Notification.Action); method public android.app.Notification.Action.WearableExtender clone(); method public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Builder); - method public java.lang.CharSequence getCancelLabel(); - method public java.lang.CharSequence getConfirmLabel(); + method public deprecated java.lang.CharSequence getCancelLabel(); + method public deprecated java.lang.CharSequence getConfirmLabel(); method public boolean getHintDisplayActionInline(); method public boolean getHintLaunchesActivity(); - method public java.lang.CharSequence getInProgressLabel(); + method public deprecated java.lang.CharSequence getInProgressLabel(); method public boolean isAvailableOffline(); method public android.app.Notification.Action.WearableExtender setAvailableOffline(boolean); - method public android.app.Notification.Action.WearableExtender setCancelLabel(java.lang.CharSequence); - method public android.app.Notification.Action.WearableExtender setConfirmLabel(java.lang.CharSequence); + method public deprecated android.app.Notification.Action.WearableExtender setCancelLabel(java.lang.CharSequence); + method public deprecated android.app.Notification.Action.WearableExtender setConfirmLabel(java.lang.CharSequence); method public android.app.Notification.Action.WearableExtender setHintDisplayActionInline(boolean); method public android.app.Notification.Action.WearableExtender setHintLaunchesActivity(boolean); - method public android.app.Notification.Action.WearableExtender setInProgressLabel(java.lang.CharSequence); + method public deprecated android.app.Notification.Action.WearableExtender setInProgressLabel(java.lang.CharSequence); } public static class Notification.BigPictureStyle extends android.app.Notification.Style { @@ -5582,39 +5583,39 @@ package android.app { method public android.graphics.Bitmap getBackground(); method public java.lang.String getBridgeTag(); method public int getContentAction(); - method public int getContentIcon(); - method public int getContentIconGravity(); + method public deprecated int getContentIcon(); + method public deprecated int getContentIconGravity(); method public boolean getContentIntentAvailableOffline(); - method public int getCustomContentHeight(); - method public int getCustomSizePreset(); + method public deprecated int getCustomContentHeight(); + method public deprecated int getCustomSizePreset(); method public java.lang.String getDismissalId(); method public android.app.PendingIntent getDisplayIntent(); - method public int getGravity(); + method public deprecated int getGravity(); method public boolean getHintAmbientBigPicture(); - method public boolean getHintAvoidBackgroundClipping(); + method public deprecated boolean getHintAvoidBackgroundClipping(); method public boolean getHintContentIntentLaunchesActivity(); - method public boolean getHintHideIcon(); - method public int getHintScreenTimeout(); - method public boolean getHintShowBackgroundOnly(); + method public deprecated boolean getHintHideIcon(); + method public deprecated int getHintScreenTimeout(); + method public deprecated boolean getHintShowBackgroundOnly(); method public java.util.List getPages(); method public boolean getStartScrollBottom(); method public android.app.Notification.WearableExtender setBackground(android.graphics.Bitmap); method public android.app.Notification.WearableExtender setBridgeTag(java.lang.String); method public android.app.Notification.WearableExtender setContentAction(int); - method public android.app.Notification.WearableExtender setContentIcon(int); - method public android.app.Notification.WearableExtender setContentIconGravity(int); + method public deprecated android.app.Notification.WearableExtender setContentIcon(int); + method public deprecated android.app.Notification.WearableExtender setContentIconGravity(int); method public android.app.Notification.WearableExtender setContentIntentAvailableOffline(boolean); - method public android.app.Notification.WearableExtender setCustomContentHeight(int); - method public android.app.Notification.WearableExtender setCustomSizePreset(int); + method public deprecated android.app.Notification.WearableExtender setCustomContentHeight(int); + method public deprecated android.app.Notification.WearableExtender setCustomSizePreset(int); method public android.app.Notification.WearableExtender setDismissalId(java.lang.String); method public android.app.Notification.WearableExtender setDisplayIntent(android.app.PendingIntent); - method public android.app.Notification.WearableExtender setGravity(int); + method public deprecated android.app.Notification.WearableExtender setGravity(int); method public android.app.Notification.WearableExtender setHintAmbientBigPicture(boolean); - method public android.app.Notification.WearableExtender setHintAvoidBackgroundClipping(boolean); + method public deprecated android.app.Notification.WearableExtender setHintAvoidBackgroundClipping(boolean); method public android.app.Notification.WearableExtender setHintContentIntentLaunchesActivity(boolean); - method public android.app.Notification.WearableExtender setHintHideIcon(boolean); - method public android.app.Notification.WearableExtender setHintScreenTimeout(int); - method public android.app.Notification.WearableExtender setHintShowBackgroundOnly(boolean); + method public deprecated android.app.Notification.WearableExtender setHintHideIcon(boolean); + method public deprecated android.app.Notification.WearableExtender setHintScreenTimeout(int); + method public deprecated android.app.Notification.WearableExtender setHintShowBackgroundOnly(boolean); method public android.app.Notification.WearableExtender setStartScrollBottom(boolean); field public static final int SCREEN_TIMEOUT_LONG = -1; // 0xffffffff field public static final int SCREEN_TIMEOUT_SHORT = 0; // 0x0 @@ -6594,7 +6595,7 @@ package android.app.admin { method public void uninstallCaCert(android.content.ComponentName, byte[]); method public boolean updateOverrideApn(android.content.ComponentName, int, android.telephony.data.ApnSetting); method public void wipeData(int); - method public void wipeDataWithReason(int, java.lang.CharSequence); + method public void wipeData(int, java.lang.CharSequence); field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN"; field public static final java.lang.String ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED = "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED"; field public static final java.lang.String ACTION_DEVICE_ADMIN_SERVICE = "android.app.action.DEVICE_ADMIN_SERVICE"; @@ -6677,7 +6678,7 @@ package android.app.admin { field public static final int LOCK_TASK_FEATURE_KEYGUARD = 32; // 0x20 field public static final int LOCK_TASK_FEATURE_NONE = 0; // 0x0 field public static final int LOCK_TASK_FEATURE_NOTIFICATIONS = 2; // 0x2 - field public static final int LOCK_TASK_FEATURE_RECENTS = 8; // 0x8 + field public static final int LOCK_TASK_FEATURE_OVERVIEW = 8; // 0x8 field public static final int LOCK_TASK_FEATURE_SYSTEM_INFO = 1; // 0x1 field public static final int MAKE_USER_EPHEMERAL = 2; // 0x2 field public static final java.lang.String MIME_TYPE_PROVISIONING_NFC = "application/com.android.managedprovisioning"; @@ -7266,6 +7267,7 @@ package android.app.slice { method public void registerSliceCallback(android.net.Uri, java.util.List, java.util.concurrent.Executor, android.app.slice.SliceManager.SliceCallback); method public void unpinSlice(android.net.Uri); method public void unregisterSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback); + field public static final java.lang.String SLICE_METADATA_KEY = "android.metadata.SLICE_URI"; } public static abstract interface SliceManager.SliceCallback { @@ -11388,6 +11390,8 @@ package android.content.pm { ctor public PermissionInfo(); ctor public PermissionInfo(android.content.pm.PermissionInfo); method public int describeContents(); + method public int getProtection(); + method public int getProtectionFlags(); method public java.lang.CharSequence loadDescription(android.content.pm.PackageManager); field public static final android.os.Parcelable.Creator CREATOR; field public static final int FLAG_COSTS_MONEY = 1; // 0x1 @@ -11404,8 +11408,8 @@ package android.content.pm { field public static final int PROTECTION_FLAG_SETUP = 2048; // 0x800 field public static final deprecated int PROTECTION_FLAG_SYSTEM = 16; // 0x10 field public static final int PROTECTION_FLAG_VERIFIER = 512; // 0x200 - field public static final int PROTECTION_MASK_BASE = 15; // 0xf - field public static final int PROTECTION_MASK_FLAGS = 65520; // 0xfff0 + field public static final deprecated int PROTECTION_MASK_BASE = 15; // 0xf + field public static final deprecated int PROTECTION_MASK_FLAGS = 65520; // 0xfff0 field public static final int PROTECTION_NORMAL = 0; // 0x0 field public static final int PROTECTION_SIGNATURE = 2; // 0x2 field public static final deprecated int PROTECTION_SIGNATURE_OR_SYSTEM = 3; // 0x3 @@ -11413,7 +11417,7 @@ package android.content.pm { field public int flags; field public java.lang.String group; field public java.lang.CharSequence nonLocalizedDescription; - field public int protectionLevel; + field public deprecated int protectionLevel; } public final class ProviderInfo extends android.content.pm.ComponentInfo implements android.os.Parcelable { @@ -13777,7 +13781,7 @@ package android.graphics { enum_constant public static final android.graphics.Matrix.ScaleToFit START; } - public class Movie { + public deprecated class Movie { method public static android.graphics.Movie decodeByteArray(byte[], int, int); method public static android.graphics.Movie decodeFile(java.lang.String); method public static android.graphics.Movie decodeStream(java.io.InputStream); @@ -13839,6 +13843,7 @@ package android.graphics { method public int breakText(java.lang.String, boolean, float, float[]); method public void clearShadowLayer(); method public float descent(); + method public boolean equalsForTextMeasurement(android.graphics.Paint); method public int getAlpha(); method public int getColor(); method public android.graphics.ColorFilter getColorFilter(); @@ -14505,7 +14510,9 @@ package android.graphics.drawable { ctor public AnimatedImageDrawable(); method public void clearAnimationCallbacks(); method public void draw(android.graphics.Canvas); + method public int getLoopCount(); method public int getOpacity(); + method public final boolean isAutoMirrored(); method public boolean isRunning(); method public void registerAnimationCallback(android.graphics.drawable.Animatable2.AnimationCallback); method public void setAlpha(int); @@ -16271,9 +16278,7 @@ package android.hardware.camera2 { field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_LENS_SHADING_CORRECTION_MAP; field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_LENS_SHADING_MAP_MODE; field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_OIS_DATA_MODE; - field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_OIS_TIMESTAMPS; - field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_OIS_X_SHIFTS; - field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_OIS_Y_SHIFTS; + field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_OIS_SAMPLES; field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_SCENE_FLICKER; field public static final android.hardware.camera2.CaptureResult.Key TONEMAP_CURVE; field public static final android.hardware.camera2.CaptureResult.Key TONEMAP_GAMMA; @@ -16369,6 +16374,13 @@ package android.hardware.camera2.params { field public static final int METERING_WEIGHT_MIN = 0; // 0x0 } + public final class OisSample { + ctor public OisSample(long, float, float); + method public long getTimestamp(); + method public float getXshift(); + method public float getYshift(); + } + public final class OutputConfiguration implements android.os.Parcelable { ctor public OutputConfiguration(android.view.Surface); ctor public OutputConfiguration(int, android.view.Surface); @@ -16570,7 +16582,7 @@ package android.hardware.fingerprint { field public static final int FINGERPRINT_ERROR_VENDOR = 8; // 0x8 } - public static abstract class FingerprintManager.AuthenticationCallback { + public static abstract deprecated class FingerprintManager.AuthenticationCallback { ctor public FingerprintManager.AuthenticationCallback(); method public void onAuthenticationError(int, java.lang.CharSequence); method public void onAuthenticationFailed(); @@ -16578,11 +16590,11 @@ package android.hardware.fingerprint { method public void onAuthenticationSucceeded(android.hardware.fingerprint.FingerprintManager.AuthenticationResult); } - public static class FingerprintManager.AuthenticationResult { + public static deprecated class FingerprintManager.AuthenticationResult { method public android.hardware.fingerprint.FingerprintManager.CryptoObject getCryptoObject(); } - public static final class FingerprintManager.CryptoObject { + public static final deprecated class FingerprintManager.CryptoObject { ctor public FingerprintManager.CryptoObject(java.security.Signature); ctor public FingerprintManager.CryptoObject(javax.crypto.Cipher); ctor public FingerprintManager.CryptoObject(javax.crypto.Mac); @@ -21901,6 +21913,7 @@ package android.media { field public static final int TYPE_FM_TUNER = 16; // 0x10 field public static final int TYPE_HDMI = 9; // 0x9 field public static final int TYPE_HDMI_ARC = 10; // 0xa + field public static final int TYPE_HEARING_AID = 23; // 0x17 field public static final int TYPE_IP = 20; // 0x14 field public static final int TYPE_LINE_ANALOG = 5; // 0x5 field public static final int TYPE_LINE_DIGITAL = 6; // 0x6 @@ -22829,6 +22842,27 @@ package android.media { field public static final int STOP_VIDEO_RECORDING = 3; // 0x3 } + public class MediaBrowser2 extends android.media.MediaController2 { + ctor public MediaBrowser2(android.content.Context, android.media.SessionToken2, java.util.concurrent.Executor, android.media.MediaBrowser2.BrowserCallback); + method public void getChildren(java.lang.String, int, int, android.os.Bundle); + method public void getItem(java.lang.String); + method public void getLibraryRoot(android.os.Bundle); + method public void getSearchResult(java.lang.String, int, int, android.os.Bundle); + method public void search(java.lang.String, android.os.Bundle); + method public void subscribe(java.lang.String, android.os.Bundle); + method public void unsubscribe(java.lang.String); + } + + public static class MediaBrowser2.BrowserCallback extends android.media.MediaController2.ControllerCallback { + ctor public MediaBrowser2.BrowserCallback(); + method public void onChildrenChanged(java.lang.String, int, android.os.Bundle); + method public void onGetChildrenDone(java.lang.String, int, int, java.util.List, android.os.Bundle); + method public void onGetItemDone(java.lang.String, android.media.MediaItem2); + method public void onGetLibraryRootDone(android.os.Bundle, java.lang.String, android.os.Bundle); + method public void onGetSearchResultDone(java.lang.String, int, int, java.util.List, android.os.Bundle); + method public void onSearchResultChanged(java.lang.String, int, android.os.Bundle); + } + public final class MediaCas implements java.lang.AutoCloseable { ctor public MediaCas(int) throws android.media.MediaCasException.UnsupportedCasException; method public void close(); @@ -23305,6 +23339,73 @@ package android.media { field public static final int REGULAR_CODECS = 0; // 0x0 } + public class MediaController2 implements java.lang.AutoCloseable { + ctor public MediaController2(android.content.Context, android.media.SessionToken2, java.util.concurrent.Executor, android.media.MediaController2.ControllerCallback); + method public void addPlaylistItem(int, android.media.MediaItem2); + method public void adjustVolume(int, int); + method public void close(); + method public void fastForward(); + method public long getBufferedPosition(); + method public android.media.MediaItem2 getCurrentPlaylistItem(); + method public android.media.MediaController2.PlaybackInfo getPlaybackInfo(); + method public float getPlaybackSpeed(); + method public int getPlayerState(); + method public java.util.List getPlaylist(); + method public android.media.MediaSession2.PlaylistParams getPlaylistParams(); + method public long getPosition(); + method public android.app.PendingIntent getSessionActivity(); + method public android.media.SessionToken2 getSessionToken(); + method public boolean isConnected(); + method public void pause(); + method public void play(); + method public void playFromMediaId(java.lang.String, android.os.Bundle); + method public void playFromSearch(java.lang.String, android.os.Bundle); + method public void playFromUri(android.net.Uri, android.os.Bundle); + method public void prepare(); + method public void prepareFromMediaId(java.lang.String, android.os.Bundle); + method public void prepareFromSearch(java.lang.String, android.os.Bundle); + method public void prepareFromUri(android.net.Uri, android.os.Bundle); + method public void removePlaylistItem(android.media.MediaItem2); + method public void rewind(); + method public void seekTo(long); + method public void sendCustomCommand(android.media.MediaSession2.Command, android.os.Bundle, android.os.ResultReceiver); + method public void setPlaylistParams(android.media.MediaSession2.PlaylistParams); + method public void setRating(java.lang.String, android.media.Rating2); + method public void setVolumeTo(int, int); + method public void skipToNext(); + method public void skipToPlaylistItem(android.media.MediaItem2); + method public void skipToPrevious(); + method public void stop(); + } + + public static abstract class MediaController2.ControllerCallback { + ctor public MediaController2.ControllerCallback(); + method public void onAllowedCommandsChanged(android.media.MediaSession2.CommandGroup); + method public void onBufferedPositionChanged(long); + method public void onConnected(android.media.MediaSession2.CommandGroup); + method public void onCurrentPlaylistItemChanged(android.media.MediaItem2); + method public void onCustomCommand(android.media.MediaSession2.Command, android.os.Bundle, android.os.ResultReceiver); + method public void onCustomLayoutChanged(java.util.List); + method public void onDisconnected(); + method public void onError(int, int); + method public void onPlaybackInfoChanged(android.media.MediaController2.PlaybackInfo); + method public void onPlaybackSpeedChanged(float); + method public void onPlayerStateChanged(int); + method public void onPlaylistChanged(java.util.List); + method public void onPlaylistParamsChanged(android.media.MediaSession2.PlaylistParams); + method public void onPositionUpdated(long, long); + } + + public static final class MediaController2.PlaybackInfo { + method public android.media.AudioAttributes getAudioAttributes(); + method public int getControlType(); + method public int getCurrentVolume(); + method public int getMaxVolume(); + method public int getPlaybackType(); + field public static final int PLAYBACK_TYPE_LOCAL = 1; // 0x1 + field public static final int PLAYBACK_TYPE_REMOTE = 2; // 0x2 + } + public final class MediaCrypto { ctor public MediaCrypto(java.util.UUID, byte[]) throws android.media.MediaCryptoException; method protected void finalize(); @@ -23615,6 +23716,7 @@ package android.media { field public static final int COLOR_TRANSFER_ST2084 = 6; // 0x6 field public static final java.lang.String KEY_AAC_DRC_ATTENUATION_FACTOR = "aac-drc-cut-level"; field public static final java.lang.String KEY_AAC_DRC_BOOST_FACTOR = "aac-drc-boost-level"; + field public static final java.lang.String KEY_AAC_DRC_EFFECT_TYPE = "aac-drc-effect-type"; field public static final java.lang.String KEY_AAC_DRC_HEAVY_COMPRESSION = "aac-drc-heavy-compression"; field public static final java.lang.String KEY_AAC_DRC_TARGET_REFERENCE_LEVEL = "aac-target-ref-level"; field public static final java.lang.String KEY_AAC_ENCODED_TARGET_LEVEL = "aac-encoded-target-level"; @@ -23699,6 +23801,69 @@ package android.media { field public static final java.lang.String MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9"; } + public class MediaItem2 { + method public static android.media.MediaItem2 fromBundle(android.content.Context, android.os.Bundle); + method public android.media.DataSourceDesc getDataSourceDesc(); + method public int getFlags(); + method public java.lang.String getMediaId(); + method public android.media.MediaMetadata2 getMetadata(); + method public boolean isBrowsable(); + method public boolean isPlayable(); + method public void setMetadata(android.media.MediaMetadata2); + method public android.os.Bundle toBundle(); + field public static final int FLAG_BROWSABLE = 1; // 0x1 + field public static final int FLAG_PLAYABLE = 2; // 0x2 + } + + public static final class MediaItem2.Builder { + ctor public MediaItem2.Builder(android.content.Context, int); + method public android.media.MediaItem2 build(); + method public android.media.MediaItem2.Builder setDataSourceDesc(android.media.DataSourceDesc); + method public android.media.MediaItem2.Builder setMediaId(java.lang.String); + method public android.media.MediaItem2.Builder setMetadata(android.media.MediaMetadata2); + } + + public abstract class MediaLibraryService2 extends android.media.MediaSessionService2 { + ctor public MediaLibraryService2(); + method public abstract android.media.MediaLibraryService2.MediaLibrarySession onCreateSession(java.lang.String); + field public static final java.lang.String SERVICE_INTERFACE = "android.media.MediaLibraryService2"; + } + + public static final class MediaLibraryService2.LibraryRoot { + ctor public MediaLibraryService2.LibraryRoot(android.content.Context, java.lang.String, android.os.Bundle); + method public android.os.Bundle getExtras(); + method public java.lang.String getRootId(); + field public static final java.lang.String EXTRA_OFFLINE = "android.media.extra.OFFLINE"; + field public static final java.lang.String EXTRA_RECENT = "android.media.extra.RECENT"; + field public static final java.lang.String EXTRA_SUGGESTED = "android.media.extra.SUGGESTED"; + } + + public static final class MediaLibraryService2.MediaLibrarySession extends android.media.MediaSession2 { + method public void notifyChildrenChanged(android.media.MediaSession2.ControllerInfo, java.lang.String, int, android.os.Bundle); + method public void notifyChildrenChanged(java.lang.String, int, android.os.Bundle); + method public void notifySearchResultChanged(android.media.MediaSession2.ControllerInfo, java.lang.String, int, android.os.Bundle); + } + + public static final class MediaLibraryService2.MediaLibrarySession.Builder { + ctor public MediaLibraryService2.MediaLibrarySession.Builder(android.media.MediaLibraryService2, android.media.MediaPlayerBase, java.util.concurrent.Executor, android.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback); + method public android.media.MediaLibraryService2.MediaLibrarySession build(); + method public android.media.MediaLibraryService2.MediaLibrarySession.Builder setId(java.lang.String); + method public android.media.MediaLibraryService2.MediaLibrarySession.Builder setSessionActivity(android.app.PendingIntent); + method public android.media.MediaLibraryService2.MediaLibrarySession.Builder setSessionCallback(java.util.concurrent.Executor, android.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback); + method public android.media.MediaLibraryService2.MediaLibrarySession.Builder setVolumeProvider(android.media.VolumeProvider2); + } + + public static class MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback extends android.media.MediaSession2.SessionCallback { + ctor public MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback(android.content.Context); + method public java.util.List onGetChildren(android.media.MediaSession2.ControllerInfo, java.lang.String, int, int, android.os.Bundle); + method public android.media.MediaItem2 onGetItem(android.media.MediaSession2.ControllerInfo, java.lang.String); + method public android.media.MediaLibraryService2.LibraryRoot onGetLibraryRoot(android.media.MediaSession2.ControllerInfo, android.os.Bundle); + method public java.util.List onGetSearchResult(android.media.MediaSession2.ControllerInfo, java.lang.String, int, int, android.os.Bundle); + method public void onSearch(android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle); + method public void onSubscribe(android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle); + method public void onUnsubscribe(android.media.MediaSession2.ControllerInfo, java.lang.String); + } + public final class MediaMetadata implements android.os.Parcelable { method public boolean containsKey(java.lang.String); method public int describeContents(); @@ -23754,6 +23919,79 @@ package android.media { method public android.media.MediaMetadata.Builder putText(java.lang.String, java.lang.CharSequence); } + public final class MediaMetadata2 { + method public boolean containsKey(java.lang.String); + method public static android.media.MediaMetadata2 fromBundle(android.content.Context, android.os.Bundle); + method public android.graphics.Bitmap getBitmap(java.lang.String); + method public android.os.Bundle getExtras(); + method public float getFloat(java.lang.String); + method public long getLong(java.lang.String); + method public java.lang.String getMediaId(); + method public android.media.Rating2 getRating(java.lang.String); + method public java.lang.String getString(java.lang.String); + method public java.lang.CharSequence getText(java.lang.String); + method public java.util.Set keySet(); + method public int size(); + method public android.os.Bundle toBundle(); + field public static final long BT_FOLDER_TYPE_ALBUMS = 2L; // 0x2L + field public static final long BT_FOLDER_TYPE_ARTISTS = 3L; // 0x3L + field public static final long BT_FOLDER_TYPE_GENRES = 4L; // 0x4L + field public static final long BT_FOLDER_TYPE_MIXED = 0L; // 0x0L + field public static final long BT_FOLDER_TYPE_PLAYLISTS = 5L; // 0x5L + field public static final long BT_FOLDER_TYPE_TITLES = 1L; // 0x1L + field public static final long BT_FOLDER_TYPE_YEARS = 6L; // 0x6L + field public static final java.lang.String METADATA_KEY_ADVERTISEMENT = "android.media.metadata.ADVERTISEMENT"; + field public static final java.lang.String METADATA_KEY_ALBUM = "android.media.metadata.ALBUM"; + field public static final java.lang.String METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART"; + field public static final java.lang.String METADATA_KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST"; + field public static final java.lang.String METADATA_KEY_ALBUM_ART_URI = "android.media.metadata.ALBUM_ART_URI"; + field public static final java.lang.String METADATA_KEY_ART = "android.media.metadata.ART"; + field public static final java.lang.String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST"; + field public static final java.lang.String METADATA_KEY_ART_URI = "android.media.metadata.ART_URI"; + field public static final java.lang.String METADATA_KEY_AUTHOR = "android.media.metadata.AUTHOR"; + field public static final java.lang.String METADATA_KEY_BT_FOLDER_TYPE = "android.media.metadata.BT_FOLDER_TYPE"; + field public static final java.lang.String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION"; + field public static final java.lang.String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER"; + field public static final java.lang.String METADATA_KEY_DATE = "android.media.metadata.DATE"; + field public static final java.lang.String METADATA_KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER"; + field public static final java.lang.String METADATA_KEY_DISPLAY_DESCRIPTION = "android.media.metadata.DISPLAY_DESCRIPTION"; + field public static final java.lang.String METADATA_KEY_DISPLAY_ICON = "android.media.metadata.DISPLAY_ICON"; + field public static final java.lang.String METADATA_KEY_DISPLAY_ICON_URI = "android.media.metadata.DISPLAY_ICON_URI"; + field public static final java.lang.String METADATA_KEY_DISPLAY_SUBTITLE = "android.media.metadata.DISPLAY_SUBTITLE"; + field public static final java.lang.String METADATA_KEY_DISPLAY_TITLE = "android.media.metadata.DISPLAY_TITLE"; + field public static final java.lang.String METADATA_KEY_DOWNLOAD_STATUS = "android.media.metadata.DOWNLOAD_STATUS"; + field public static final java.lang.String METADATA_KEY_DURATION = "android.media.metadata.DURATION"; + field public static final java.lang.String METADATA_KEY_EXTRAS = "android.media.metadata.EXTRAS"; + field public static final java.lang.String METADATA_KEY_GENRE = "android.media.metadata.GENRE"; + field public static final java.lang.String METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID"; + field public static final java.lang.String METADATA_KEY_MEDIA_URI = "android.media.metadata.MEDIA_URI"; + field public static final java.lang.String METADATA_KEY_NUM_TRACKS = "android.media.metadata.NUM_TRACKS"; + field public static final java.lang.String METADATA_KEY_RADIO_CALLSIGN = "android.media.metadata.RADIO_CALLSIGN"; + field public static final java.lang.String METADATA_KEY_RADIO_FREQUENCY = "android.media.metadata.RADIO_FREQUENCY"; + field public static final java.lang.String METADATA_KEY_RATING = "android.media.metadata.RATING"; + field public static final java.lang.String METADATA_KEY_TITLE = "android.media.metadata.TITLE"; + field public static final java.lang.String METADATA_KEY_TRACK_NUMBER = "android.media.metadata.TRACK_NUMBER"; + field public static final java.lang.String METADATA_KEY_USER_RATING = "android.media.metadata.USER_RATING"; + field public static final java.lang.String METADATA_KEY_WRITER = "android.media.metadata.WRITER"; + field public static final java.lang.String METADATA_KEY_YEAR = "android.media.metadata.YEAR"; + field public static final long STATUS_DOWNLOADED = 2L; // 0x2L + field public static final long STATUS_DOWNLOADING = 1L; // 0x1L + field public static final long STATUS_NOT_DOWNLOADED = 0L; // 0x0L + } + + public static final class MediaMetadata2.Builder { + ctor public MediaMetadata2.Builder(android.content.Context); + ctor public MediaMetadata2.Builder(android.content.Context, android.media.MediaMetadata2); + method public android.media.MediaMetadata2 build(); + method public android.media.MediaMetadata2.Builder putBitmap(java.lang.String, android.graphics.Bitmap); + method public android.media.MediaMetadata2.Builder putFloat(java.lang.String, float); + method public android.media.MediaMetadata2.Builder putLong(java.lang.String, long); + method public android.media.MediaMetadata2.Builder putRating(java.lang.String, android.media.Rating2); + method public android.media.MediaMetadata2.Builder putString(java.lang.String, java.lang.String); + method public android.media.MediaMetadata2.Builder putText(java.lang.String, java.lang.CharSequence); + method public android.media.MediaMetadata2.Builder setExtras(android.os.Bundle); + } + public abstract deprecated class MediaMetadataEditor { method public synchronized void addEditableKey(int); method public abstract void apply(); @@ -24069,13 +24307,14 @@ package android.media { method public static final android.media.MediaPlayer2 create(); method public abstract void deselectTrack(int); method public abstract android.media.DataSourceDesc editPlaylistItem(int, android.media.DataSourceDesc); + method public abstract android.media.AudioAttributes getAudioAttributes(); method public abstract int getAudioSessionId(); method public abstract android.media.DataSourceDesc getCurrentDataSource(); method public abstract int getCurrentPlaylistItemIndex(); - method public abstract int getCurrentPosition(); + method public abstract long getCurrentPosition(); method public abstract android.media.MediaPlayer2.DrmInfo getDrmInfo(); method public abstract java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer2.NoDrmSchemeException; - method public abstract int getDuration(); + method public abstract long getDuration(); method public abstract android.media.MediaDrm.KeyRequest getKeyRequest(byte[], byte[], java.lang.String, int, java.util.Map) throws android.media.MediaPlayer2.NoDrmSchemeException; method public abstract int getLoopingMode(); method public abstract android.os.PersistableBundle getMetrics(); @@ -24161,8 +24400,8 @@ package android.media { public static abstract class MediaPlayer2.DrmEventCallback { ctor public MediaPlayer2.DrmEventCallback(); - method public void onDrmInfo(android.media.MediaPlayer2, android.media.MediaPlayer2.DrmInfo); - method public void onDrmPrepared(android.media.MediaPlayer2, int); + method public void onDrmInfo(android.media.MediaPlayer2, long, android.media.MediaPlayer2.DrmInfo); + method public void onDrmPrepared(android.media.MediaPlayer2, long, int); } public static abstract class MediaPlayer2.DrmInfo { @@ -24200,7 +24439,7 @@ package android.media { } public static abstract interface MediaPlayer2.OnDrmConfigHelper { - method public abstract void onDrmConfig(android.media.MediaPlayer2); + method public abstract void onDrmConfig(android.media.MediaPlayer2, long); } public static abstract class MediaPlayer2.ProvisioningNetworkErrorException extends android.media.MediaDrmException { @@ -24224,6 +24463,19 @@ package android.media { field public static final int MEDIA_TRACK_TYPE_VIDEO = 1; // 0x1 } + public abstract class MediaPlayerBase implements java.lang.AutoCloseable { + ctor public MediaPlayerBase(); + method public abstract android.media.AudioAttributes getAudioAttributes(); + method public abstract int getPlayerState(); + method public abstract void pause(); + method public abstract void play(); + method public abstract void setAudioAttributes(android.media.AudioAttributes); + field public static final int STATE_ERROR = 0; // 0x0 + field public static final int STATE_IDLE = 0; // 0x0 + field public static final int STATE_PAUSED = 0; // 0x0 + field public static final int STATE_PLAYING = 0; // 0x0 + } + public class MediaRecorder implements android.media.AudioRouting { ctor public MediaRecorder(); method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); @@ -24500,6 +24752,172 @@ package android.media { method public abstract void onScanCompleted(java.lang.String, android.net.Uri); } + public class MediaSession2 implements java.lang.AutoCloseable { + method public void addPlaylistItem(int, android.media.MediaItem2); + method public void close(); + method public void editPlaylistItem(android.media.MediaItem2); + method public void fastForward(); + method public java.util.List getConnectedControllers(); + method public android.media.MediaItem2 getCurrentPlaylistItem(); + method public android.media.MediaPlayerBase getPlayer(); + method public java.util.List getPlaylist(); + method public android.media.MediaSession2.PlaylistParams getPlaylistParams(); + method public android.media.SessionToken2 getToken(); + method public void notifyError(int, int); + method public void pause(); + method public void play(); + method public void prepare(); + method public void removePlaylistItem(android.media.MediaItem2); + method public void rewind(); + method public void seekTo(long); + method public void sendCustomCommand(android.media.MediaSession2.Command, android.os.Bundle); + method public void sendCustomCommand(android.media.MediaSession2.ControllerInfo, android.media.MediaSession2.Command, android.os.Bundle, android.os.ResultReceiver); + method public void setAllowedCommands(android.media.MediaSession2.ControllerInfo, android.media.MediaSession2.CommandGroup); + method public void setCustomLayout(android.media.MediaSession2.ControllerInfo, java.util.List); + method public void setPlayer(android.media.MediaPlayerBase); + method public void setPlayer(android.media.MediaPlayerBase, android.media.VolumeProvider2); + method public void setPlaylist(java.util.List); + method public void setPlaylistParams(android.media.MediaSession2.PlaylistParams); + method public void skipToNext(); + method public void skipToPlaylistItem(android.media.MediaItem2); + method public void skipToPrevious(); + method public void stop(); + field public static final int COMMAND_CODE_BROWSER = 22; // 0x16 + field public static final int COMMAND_CODE_CUSTOM = 0; // 0x0 + field public static final int COMMAND_CODE_PLAYBACK_FAST_FORWARD = 7; // 0x7 + field public static final int COMMAND_CODE_PLAYBACK_PAUSE = 2; // 0x2 + field public static final int COMMAND_CODE_PLAYBACK_PLAY = 1; // 0x1 + field public static final int COMMAND_CODE_PLAYBACK_PREPARE = 6; // 0x6 + field public static final int COMMAND_CODE_PLAYBACK_REWIND = 8; // 0x8 + field public static final int COMMAND_CODE_PLAYBACK_SEEK_TO = 9; // 0x9 + field public static final int COMMAND_CODE_PLAYBACK_SET_CURRENT_PLAYLIST_ITEM = 10; // 0xa + field public static final int COMMAND_CODE_PLAYBACK_SET_PLAYLIST_PARAMS = 11; // 0xb + field public static final int COMMAND_CODE_PLAYBACK_SKIP_NEXT_ITEM = 4; // 0x4 + field public static final int COMMAND_CODE_PLAYBACK_SKIP_PREV_ITEM = 5; // 0x5 + field public static final int COMMAND_CODE_PLAYBACK_STOP = 3; // 0x3 + field public static final int COMMAND_CODE_PLAYLIST_ADD = 12; // 0xc + field public static final int COMMAND_CODE_PLAYLIST_GET = 14; // 0xe + field public static final int COMMAND_CODE_PLAYLIST_REMOVE = 13; // 0xd + field public static final int COMMAND_CODE_PLAY_FROM_MEDIA_ID = 16; // 0x10 + field public static final int COMMAND_CODE_PLAY_FROM_SEARCH = 18; // 0x12 + field public static final int COMMAND_CODE_PLAY_FROM_URI = 17; // 0x11 + field public static final int COMMAND_CODE_PREPARE_FROM_MEDIA_ID = 19; // 0x13 + field public static final int COMMAND_CODE_PREPARE_FROM_SEARCH = 21; // 0x15 + field public static final int COMMAND_CODE_PREPARE_FROM_URI = 20; // 0x14 + field public static final int COMMAND_CODE_SET_VOLUME = 15; // 0xf + field public static final int ERROR_CODE_ACTION_ABORTED = 10; // 0xa + field public static final int ERROR_CODE_APP_ERROR = 1; // 0x1 + field public static final int ERROR_CODE_AUTHENTICATION_EXPIRED = 3; // 0x3 + field public static final int ERROR_CODE_CONCURRENT_STREAM_LIMIT = 5; // 0x5 + field public static final int ERROR_CODE_CONTENT_ALREADY_PLAYING = 8; // 0x8 + field public static final int ERROR_CODE_END_OF_QUEUE = 11; // 0xb + field public static final int ERROR_CODE_NOT_AVAILABLE_IN_REGION = 7; // 0x7 + field public static final int ERROR_CODE_NOT_SUPPORTED = 2; // 0x2 + field public static final int ERROR_CODE_PARENTAL_CONTROL_RESTRICTED = 6; // 0x6 + field public static final int ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED = 4; // 0x4 + field public static final int ERROR_CODE_SETUP_REQUIRED = 12; // 0xc + field public static final int ERROR_CODE_SKIP_LIMIT_REACHED = 9; // 0x9 + field public static final int ERROR_CODE_UNKNOWN_ERROR = 0; // 0x0 + } + + public static final class MediaSession2.Builder { + ctor public MediaSession2.Builder(android.content.Context, android.media.MediaPlayerBase); + method public android.media.MediaSession2 build(); + method public android.media.MediaSession2.Builder setId(java.lang.String); + method public android.media.MediaSession2.Builder setSessionActivity(android.app.PendingIntent); + method public android.media.MediaSession2.Builder setSessionCallback(java.util.concurrent.Executor, android.media.MediaSession2.SessionCallback); + method public android.media.MediaSession2.Builder setVolumeProvider(android.media.VolumeProvider2); + } + + public static final class MediaSession2.Command { + ctor public MediaSession2.Command(android.content.Context, int); + ctor public MediaSession2.Command(android.content.Context, java.lang.String, android.os.Bundle); + method public int getCommandCode(); + method public java.lang.String getCustomCommand(); + method public android.os.Bundle getExtra(); + } + + public static final class MediaSession2.CommandButton { + method public android.media.MediaSession2.Command getCommand(); + method public java.lang.String getDisplayName(); + method public android.os.Bundle getExtra(); + method public int getIconResId(); + method public boolean isEnabled(); + } + + public static final class MediaSession2.CommandButton.Builder { + ctor public MediaSession2.CommandButton.Builder(android.content.Context); + method public android.media.MediaSession2.CommandButton build(); + method public android.media.MediaSession2.CommandButton.Builder setCommand(android.media.MediaSession2.Command); + method public android.media.MediaSession2.CommandButton.Builder setDisplayName(java.lang.String); + method public android.media.MediaSession2.CommandButton.Builder setEnabled(boolean); + method public android.media.MediaSession2.CommandButton.Builder setExtra(android.os.Bundle); + method public android.media.MediaSession2.CommandButton.Builder setIconResId(int); + } + + public static final class MediaSession2.CommandGroup { + ctor public MediaSession2.CommandGroup(android.content.Context); + ctor public MediaSession2.CommandGroup(android.content.Context, android.media.MediaSession2.CommandGroup); + method public void addAllPredefinedCommands(); + method public void addCommand(android.media.MediaSession2.Command); + method public boolean hasCommand(android.media.MediaSession2.Command); + method public boolean hasCommand(int); + method public void removeCommand(android.media.MediaSession2.Command); + } + + public static final class MediaSession2.ControllerInfo { + method public java.lang.String getPackageName(); + method public int getUid(); + method public boolean isTrusted(); + } + + public static final class MediaSession2.PlaylistParams { + ctor public MediaSession2.PlaylistParams(android.content.Context, int, int, android.media.MediaMetadata2); + method public static android.media.MediaSession2.PlaylistParams fromBundle(android.content.Context, android.os.Bundle); + method public android.media.MediaMetadata2 getPlaylistMetadata(); + method public int getRepeatMode(); + method public int getShuffleMode(); + method public android.os.Bundle toBundle(); + field public static final int REPEAT_MODE_ALL = 2; // 0x2 + field public static final int REPEAT_MODE_GROUP = 3; // 0x3 + field public static final int REPEAT_MODE_NONE = 0; // 0x0 + field public static final int REPEAT_MODE_ONE = 1; // 0x1 + field public static final int SHUFFLE_MODE_ALL = 1; // 0x1 + field public static final int SHUFFLE_MODE_GROUP = 2; // 0x2 + field public static final int SHUFFLE_MODE_NONE = 0; // 0x0 + } + + public static abstract class MediaSession2.SessionCallback { + ctor public MediaSession2.SessionCallback(android.content.Context); + method public boolean onCommandRequest(android.media.MediaSession2.ControllerInfo, android.media.MediaSession2.Command); + method public android.media.MediaSession2.CommandGroup onConnect(android.media.MediaSession2.ControllerInfo); + method public void onCustomCommand(android.media.MediaSession2.ControllerInfo, android.media.MediaSession2.Command, android.os.Bundle, android.os.ResultReceiver); + method public void onDisconnected(android.media.MediaSession2.ControllerInfo); + method public void onPlayFromMediaId(android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle); + method public void onPlayFromSearch(android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle); + method public void onPlayFromUri(android.media.MediaSession2.ControllerInfo, android.net.Uri, android.os.Bundle); + method public void onPrepareFromMediaId(android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle); + method public void onPrepareFromSearch(android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle); + method public void onPrepareFromUri(android.media.MediaSession2.ControllerInfo, android.net.Uri, android.os.Bundle); + method public void onSetRating(android.media.MediaSession2.ControllerInfo, java.lang.String, android.media.Rating2); + } + + public abstract class MediaSessionService2 extends android.app.Service { + ctor public MediaSessionService2(); + method public final android.media.MediaSession2 getSession(); + method public android.os.IBinder onBind(android.content.Intent); + method public abstract android.media.MediaSession2 onCreateSession(java.lang.String); + method public android.media.MediaSessionService2.MediaNotification onUpdateNotification(); + field public static final java.lang.String SERVICE_INTERFACE = "android.media.MediaSessionService2"; + field public static final java.lang.String SERVICE_META_DATA = "android.media.session"; + } + + public static class MediaSessionService2.MediaNotification { + ctor public MediaSessionService2.MediaNotification(android.content.Context, int, android.app.Notification); + method public android.app.Notification getNotification(); + method public int getNotificationId(); + } + public final class MediaSync { ctor public MediaSync(); method public android.view.Surface createInputSurface(); @@ -24567,13 +24985,19 @@ package android.media { field public static final int DIRECTIONALITY_OMNI = 1; // 0x1 field public static final int DIRECTIONALITY_SUPER_CARDIOID = 5; // 0x5 field public static final int DIRECTIONALITY_UNKNOWN = 0; // 0x0 + field public static final int GROUP_UNKNOWN = -1; // 0xffffffff + field public static final int INDEX_IN_THE_GROUP_UNKNOWN = -1; // 0xffffffff field public static final int LOCATION_MAINBODY = 1; // 0x1 field public static final int LOCATION_MAINBODY_MOVABLE = 2; // 0x2 field public static final int LOCATION_PERIPHERAL = 3; // 0x3 field public static final int LOCATION_UNKNOWN = 0; // 0x0 + field public static final android.media.MicrophoneInfo.Coordinate3F ORIENTATION_UNKNOWN; + field public static final android.media.MicrophoneInfo.Coordinate3F POSITION_UNKNOWN; + field public static final float SENSITIVITY_UNKNOWN = -3.4028235E38f; + field public static final float SPL_UNKNOWN = -3.4028235E38f; } - public class MicrophoneInfo.Coordinate3F { + public static final class MicrophoneInfo.Coordinate3F { field public final float x; field public final float y; field public final float z; @@ -24624,6 +25048,29 @@ package android.media { field public static final int RATING_THUMB_UP_DOWN = 2; // 0x2 } + public final class Rating2 { + method public static android.media.Rating2 fromBundle(android.content.Context, android.os.Bundle); + method public float getPercentRating(); + method public int getRatingStyle(); + method public float getStarRating(); + method public boolean hasHeart(); + method public boolean isRated(); + method public boolean isThumbUp(); + method public static android.media.Rating2 newHeartRating(android.content.Context, boolean); + method public static android.media.Rating2 newPercentageRating(android.content.Context, float); + method public static android.media.Rating2 newStarRating(android.content.Context, int, float); + method public static android.media.Rating2 newThumbRating(android.content.Context, boolean); + method public static android.media.Rating2 newUnratedRating(android.content.Context, int); + method public android.os.Bundle toBundle(); + field public static final int RATING_3_STARS = 3; // 0x3 + field public static final int RATING_4_STARS = 4; // 0x4 + field public static final int RATING_5_STARS = 5; // 0x5 + field public static final int RATING_HEART = 1; // 0x1 + field public static final int RATING_NONE = 0; // 0x0 + field public static final int RATING_PERCENTAGE = 6; // 0x6 + field public static final int RATING_THUMB_UP_DOWN = 2; // 0x2 + } + public deprecated class RemoteControlClient { ctor public RemoteControlClient(android.app.PendingIntent); ctor public RemoteControlClient(android.app.PendingIntent, android.os.Looper); @@ -24759,6 +25206,22 @@ package android.media { field public static final int URI_COLUMN_INDEX = 2; // 0x2 } + public final class SessionToken2 { + ctor public SessionToken2(android.content.Context, java.lang.String, java.lang.String); + method public static android.media.SessionToken2 fromBundle(android.content.Context, android.os.Bundle); + method public java.lang.String getId(); + method public java.lang.String getPackageName(); + method public int getType(); + method public int getUid(); + method public android.os.Bundle toBundle(); + field public static final int TYPE_LIBRARY_SERVICE = 2; // 0x2 + field public static final int TYPE_SESSION = 0; // 0x0 + field public static final int TYPE_SESSION_SERVICE = 1; // 0x1 + } + + public static abstract class SessionToken2.TokenType implements java.lang.annotation.Annotation { + } + public class SoundPool { ctor public deprecated SoundPool(int, int, int); method public final void autoPause(); @@ -24962,6 +25425,19 @@ package android.media { field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1 } + public abstract class VolumeProvider2 { + ctor public VolumeProvider2(android.content.Context, int, int, int); + method public final int getControlType(); + method public final int getCurrentVolume(); + method public final int getMaxVolume(); + method public void onAdjustVolume(int); + method public void onSetVolumeTo(int); + method public final void setCurrentVolume(int); + field public static final int VOLUME_CONTROL_ABSOLUTE = 2; // 0x2 + field public static final int VOLUME_CONTROL_FIXED = 0; // 0x0 + field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1 + } + public final class VolumeShaper implements java.lang.AutoCloseable { method public void apply(android.media.VolumeShaper.Operation); method public void close(); @@ -25708,14 +26184,23 @@ package android.media.session { public final class MediaSessionManager { method public void addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName); method public void addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName, android.os.Handler); + method public void addOnSessionTokensChangedListener(java.util.concurrent.Executor, android.media.session.MediaSessionManager.OnSessionTokensChangedListener); + method public java.util.List getActiveSessionTokens(); method public java.util.List getActiveSessions(android.content.ComponentName); + method public java.util.List getAllSessionTokens(); + method public java.util.List getSessionServiceTokens(); method public void removeOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener); + method public void removeOnSessionTokensChangedListener(android.media.session.MediaSessionManager.OnSessionTokensChangedListener); } public static abstract interface MediaSessionManager.OnActiveSessionsChangedListener { method public abstract void onActiveSessionsChanged(java.util.List); } + public static abstract interface MediaSessionManager.OnSessionTokensChangedListener { + method public abstract void onSessionTokensChanged(java.util.List); + } + public final class PlaybackState implements android.os.Parcelable { method public int describeContents(); method public long getActions(); @@ -32974,7 +33459,7 @@ package android.os { method public android.os.StrictMode.ThreadPolicy.Builder penaltyDialog(); method public android.os.StrictMode.ThreadPolicy.Builder penaltyDropBox(); method public android.os.StrictMode.ThreadPolicy.Builder penaltyFlashScreen(); - method public android.os.StrictMode.ThreadPolicy.Builder penaltyListener(android.os.StrictMode.OnThreadViolationListener, java.util.concurrent.Executor); + method public android.os.StrictMode.ThreadPolicy.Builder penaltyListener(java.util.concurrent.Executor, android.os.StrictMode.OnThreadViolationListener); method public android.os.StrictMode.ThreadPolicy.Builder penaltyLog(); method public android.os.StrictMode.ThreadPolicy.Builder permitAll(); method public android.os.StrictMode.ThreadPolicy.Builder permitCustomSlowCalls(); @@ -33006,7 +33491,7 @@ package android.os { method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnCleartextNetwork(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnFileUriExposure(); method public android.os.StrictMode.VmPolicy.Builder penaltyDropBox(); - method public android.os.StrictMode.VmPolicy.Builder penaltyListener(android.os.StrictMode.OnVmViolationListener, java.util.concurrent.Executor); + method public android.os.StrictMode.VmPolicy.Builder penaltyListener(java.util.concurrent.Executor, android.os.StrictMode.OnVmViolationListener); method public android.os.StrictMode.VmPolicy.Builder penaltyLog(); method public android.os.StrictMode.VmPolicy.Builder setClassInstanceLimit(java.lang.Class, int); } @@ -34616,10 +35101,9 @@ package android.provider { field public static final java.lang.String DURATION = "duration"; field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER"; field public static final java.lang.String FEATURES = "features"; - field public static final int FEATURES_ASSISTED_DIALING_USED = 16; // 0x10 field public static final int FEATURES_HD_CALL = 4; // 0x4 field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2 - field public static final int FEATURES_RTT = 32; // 0x20 + field public static final int FEATURES_RTT = 16; // 0x10 field public static final int FEATURES_VIDEO = 1; // 0x1 field public static final int FEATURES_WIFI = 8; // 0x8 field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location"; @@ -38240,17 +38724,6 @@ package android.se.omapi { method public byte[] transmit(byte[]) throws java.io.IOException; } - public abstract interface ISecureElementListener implements android.os.IInterface { - method public abstract void serviceConnected() throws android.os.RemoteException; - } - - public static abstract class ISecureElementListener.Stub extends android.os.Binder implements android.se.omapi.ISecureElementListener { - ctor public ISecureElementListener.Stub(); - method public android.os.IBinder asBinder(); - method public static android.se.omapi.ISecureElementListener asInterface(android.os.IBinder); - method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException; - } - public class Reader { method public void closeSessions(); method public java.lang.String getName(); @@ -38260,13 +38733,19 @@ package android.se.omapi { } public class SEService { - ctor public SEService(android.content.Context, android.se.omapi.ISecureElementListener); + ctor public SEService(android.content.Context, android.se.omapi.SEService.SecureElementListener); method public android.se.omapi.Reader[] getReaders(); method public java.lang.String getVersion(); method public boolean isConnected(); method public void shutdown(); } + public static abstract class SEService.SecureElementListener extends android.os.Binder { + ctor public SEService.SecureElementListener(); + method public android.os.IBinder asBinder(); + method public void serviceConnected(); + } + public class Session { method public void close(); method public void closeChannels(); @@ -38426,7 +38905,6 @@ package android.security.keystore { method public boolean isRandomizedEncryptionRequired(); method public boolean isStrongBoxBacked(); method public boolean isTrustedUserPresenceRequired(); - method public boolean isUnlockedDeviceRequired(); method public boolean isUserAuthenticationRequired(); method public boolean isUserAuthenticationValidWhileOnBody(); method public boolean isUserConfirmationRequired(); @@ -38454,7 +38932,6 @@ package android.security.keystore { method public android.security.keystore.KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean); method public android.security.keystore.KeyGenParameterSpec.Builder setSignaturePaddings(java.lang.String...); method public android.security.keystore.KeyGenParameterSpec.Builder setTrustedUserPresenceRequired(boolean); - method public android.security.keystore.KeyGenParameterSpec.Builder setUnlockedDeviceRequired(boolean); method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationRequired(boolean); method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidWhileOnBody(boolean); method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidityDurationSeconds(int); @@ -38546,8 +39023,6 @@ package android.security.keystore { method public boolean isDigestsSpecified(); method public boolean isInvalidatedByBiometricEnrollment(); method public boolean isRandomizedEncryptionRequired(); - method public boolean isTrustedUserPresenceRequired(); - method public boolean isUnlockedDeviceRequired(); method public boolean isUserAuthenticationRequired(); method public boolean isUserAuthenticationValidWhileOnBody(); method public boolean isUserConfirmationRequired(); @@ -38566,8 +39041,6 @@ package android.security.keystore { method public android.security.keystore.KeyProtection.Builder setKeyValidityStart(java.util.Date); method public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean); method public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...); - method public android.security.keystore.KeyProtection.Builder setTrustedUserPresenceRequired(boolean); - method public android.security.keystore.KeyProtection.Builder setUnlockedDeviceRequired(boolean); method public android.security.keystore.KeyProtection.Builder setUserAuthenticationRequired(boolean); method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidWhileOnBody(boolean); method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidityDurationSeconds(int); @@ -40620,7 +41093,6 @@ package android.telecom { field public static final int CAPABILITY_SUPPORT_DEFLECT = 16777216; // 0x1000000 field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2 field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8 - field public static final int PROPERTY_ASSISTED_DIALING_USED = 512; // 0x200 field public static final int PROPERTY_CONFERENCE = 1; // 0x1 field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4 field public static final int PROPERTY_ENTERPRISE_CALL = 32; // 0x20 @@ -40845,7 +41317,6 @@ package android.telecom { field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT"; field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS"; field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER"; - field public static final int PROPERTY_ASSISTED_DIALING_USED = 512; // 0x200 field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 32; // 0x20 field public static final int PROPERTY_IS_EXTERNAL_CALL = 16; // 0x10 field public static final int PROPERTY_IS_RTT = 256; // 0x100 @@ -41262,14 +41733,12 @@ package android.telecom { field public static final deprecated java.lang.String ACTION_INCOMING_CALL = "android.telecom.action.INCOMING_CALL"; field public static final java.lang.String ACTION_PHONE_ACCOUNT_REGISTERED = "android.telecom.action.PHONE_ACCOUNT_REGISTERED"; field public static final java.lang.String ACTION_PHONE_ACCOUNT_UNREGISTERED = "android.telecom.action.PHONE_ACCOUNT_UNREGISTERED"; - field public static final java.lang.String ACTION_SHOW_ASSISTED_DIALING_SETTINGS = "android.telecom.action.SHOW_ASSISTED_DIALING_SETTINGS"; field public static final java.lang.String ACTION_SHOW_CALL_ACCESSIBILITY_SETTINGS = "android.telecom.action.SHOW_CALL_ACCESSIBILITY_SETTINGS"; field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS"; field public static final java.lang.String ACTION_SHOW_MISSED_CALLS_NOTIFICATION = "android.telecom.action.SHOW_MISSED_CALLS_NOTIFICATION"; field public static final java.lang.String ACTION_SHOW_RESPOND_VIA_SMS_SETTINGS = "android.telecom.action.SHOW_RESPOND_VIA_SMS_SETTINGS"; field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ',' field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';' - field public static final java.lang.String EXTRA_ASSISTED_DIALING_TRANSFORMATION_INFO = "android.telecom.extra.ASSISTED_DIALING_TRANSFORMATION_INFO"; field public static final java.lang.String EXTRA_CALL_BACK_NUMBER = "android.telecom.extra.CALL_BACK_NUMBER"; field public static final java.lang.String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecom.extra.CALL_DISCONNECT_CAUSE"; field public static final java.lang.String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecom.extra.CALL_DISCONNECT_MESSAGE"; @@ -41285,7 +41754,6 @@ package android.telecom { field public static final java.lang.String EXTRA_START_CALL_WITH_RTT = "android.telecom.extra.START_CALL_WITH_RTT"; field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecom.extra.START_CALL_WITH_SPEAKERPHONE"; field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE"; - field public static final java.lang.String EXTRA_USE_ASSISTED_DIALING = "android.telecom.extra.USE_ASSISTED_DIALING"; field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS"; field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE"; field public static final java.lang.String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS"; @@ -41298,18 +41766,6 @@ package android.telecom { field public static final int PRESENTATION_UNKNOWN = 3; // 0x3 } - public final class TransformationInfo implements android.os.Parcelable { - ctor public TransformationInfo(java.lang.String, java.lang.String, java.lang.String, java.lang.String, int); - method public int describeContents(); - method public java.lang.String getOriginalNumber(); - method public java.lang.String getTransformedNumber(); - method public int getTransformedNumberCountryCallingCode(); - method public java.lang.String getUserHomeCountryCode(); - method public java.lang.String getUserRoamingCountryCode(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator CREATOR; - } - public class VideoProfile implements android.os.Parcelable { ctor public VideoProfile(int); ctor public VideoProfile(int, int); @@ -41476,7 +41932,6 @@ package android.telephony { field public static final java.lang.String KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL = "allow_non_emergency_calls_in_ecm_bool"; field public static final java.lang.String KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL = "always_show_emergency_alert_onoff_bool"; field public static final java.lang.String KEY_APN_EXPAND_BOOL = "apn_expand_bool"; - field public static final java.lang.String KEY_ASSISTED_DIALING_ENABLED_BOOL = "assisted_dialing_enabled_bool"; field public static final java.lang.String KEY_AUTO_RETRY_ENABLED_BOOL = "auto_retry_enabled_bool"; field public static final java.lang.String KEY_CALL_FORWARDING_BLOCKS_WHILE_ROAMING_STRING_ARRAY = "call_forwarding_blocks_while_roaming_string_array"; field public static final java.lang.String KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL = "carrier_allow_turnoff_ims_bool"; @@ -41815,12 +42270,12 @@ package android.telephony { public class MbmsDownloadSession implements java.lang.AutoCloseable { method public int cancelDownload(android.telephony.mbms.DownloadRequest); method public void close(); - method public static android.telephony.MbmsDownloadSession create(android.content.Context, android.telephony.mbms.MbmsDownloadSessionCallback, android.os.Handler); - method public static android.telephony.MbmsDownloadSession create(android.content.Context, android.telephony.mbms.MbmsDownloadSessionCallback, int, android.os.Handler); + method public static android.telephony.MbmsDownloadSession create(android.content.Context, java.util.concurrent.Executor, android.telephony.mbms.MbmsDownloadSessionCallback); + method public static android.telephony.MbmsDownloadSession create(android.content.Context, java.util.concurrent.Executor, int, android.telephony.mbms.MbmsDownloadSessionCallback); method public int download(android.telephony.mbms.DownloadRequest); method public java.io.File getTempFileRootDirectory(); method public java.util.List listPendingDownloads(); - method public int registerStateCallback(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStateCallback, android.os.Handler); + method public int registerStateCallback(android.telephony.mbms.DownloadRequest, java.util.concurrent.Executor, android.telephony.mbms.DownloadStateCallback); method public void requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo); method public void requestUpdateFileServices(java.util.List); method public void resetDownloadKnowledge(android.telephony.mbms.DownloadRequest); @@ -41848,10 +42303,10 @@ package android.telephony { public class MbmsStreamingSession implements java.lang.AutoCloseable { method public void close(); - method public static android.telephony.MbmsStreamingSession create(android.content.Context, android.telephony.mbms.MbmsStreamingSessionCallback, int, android.os.Handler); - method public static android.telephony.MbmsStreamingSession create(android.content.Context, android.telephony.mbms.MbmsStreamingSessionCallback, android.os.Handler); + method public static android.telephony.MbmsStreamingSession create(android.content.Context, java.util.concurrent.Executor, int, android.telephony.mbms.MbmsStreamingSessionCallback); + method public static android.telephony.MbmsStreamingSession create(android.content.Context, java.util.concurrent.Executor, android.telephony.mbms.MbmsStreamingSessionCallback); method public void requestUpdateStreamingServices(java.util.List); - method public android.telephony.mbms.StreamingService startStreaming(android.telephony.mbms.StreamingServiceInfo, android.telephony.mbms.StreamingServiceCallback, android.os.Handler); + method public android.telephony.mbms.StreamingService startStreaming(android.telephony.mbms.StreamingServiceInfo, java.util.concurrent.Executor, android.telephony.mbms.StreamingServiceCallback); } public class NeighboringCellInfo implements android.os.Parcelable { @@ -42724,20 +43179,23 @@ package android.telephony.gsm { package android.telephony.mbms { public final class DownloadRequest implements android.os.Parcelable { - method public static android.telephony.mbms.DownloadRequest copy(android.telephony.mbms.DownloadRequest); method public int describeContents(); + method public android.net.Uri getDestinationUri(); method public java.lang.String getFileServiceId(); method public static int getMaxAppIntentSize(); method public static int getMaxDestinationUriSize(); method public android.net.Uri getSourceUri(); method public int getSubscriptionId(); + method public byte[] toByteArray(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; } public static class DownloadRequest.Builder { - ctor public DownloadRequest.Builder(android.net.Uri); + ctor public DownloadRequest.Builder(android.net.Uri, android.net.Uri); method public android.telephony.mbms.DownloadRequest build(); + method public static android.telephony.mbms.DownloadRequest.Builder fromDownloadRequest(android.telephony.mbms.DownloadRequest); + method public static android.telephony.mbms.DownloadRequest.Builder fromSerializedRequest(byte[]); method public android.telephony.mbms.DownloadRequest.Builder setAppIntent(android.content.Intent); method public android.telephony.mbms.DownloadRequest.Builder setServiceInfo(android.telephony.mbms.FileServiceInfo); method public android.telephony.mbms.DownloadRequest.Builder setSubscriptionId(int); @@ -42833,10 +43291,10 @@ package android.telephony.mbms { method public java.util.Date getSessionStartTime(); } - public class StreamingService { + public class StreamingService implements java.lang.AutoCloseable { + method public void close(); method public android.telephony.mbms.StreamingServiceInfo getInfo(); method public android.net.Uri getPlaybackUri(); - method public void stopStreaming(); field public static final int BROADCAST_METHOD = 1; // 0x1 field public static final int REASON_BY_USER_REQUEST = 1; // 0x1 field public static final int REASON_END_OF_SESSION = 2; // 0x2 @@ -43216,45 +43674,47 @@ package android.text { method public boolean isAllowed(char); } - public class MeasuredText implements android.text.Spanned { + public abstract interface NoCopySpan { + } + + public static class NoCopySpan.Concrete implements android.text.NoCopySpan { + ctor public NoCopySpan.Concrete(); + } + + public abstract interface ParcelableSpan implements android.os.Parcelable { + method public abstract int getSpanTypeId(); + } + + public class PrecomputedText implements android.text.Spanned { method public char charAt(int); - method public int getBreakStrategy(); - method public int getEnd(); - method public int getHyphenationFrequency(); - method public android.text.TextPaint getPaint(); + method public static android.text.PrecomputedText create(java.lang.CharSequence, android.text.PrecomputedText.Params); method public int getParagraphCount(); method public int getParagraphEnd(int); method public int getParagraphStart(int); + method public android.text.PrecomputedText.Params getParams(); method public int getSpanEnd(java.lang.Object); method public int getSpanFlags(java.lang.Object); method public int getSpanStart(java.lang.Object); method public T[] getSpans(int, int, java.lang.Class); - method public int getStart(); method public java.lang.CharSequence getText(); - method public android.text.TextDirectionHeuristic getTextDir(); method public int length(); method public int nextSpanTransition(int, int, java.lang.Class); method public java.lang.CharSequence subSequence(int, int); } - public static final class MeasuredText.Builder { - ctor public MeasuredText.Builder(java.lang.CharSequence, android.text.TextPaint); - method public android.text.MeasuredText build(); - method public android.text.MeasuredText.Builder setBreakStrategy(int); - method public android.text.MeasuredText.Builder setHyphenationFrequency(int); - method public android.text.MeasuredText.Builder setRange(int, int); - method public android.text.MeasuredText.Builder setTextDirection(android.text.TextDirectionHeuristic); - } - - public abstract interface NoCopySpan { - } - - public static class NoCopySpan.Concrete implements android.text.NoCopySpan { - ctor public NoCopySpan.Concrete(); + public static final class PrecomputedText.Params { + method public int getBreakStrategy(); + method public int getHyphenationFrequency(); + method public android.text.TextDirectionHeuristic getTextDirection(); + method public android.text.TextPaint getTextPaint(); } - public abstract interface ParcelableSpan implements android.os.Parcelable { - method public abstract int getSpanTypeId(); + public static class PrecomputedText.Params.Builder { + ctor public PrecomputedText.Params.Builder(android.text.TextPaint); + method public android.text.PrecomputedText.Params build(); + method public android.text.PrecomputedText.Params.Builder setBreakStrategy(int); + method public android.text.PrecomputedText.Params.Builder setHyphenationFrequency(int); + method public android.text.PrecomputedText.Params.Builder setTextDirection(android.text.TextDirectionHeuristic); } public class Selection { @@ -47610,6 +48070,7 @@ package android.view { method public void setAlpha(float); method public void setAnimation(android.view.animation.Animation); method public void setAutofillHints(java.lang.String...); + method public void setAutofillId(android.view.autofill.AutofillId); method public void setBackground(android.graphics.drawable.Drawable); method public void setBackgroundColor(int); method public deprecated void setBackgroundDrawable(android.graphics.drawable.Drawable); @@ -49773,6 +50234,7 @@ package android.view.autofill { method public android.content.ComponentName getAutofillServiceComponentName(); method public java.util.List getAvailableFieldClassificationAlgorithms(); method public java.lang.String getDefaultFieldClassificationAlgorithm(); + method public android.view.autofill.AutofillId getNextAutofillId(); method public android.service.autofill.UserData getUserData(); method public java.lang.String getUserDataId(); method public boolean hasEnabledAutofillServices(); @@ -50288,15 +50750,13 @@ package android.view.textclassifier { 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 java.util.Collection getEntitiesForPreset(int); method public default android.view.textclassifier.logging.Logger getLogger(android.view.textclassifier.logging.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); method public default android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.os.LocaleList); - field public static final int ENTITY_PRESET_ALL = 0; // 0x0 - field public static final int ENTITY_PRESET_BASE = 2; // 0x2 - field public static final int ENTITY_PRESET_NONE = 1; // 0x1 + field public static final java.lang.String HINT_TEXT_IS_EDITABLE = "android.text_is_editable"; + field public static final java.lang.String HINT_TEXT_IS_NOT_EDITABLE = "android.text_is_not_editable"; field public static final android.view.textclassifier.TextClassifier NO_OP; field public static final java.lang.String TYPE_ADDRESS = "address"; field public static final java.lang.String TYPE_DATE = "date"; @@ -50310,11 +50770,12 @@ package android.view.textclassifier { } public static final class TextClassifier.EntityConfig implements android.os.Parcelable { - ctor public TextClassifier.EntityConfig(int); + method public static android.view.textclassifier.TextClassifier.EntityConfig create(java.util.Collection); + method public static android.view.textclassifier.TextClassifier.EntityConfig create(java.util.Collection, java.util.Collection, java.util.Collection); + method public static android.view.textclassifier.TextClassifier.EntityConfig createWithEntityList(java.util.Collection); method public int describeContents(); - method public android.view.textclassifier.TextClassifier.EntityConfig excludeEntities(java.lang.String...); - method public java.util.List getEntities(android.view.textclassifier.TextClassifier); - method public android.view.textclassifier.TextClassifier.EntityConfig includeEntities(java.lang.String...); + method public java.util.Collection getHints(); + method public java.util.List resolveEntityListModifications(java.util.Collection); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; } @@ -53640,6 +54101,7 @@ package android.widget { method public final android.content.res.ColorStateList getTextColors(); method public java.util.Locale getTextLocale(); method public android.os.LocaleList getTextLocales(); + method public android.text.PrecomputedText.Params getTextMetricsParams(); method public float getTextScaleX(); method public float getTextSize(); method public int getTotalPaddingBottom(); @@ -53769,6 +54231,7 @@ package android.widget { method public final void setTextKeepState(java.lang.CharSequence, android.widget.TextView.BufferType); method public void setTextLocale(java.util.Locale); method public void setTextLocales(android.os.LocaleList); + method public void setTextMetricsParams(android.text.PrecomputedText.Params); method public void setTextScaleX(float); method public void setTextSize(float); method public void setTextSize(int, float); diff --git a/api/removed.txt b/api/removed.txt index 55022f36a016056fa22546845c79eda6abf54acf..79c54fde547745940c9ebcf6c766220febf04dc7 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -257,6 +257,14 @@ package android.os { ctor public RecoverySystem(); } + public static final class StrictMode.ThreadPolicy.Builder { + method public android.os.StrictMode.ThreadPolicy.Builder penaltyListener(android.os.StrictMode.OnThreadViolationListener, java.util.concurrent.Executor); + } + + public static final class StrictMode.VmPolicy.Builder { + method public android.os.StrictMode.VmPolicy.Builder penaltyListener(android.os.StrictMode.OnVmViolationListener, java.util.concurrent.Executor); + } + public final class SystemClock { method public static java.time.Clock elapsedRealtimeClock(); method public static java.time.Clock uptimeClock(); diff --git a/api/system-current.txt b/api/system-current.txt index 930224dc2ce22f64eb35eddb30ab87f49ad9b625..3aca59a5724d7f245d7c04f2a25c5d8668f49c11 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -10,6 +10,7 @@ package android { field public static final java.lang.String ACCESS_MTP = "android.permission.ACCESS_MTP"; field public static final java.lang.String ACCESS_NETWORK_CONDITIONS = "android.permission.ACCESS_NETWORK_CONDITIONS"; field public static final java.lang.String ACCESS_NOTIFICATIONS = "android.permission.ACCESS_NOTIFICATIONS"; + field public static final java.lang.String ACCESS_SHORTCUTS = "android.permission.ACCESS_SHORTCUTS"; field public static final java.lang.String ACCESS_SURFACE_FLINGER = "android.permission.ACCESS_SURFACE_FLINGER"; field public static final java.lang.String ACCOUNT_MANAGER = "android.permission.ACCOUNT_MANAGER"; field public static final java.lang.String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING"; @@ -124,6 +125,7 @@ package android { field public static final java.lang.String PERFORM_SIM_ACTIVATION = "android.permission.PERFORM_SIM_ACTIVATION"; field public static final java.lang.String PROVIDE_RESOLVER_RANKER_SERVICE = "android.permission.PROVIDE_RESOLVER_RANKER_SERVICE"; field public static final java.lang.String PROVIDE_TRUST_AGENT = "android.permission.PROVIDE_TRUST_AGENT"; + field public static final java.lang.String QUERY_TIME_ZONE_RULES = "android.permission.QUERY_TIME_ZONE_RULES"; field public static final java.lang.String READ_CONTENT_RATING_SYSTEMS = "android.permission.READ_CONTENT_RATING_SYSTEMS"; field public static final java.lang.String READ_DREAM_STATE = "android.permission.READ_DREAM_STATE"; field public static final java.lang.String READ_FRAME_BUFFER = "android.permission.READ_FRAME_BUFFER"; @@ -179,6 +181,7 @@ package android { field public static final java.lang.String TETHER_PRIVILEGED = "android.permission.TETHER_PRIVILEGED"; field public static final java.lang.String TV_INPUT_HARDWARE = "android.permission.TV_INPUT_HARDWARE"; field public static final java.lang.String TV_VIRTUAL_REMOTE_CONTROLLER = "android.permission.TV_VIRTUAL_REMOTE_CONTROLLER"; + field public static final java.lang.String UNLIMITED_SHORTCUTS_API_CALLS = "android.permission.UNLIMITED_SHORTCUTS_API_CALLS"; field public static final java.lang.String UPDATE_APP_OPS_STATS = "android.permission.UPDATE_APP_OPS_STATS"; field public static final java.lang.String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS"; field public static final java.lang.String UPDATE_LOCK = "android.permission.UPDATE_LOCK"; @@ -201,6 +204,7 @@ package android { field public static final int isVrOnly = 16844152; // 0x1010578 field public static final int requiredSystemPropertyName = 16844133; // 0x1010565 field public static final int requiredSystemPropertyValue = 16844134; // 0x1010566 + field public static final int userRestriction = 16844165; // 0x1010585 } public static final class R.raw { @@ -467,7 +471,11 @@ package android.app.backup { method public android.app.backup.RestoreSession beginRestoreSession(); method public void cancelBackups(); method public long getAvailableRestoreToken(java.lang.String); + method public android.content.Intent getConfigurationIntent(java.lang.String); method public java.lang.String getCurrentTransport(); + method public android.content.Intent getDataManagementIntent(java.lang.String); + method public java.lang.String getDataManagementLabel(java.lang.String); + method public java.lang.String getDestinationString(java.lang.String); method public boolean isAppEligibleForBackup(java.lang.String); method public boolean isBackupEnabled(); method public boolean isBackupServiceActive(android.os.UserHandle); @@ -1085,6 +1093,7 @@ package android.content.pm { public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable { field public static final int FLAG_REMOVED = 2; // 0x2 field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000 + field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000 field public int requestRes; } @@ -4168,6 +4177,8 @@ package android.provider { method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String, java.lang.String, boolean); method public static void resetToDefaults(android.content.ContentResolver, java.lang.String); field public static final java.lang.String AUTOFILL_COMPAT_ALLOWED_PACKAGES = "autofill_compat_allowed_packages"; + field public static final java.lang.String CARRIER_APP_NAMES = "carrier_app_names"; + field public static final java.lang.String CARRIER_APP_WHITELIST = "carrier_app_whitelist"; field public static final java.lang.String DEFAULT_SM_DP_PLUS = "default_sm_dp_plus"; field public static final java.lang.String INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT = "install_carrier_app_notification_persistent"; field public static final java.lang.String INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS = "install_carrier_app_notification_sleep_millis"; @@ -4263,7 +4274,7 @@ package android.security.keystore.recovery { method public int getMaxAttempts(); method public byte[] getServerParams(); method public int getSnapshotVersion(); - method public byte[] getTrustedHardwarePublicKey(); + method public java.security.cert.CertPath getTrustedHardwareCertPath(); method public java.util.List getWrappedApplicationKeys(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; @@ -4284,21 +4295,21 @@ package android.security.keystore.recovery { } public class RecoveryController { + method public android.security.keystore.recovery.RecoverySession createRecoverySession(); method public byte[] generateAndStoreKey(java.lang.String, byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; - method public java.util.List getAliases(java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException; + method public java.security.Key generateKey(java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; + method public java.util.List getAliases() throws android.security.keystore.recovery.InternalRecoveryServiceException; method public static android.security.keystore.recovery.RecoveryController getInstance(android.content.Context); method public int[] getPendingRecoverySecretTypes() throws android.security.keystore.recovery.InternalRecoveryServiceException; - method public android.security.keystore.recovery.KeyChainSnapshot getRecoveryData() throws android.security.keystore.recovery.InternalRecoveryServiceException; method public int[] getRecoverySecretTypes() throws android.security.keystore.recovery.InternalRecoveryServiceException; - method public int getRecoveryStatus(java.lang.String, java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException; + method public int getRecoveryStatus(java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException; method public void initRecoveryService(java.lang.String, byte[]) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException; method public void recoverySecretAvailable(android.security.keystore.recovery.KeyChainProtectionParams) throws android.security.keystore.recovery.InternalRecoveryServiceException; method public void removeKey(java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException; method public void setRecoverySecretTypes(int[]) throws android.security.keystore.recovery.InternalRecoveryServiceException; - method public void setRecoveryStatus(java.lang.String, java.lang.String, int) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.content.pm.PackageManager.NameNotFoundException; + method public void setRecoveryStatus(java.lang.String, int) throws android.security.keystore.recovery.InternalRecoveryServiceException; method public void setServerParams(byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException; method public void setSnapshotCreatedPendingIntent(android.app.PendingIntent) throws android.security.keystore.recovery.InternalRecoveryServiceException; - field public static final int RECOVERY_STATUS_MISSING_ACCOUNT = 2; // 0x2 field public static final int RECOVERY_STATUS_PERMANENT_FAILURE = 3; // 0x3 field public static final int RECOVERY_STATUS_SYNCED = 0; // 0x0 field public static final int RECOVERY_STATUS_SYNC_IN_PROGRESS = 1; // 0x1 @@ -4307,7 +4318,7 @@ package android.security.keystore.recovery { public class RecoverySession implements java.lang.AutoCloseable { method public void close(); method public java.util.Map recoverKeys(byte[], java.util.List) throws android.security.keystore.recovery.DecryptionFailedException, android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.SessionExpiredException; - method public byte[] start(byte[], byte[], byte[], java.util.List) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException; + method public byte[] start(java.security.cert.CertPath, byte[], byte[], java.util.List) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException; } public class SessionExpiredException extends java.security.GeneralSecurityException { @@ -4316,7 +4327,6 @@ package android.security.keystore.recovery { public final class WrappedApplicationKey implements android.os.Parcelable { method public int describeContents(); - method public byte[] getAccount(); method public java.lang.String getAlias(); method public byte[] getEncryptedKeyMaterial(); method public void writeToParcel(android.os.Parcel, int); @@ -4326,7 +4336,6 @@ package android.security.keystore.recovery { public static class WrappedApplicationKey.Builder { ctor public WrappedApplicationKey.Builder(); method public android.security.keystore.recovery.WrappedApplicationKey build(); - method public android.security.keystore.recovery.WrappedApplicationKey.Builder setAccount(byte[]); method public android.security.keystore.recovery.WrappedApplicationKey.Builder setAlias(java.lang.String); method public android.security.keystore.recovery.WrappedApplicationKey.Builder setEncryptedKeyMaterial(byte[]); } @@ -5212,6 +5221,7 @@ package android.telephony { method public int describeContents(); method public int getCarrierPrivilegeStatus(android.content.pm.PackageInfo); method public int getCarrierPrivilegeStatus(android.content.pm.Signature, java.lang.String); + method public java.lang.String getCertificateHexString(); method public java.lang.String getPackageName(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; @@ -6120,7 +6130,9 @@ package android.telephony.ims.stub { method public final void onSmsReceived(int, java.lang.String, byte[]) throws java.lang.RuntimeException; method public final void onSmsStatusReportReceived(int, int, java.lang.String, byte[]) throws java.lang.RuntimeException; method public void sendSms(int, int, java.lang.String, java.lang.String, boolean, byte[]); - field public static final int DELIVER_STATUS_ERROR = 2; // 0x2 + field public static final int DELIVER_STATUS_ERROR_GENERIC = 2; // 0x2 + field public static final int DELIVER_STATUS_ERROR_NO_MEMORY = 3; // 0x3 + field public static final int DELIVER_STATUS_ERROR_REQUEST_NOT_SUPPORTED = 4; // 0x4 field public static final int DELIVER_STATUS_OK = 1; // 0x1 field public static final int SEND_STATUS_ERROR = 2; // 0x2 field public static final int SEND_STATUS_ERROR_FALLBACK = 4; // 0x4 @@ -6157,12 +6169,7 @@ package android.telephony.ims.stub { package android.telephony.mbms { - public final class DownloadRequest implements android.os.Parcelable { - method public byte[] getOpaqueData(); - } - public static class DownloadRequest.Builder { - method public android.telephony.mbms.DownloadRequest.Builder setOpaqueData(byte[]); method public android.telephony.mbms.DownloadRequest.Builder setServiceId(java.lang.String); } diff --git a/api/system-removed.txt b/api/system-removed.txt index 48f43e0880daea0e55f600bbdf16726967b50e5d..58652a297bd8c72f0d27b1d36ca16264ca0ef368 100644 --- a/api/system-removed.txt +++ b/api/system-removed.txt @@ -91,6 +91,34 @@ package android.os { } +package android.security.keystore.recovery { + + public final class KeyChainSnapshot implements android.os.Parcelable { + method public deprecated byte[] getTrustedHardwarePublicKey(); + } + + public class RecoveryController { + method public deprecated java.security.Key generateKey(java.lang.String, byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; + method public deprecated java.util.List getAliases(java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException; + method public deprecated android.security.keystore.recovery.KeyChainSnapshot getRecoveryData() throws android.security.keystore.recovery.InternalRecoveryServiceException; + method public deprecated int getRecoveryStatus(java.lang.String, java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException; + method public deprecated void setRecoveryStatus(java.lang.String, java.lang.String, int) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.content.pm.PackageManager.NameNotFoundException; + } + + public class RecoverySession implements java.lang.AutoCloseable { + method public deprecated byte[] start(byte[], byte[], byte[], java.util.List) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException; + } + + public final class WrappedApplicationKey implements android.os.Parcelable { + method public deprecated byte[] getAccount(); + } + + public static class WrappedApplicationKey.Builder { + method public deprecated android.security.keystore.recovery.WrappedApplicationKey.Builder setAccount(byte[]); + } + +} + package android.service.notification { public abstract class NotificationListenerService extends android.app.Service { diff --git a/api/test-current.txt b/api/test-current.txt index 92251f74a2944a6afedc37bbe836847c491b195b..d5b43115c1259f85e7589ecac90cc34082e3a7f2 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -167,6 +167,17 @@ package android.app.admin { } +package android.app.backup { + + public class BackupManager { + method public android.content.Intent getConfigurationIntent(java.lang.String); + method public android.content.Intent getDataManagementIntent(java.lang.String); + method public java.lang.String getDataManagementLabel(java.lang.String); + method public java.lang.String getDestinationString(java.lang.String); + } + +} + package android.app.usage { public class StorageStatsManager { @@ -216,6 +227,7 @@ package android.content.pm { } public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable { + field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000 field public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 32768; // 0x8000 } @@ -720,6 +732,10 @@ package android.telephony { field public static final java.lang.String MBMS_STREAMING_SERVICE_OVERRIDE_METADATA = "mbms-streaming-service-override"; } + public class ServiceState implements android.os.Parcelable { + method public void setSystemAndNetworkId(int, int); + } + } package android.telephony.mbms { @@ -1096,6 +1112,11 @@ package android.widget { method public android.graphics.Bitmap getContent(); method public static android.graphics.PointF getMagnifierDefaultSize(); method public android.graphics.Rect getWindowPositionOnScreen(); + method public void setOnOperationCompleteCallback(android.widget.Magnifier.Callback); + } + + public static abstract interface Magnifier.Callback { + method public abstract void onOperationComplete(); } public class NumberPicker extends android.widget.LinearLayout { diff --git a/cmds/incident_helper/src/parsers/PageTypeInfoParser.cpp b/cmds/incident_helper/src/parsers/PageTypeInfoParser.cpp index 45a0e7b459d255d9dbbe11bfa9d754a8ec90c764..ab4382ac13f40adf4b284d40f3ff341366ca8794 100644 --- a/cmds/incident_helper/src/parsers/PageTypeInfoParser.cpp +++ b/cmds/incident_helper/src/parsers/PageTypeInfoParser.cpp @@ -104,7 +104,8 @@ PageTypeInfoParser::Parse(const int in, const int out) const for (size_t i=0; i ReportRequestQueue::getNextRequest() { } // ================================================================================ -ReportHandler::ReportHandler(const sp& handlerLooper, const sp& queue) - : mBacklogDelay(DEFAULT_BACKLOG_DELAY_NS), mHandlerLooper(handlerLooper), mQueue(queue) {} +ReportHandler::ReportHandler(const sp& handlerLooper, const sp& queue, + const sp& throttler) + : mBacklogDelay(DEFAULT_BACKLOG_DELAY_NS), + mHandlerLooper(handlerLooper), + mQueue(queue), + mThrottler(throttler) {} ReportHandler::~ReportHandler() {} @@ -159,10 +166,17 @@ void ReportHandler::run_report() { reporter->batch.add(request); } + if (mThrottler->shouldThrottle()) { + ALOGW("RunReport got throttled."); + return; + } + // Take the report, which might take a while. More requests might queue // up while we're doing this, and we'll handle them in their next batch. // TODO: We should further rate-limit the reports to no more than N per time-period. - Reporter::run_report_status_t reportStatus = reporter->runReport(); + size_t reportByteSize = 0; + Reporter::run_report_status_t reportStatus = reporter->runReport(&reportByteSize); + mThrottler->addReportSize(reportByteSize); if (reportStatus == Reporter::REPORT_NEEDS_DROPBOX) { unique_lock lock(mLock); schedule_send_backlog_to_dropbox_locked(); @@ -184,8 +198,9 @@ void ReportHandler::send_backlog_to_dropbox() { // ================================================================================ IncidentService::IncidentService(const sp& handlerLooper) - : mQueue(new ReportRequestQueue()) { - mHandler = new ReportHandler(handlerLooper, mQueue); + : mQueue(new ReportRequestQueue()), + mThrottler(new Throttler(DEFAULT_BYTES_SIZE_LIMIT, DEFAULT_REFACTORY_PERIOD_MS)) { + mHandler = new ReportHandler(handlerLooper, mQueue, mThrottler); } IncidentService::~IncidentService() {} @@ -294,6 +309,10 @@ status_t IncidentService::command(FILE* in, FILE* out, FILE* err, Vectordump(out); + return NO_ERROR; + } } return cmd_help(out); } @@ -302,6 +321,9 @@ status_t IncidentService::cmd_help(FILE* out) { fprintf(out, "usage: adb shell cmd incident privacy print \n"); fprintf(out, "usage: adb shell cmd incident privacy parse < proto.txt\n"); fprintf(out, " Prints/parses for the section id.\n"); + fprintf(out, "\n"); + fprintf(out, "usage: adb shell cmd incident throttler\n"); + fprintf(out, " Prints the current throttler state\n"); return NO_ERROR; } diff --git a/cmds/incidentd/src/IncidentService.h b/cmds/incidentd/src/IncidentService.h index 3c665076bebc36f524de3472630fdbaa797b5685..0ab34ede96421f21360da613b1824f0dcd6773d9 100644 --- a/cmds/incidentd/src/IncidentService.h +++ b/cmds/incidentd/src/IncidentService.h @@ -26,6 +26,8 @@ #include #include +#include "Throttler.h" + using namespace android; using namespace android::base; using namespace android::binder; @@ -49,7 +51,8 @@ private: // ================================================================================ class ReportHandler : public MessageHandler { public: - ReportHandler(const sp& handlerLooper, const sp& queue); + ReportHandler(const sp& handlerLooper, const sp& queue, + const sp& throttler); virtual ~ReportHandler(); virtual void handleMessage(const Message& message); @@ -70,6 +73,7 @@ private: nsecs_t mBacklogDelay; sp mHandlerLooper; sp mQueue; + sp mThrottler; /** * Runs all of the reports that have been queued. @@ -109,6 +113,7 @@ public: private: sp mQueue; sp mHandler; + sp mThrottler; /** * Commands print out help. diff --git a/cmds/incidentd/src/Log.h b/cmds/incidentd/src/Log.h index 46efbd1fb7d035681492b16cbee2e4f6057267c6..22de46dfd9a2fb838139b8c7c4969ae313cf534e 100644 --- a/cmds/incidentd/src/Log.h +++ b/cmds/incidentd/src/Log.h @@ -23,7 +23,6 @@ #pragma once #define LOG_TAG "incidentd" -#define DEBUG false #include diff --git a/cmds/incidentd/src/PrivacyBuffer.cpp b/cmds/incidentd/src/PrivacyBuffer.cpp index e4128f4217d187ddc686cd72800916a53ba160a0..ee57f4d0e5d6f154c14802d42b3812ce086ef9a3 100644 --- a/cmds/incidentd/src/PrivacyBuffer.cpp +++ b/cmds/incidentd/src/PrivacyBuffer.cpp @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#define DEBUG false #include "Log.h" #include "PrivacyBuffer.h" diff --git a/cmds/incidentd/src/Reporter.cpp b/cmds/incidentd/src/Reporter.cpp index c0b53586a8ceb8440f4eed2b62ae4ccf36079362..12764f8ff09c9a09f44745be6d5031bd724c8503 100644 --- a/cmds/incidentd/src/Reporter.cpp +++ b/cmds/incidentd/src/Reporter.cpp @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#define DEBUG false #include "Log.h" #include "Reporter.h" @@ -118,7 +119,7 @@ Reporter::Reporter(const char* directory) : batch() { Reporter::~Reporter() {} -Reporter::run_report_status_t Reporter::runReport() { +Reporter::run_report_status_t Reporter::runReport(size_t* reportByteSize) { status_t err = NO_ERROR; bool needMainFd = false; int mainFd = -1; @@ -185,7 +186,6 @@ Reporter::run_report_status_t Reporter::runReport() { int64_t startTime = uptimeMillis(); err = (*section)->Execute(&batch); int64_t endTime = uptimeMillis(); - stats->set_success(err == NO_ERROR); stats->set_exec_duration_ms(endTime - startTime); if (err != NO_ERROR) { @@ -193,6 +193,7 @@ Reporter::run_report_status_t Reporter::runReport() { (*section)->name.string(), id, strerror(-err)); goto DONE; } + (*reportByteSize) += stats->report_size_bytes(); // Notify listener of starting for (ReportRequestSet::iterator it = batch.begin(); it != batch.end(); it++) { diff --git a/cmds/incidentd/src/Reporter.h b/cmds/incidentd/src/Reporter.h index 0f3f2217245249a704b8b2a089c0567c3651a118..ba8965ef4a6cc397a507393b6d12d88367edcb7f 100644 --- a/cmds/incidentd/src/Reporter.h +++ b/cmds/incidentd/src/Reporter.h @@ -18,8 +18,6 @@ #ifndef REPORTER_H #define REPORTER_H -#include "frameworks/base/libs/incident/proto/android/os/metadata.pb.h" - #include #include @@ -29,6 +27,9 @@ #include +#include "Throttler.h" +#include "frameworks/base/libs/incident/proto/android/os/metadata.pb.h" + using namespace android; using namespace android::os; using namespace std; @@ -91,7 +92,7 @@ public: virtual ~Reporter(); // Run the report as described in the batch and args parameters. - run_report_status_t runReport(); + run_report_status_t runReport(size_t* reportByteSize); static run_report_status_t upload_backlog(); diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp index 2e4e980278f9aedeb6fc7f4401aee82d1c45037f..64eae3acd34c1ae69827377c127c2ae45b7f890e 100644 --- a/cmds/incidentd/src/Section.cpp +++ b/cmds/incidentd/src/Section.cpp @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#define DEBUG false #include "Log.h" #include "Section.h" @@ -244,7 +245,8 @@ status_t MetadataSection::Execute(ReportRequestSet* requests) const { } 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 (!WriteFully(requests->mainFd(), (uint8_t const*)metadataBuf.data(), + metadataBuf.size())) { ALOGW("Failed to write metadata to dropbox fd %d", requests->mainFd()); return -1; } diff --git a/cmds/incidentd/src/Throttler.cpp b/cmds/incidentd/src/Throttler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1abf26785733a39788555b5f1a31ffdefd57b2f6 --- /dev/null +++ b/cmds/incidentd/src/Throttler.cpp @@ -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. + */ +#define DEBUG false +#include "Log.h" + +#include "Throttler.h" + +#include + +Throttler::Throttler(size_t limit, int64_t refractoryPeriodMs) + : mSizeLimit(limit), + mRefractoryPeriodMs(refractoryPeriodMs), + mAccumulatedSize(0), + mLastRefractoryMs(android::elapsedRealtime()) {} + +Throttler::~Throttler() {} + +bool Throttler::shouldThrottle() { + int64_t now = android::elapsedRealtime(); + if (now > mRefractoryPeriodMs + mLastRefractoryMs) { + mLastRefractoryMs = now; + mAccumulatedSize = 0; + } + return mAccumulatedSize > mSizeLimit; +} + +void Throttler::addReportSize(size_t reportByteSize) { + VLOG("The current request took %d bytes to dropbox", (int)reportByteSize); + mAccumulatedSize += reportByteSize; +} + +void Throttler::dump(FILE* out) { + fprintf(out, "mSizeLimit=%d\n", (int)mSizeLimit); + fprintf(out, "mAccumulatedSize=%d\n", (int)mAccumulatedSize); + fprintf(out, "mRefractoryPeriodMs=%d\n", (int)mRefractoryPeriodMs); + fprintf(out, "mLastRefractoryMs=%d\n", (int)mLastRefractoryMs); +} diff --git a/cmds/incidentd/src/Throttler.h b/cmds/incidentd/src/Throttler.h new file mode 100644 index 0000000000000000000000000000000000000000..c56f75386d492056d45570d528e94758021f47a5 --- /dev/null +++ b/cmds/incidentd/src/Throttler.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +#ifndef THROTTLER_H +#define THROTTLER_H + +#include + +#include +/** + * This is a size-based throttler which prevents incidentd to take more data. + */ +class Throttler : public virtual android::RefBase { +public: + Throttler(size_t limit, int64_t refractoryPeriodMs); + ~Throttler(); + + /** + * Asserts this before starting taking report. + */ + bool shouldThrottle(); + + void addReportSize(size_t reportByteSize); + + void dump(FILE* out); + +private: + const size_t mSizeLimit; + const int64_t mRefractoryPeriodMs; + + size_t mAccumulatedSize; + int64_t mLastRefractoryMs; +}; + +#endif // THROTTLER_H diff --git a/cmds/incidentd/src/report_directory.cpp b/cmds/incidentd/src/report_directory.cpp index b71c066201c4fc9c3f380462f03b73018776d1f3..f023ee1a6b7f60d73b901777f0572a753d7e5209 100644 --- a/cmds/incidentd/src/report_directory.cpp +++ b/cmds/incidentd/src/report_directory.cpp @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#define DEBUG false #include "Log.h" #include "report_directory.h" diff --git a/cmds/incidentd/tests/FdBuffer_test.cpp b/cmds/incidentd/tests/FdBuffer_test.cpp index 956c8d39346a553627bc0d1215136bd47d1cb828..0e5eec6c702302586dad59b308a188348baad7b7 100644 --- a/cmds/incidentd/tests/FdBuffer_test.cpp +++ b/cmds/incidentd/tests/FdBuffer_test.cpp @@ -11,6 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +#define DEBUG false #include "Log.h" #include "FdBuffer.h" diff --git a/cmds/incidentd/tests/PrivacyBuffer_test.cpp b/cmds/incidentd/tests/PrivacyBuffer_test.cpp index 7ea9bbfcd8c73a7a2bea630d10e83afd0bfce7ee..c7c69a746f0ac3bf6055915fce679d29db254b8c 100644 --- a/cmds/incidentd/tests/PrivacyBuffer_test.cpp +++ b/cmds/incidentd/tests/PrivacyBuffer_test.cpp @@ -11,6 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +#define DEBUG false #include "Log.h" #include "FdBuffer.h" diff --git a/cmds/incidentd/tests/Reporter_test.cpp b/cmds/incidentd/tests/Reporter_test.cpp index bd359ac9516cf7478683bc4372d01a1e684869c1..955dbac72ebe1ed8220f964ef2b3a16a9f0f1d58 100644 --- a/cmds/incidentd/tests/Reporter_test.cpp +++ b/cmds/incidentd/tests/Reporter_test.cpp @@ -11,6 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +#define DEBUG false #include "Log.h" #include "Reporter.h" @@ -106,6 +107,7 @@ protected: ReportRequestSet requests; sp reporter; sp l; + size_t size; }; TEST_F(ReporterTest, IncidentReportArgs) { @@ -125,7 +127,7 @@ TEST_F(ReporterTest, ReportRequestSetEmpty) { } TEST_F(ReporterTest, RunReportEmpty) { - ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport()); + ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport(&size)); EXPECT_EQ(l->startInvoked, 0); EXPECT_EQ(l->finishInvoked, 0); EXPECT_TRUE(l->startSections.empty()); @@ -147,7 +149,7 @@ TEST_F(ReporterTest, RunReportWithHeaders) { reporter->batch.add(r1); reporter->batch.add(r2); - ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport()); + ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport(&size)); string result; ReadFileToString(tf.path, &result); @@ -171,7 +173,7 @@ TEST_F(ReporterTest, RunReportToGivenDirectory) { sp r = new ReportRequest(args, l, -1); reporter->batch.add(r); - ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport()); + ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport(&size)); vector results = InspectFiles(); ASSERT_EQ((int)results.size(), 1); EXPECT_EQ(results[0], @@ -188,7 +190,7 @@ TEST_F(ReporterTest, ReportMetadata) { sp r = new ReportRequest(args, l, -1); reporter->batch.add(r); - ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport()); + ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport(&size)); auto metadata = reporter->batch.metadata(); EXPECT_EQ(IncidentMetadata_Destination_EXPLICIT, metadata.dest()); EXPECT_EQ(1, metadata.request_size()); diff --git a/cmds/incidentd/tests/Section_test.cpp b/cmds/incidentd/tests/Section_test.cpp index a1f4fdc773009c03a420e89ba077096b09022192..026bf7419eb1e002296bc1854936de1541f6dbc1 100644 --- a/cmds/incidentd/tests/Section_test.cpp +++ b/cmds/incidentd/tests/Section_test.cpp @@ -11,6 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +#define DEBUG false #include "Log.h" #include "Section.h" diff --git a/cmds/incidentd/tests/Throttler_test.cpp b/cmds/incidentd/tests/Throttler_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..213dcef5d30aebb84b918db751daed00e1a0fe27 --- /dev/null +++ b/cmds/incidentd/tests/Throttler_test.cpp @@ -0,0 +1,37 @@ +// 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. +#define DEBUG false +#include "Log.h" + +#include "Throttler.h" + +#include +#include +#include + +TEST(ThrottlerTest, DataSizeExceeded) { + Throttler t(100, 100000); + EXPECT_FALSE(t.shouldThrottle()); + t.addReportSize(200); + EXPECT_TRUE(t.shouldThrottle()); +} + +TEST(ThrottlerTest, TimeReset) { + Throttler t(100, 500); + EXPECT_FALSE(t.shouldThrottle()); + t.addReportSize(200); + EXPECT_TRUE(t.shouldThrottle()); + sleep(1); // sleep for 1 second to make sure throttler resets + EXPECT_FALSE(t.shouldThrottle()); +} diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp index a5eae15b50da7bd4cd3562b7302f422e5dffe9a4..b5660995fa369cd717c1d464b2996f0ac69ed12c 100644 --- a/cmds/statsd/Android.bp +++ b/cmds/statsd/Android.bp @@ -21,6 +21,7 @@ cc_library_host_shared { name: "libstats_proto_host", srcs: [ "src/atoms.proto", + "src/atom_field_options.proto", ], shared_libs: [ @@ -30,6 +31,9 @@ cc_library_host_shared { proto: { type: "full", export_proto_headers: true, + include_dirs: [ + "external/protobuf/src", + ], }, export_shared_lib_headers: [ diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk index 740fdc0af5f17aa919e8beaeabeaea15a1c51402..87825f1619702830623ad9fd1e0ac05e2792538b 100644 --- a/cmds/statsd/Android.mk +++ b/cmds/statsd/Android.mk @@ -17,9 +17,8 @@ LOCAL_PATH:= $(call my-dir) statsd_common_src := \ ../../core/java/android/os/IStatsCompanionService.aidl \ ../../core/java/android/os/IStatsManager.aidl \ - src/stats_log.proto \ + src/stats_log_common.proto \ src/statsd_config.proto \ - src/atoms.proto \ src/FieldValue.cpp \ src/stats_log_util.cpp \ src/anomaly/AnomalyMonitor.cpp \ @@ -168,6 +167,9 @@ LOCAL_CFLAGS += \ LOCAL_SRC_FILES := \ $(statsd_common_src) \ + src/atom_field_options.proto \ + src/atoms.proto \ + src/stats_log.proto \ tests/AnomalyMonitor_test.cpp \ tests/anomaly/AnomalyTracker_test.cpp \ tests/ConfigManager_test.cpp \ @@ -202,9 +204,13 @@ LOCAL_STATIC_LIBRARIES := \ $(statsd_common_static_libraries) \ libgmock -LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries) +LOCAL_PROTOC_OPTIMIZE_TYPE := full -LOCAL_PROTOC_OPTIMIZE_TYPE := lite +LOCAL_PROTOC_FLAGS := \ + -Iexternal/protobuf/src + +LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries) \ + libprotobuf-cpp-full include $(BUILD_NATIVE_TEST) @@ -217,6 +223,7 @@ LOCAL_MODULE := statsdprotolite LOCAL_SRC_FILES := \ src/stats_log.proto \ + src/stats_log_common.proto \ src/statsd_config.proto \ src/perfetto/perfetto_config.proto \ src/atoms.proto @@ -226,6 +233,9 @@ LOCAL_PROTOC_OPTIMIZE_TYPE := lite LOCAL_STATIC_JAVA_LIBRARIES := \ platformprotoslite +LOCAL_PROTOC_FLAGS := \ + -Iexternal/protobuf/src + include $(BUILD_STATIC_JAVA_LIBRARY) ############################## @@ -239,7 +249,8 @@ LOCAL_SRC_FILES := $(statsd_common_src) \ benchmark/main.cpp \ benchmark/hello_world_benchmark.cpp \ benchmark/log_event_benchmark.cpp \ - benchmark/stats_write_benchmark.cpp + benchmark/stats_write_benchmark.cpp \ + benchmark/filter_value_benchmark.cpp LOCAL_C_INCLUDES := $(statsd_common_c_includes) @@ -261,8 +272,6 @@ LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries) \ libgtest_prod \ libstatslog -LOCAL_PROTOC_OPTIMIZE_TYPE := lite - LOCAL_MODULE_TAGS := eng tests include $(BUILD_NATIVE_BENCHMARK) diff --git a/cmds/statsd/benchmark/filter_value_benchmark.cpp b/cmds/statsd/benchmark/filter_value_benchmark.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b9ddf36d82955cbbc89c0d897e696ec31035c822 --- /dev/null +++ b/cmds/statsd/benchmark/filter_value_benchmark.cpp @@ -0,0 +1,53 @@ +/* + * 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. + */ +#include +#include "benchmark/benchmark.h" +#include "FieldValue.h" +#include "HashableDimensionKey.h" +#include "logd/LogEvent.h" + +namespace android { +namespace os { +namespace statsd { + +using std::vector; + +static void BM_FilterValue(benchmark::State& state) { + LogEvent event(1, 100000); + event.write(3.2f); + event.write("LOCATION"); + event.write((int64_t)990); + event.init(); + + FieldMatcher field_matcher; + field_matcher.set_field(1); + field_matcher.add_child()->set_field(2); + field_matcher.add_child()->set_field(3); + + std::vector matchers; + translateFieldMatcher(field_matcher, &matchers); + + while (state.KeepRunning()) { + vector output; + filterValues(matchers, event.getValues(), &output); + } +} + +BENCHMARK(BM_FilterValue); + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/src/FieldValue.cpp b/cmds/statsd/src/FieldValue.cpp index 6894bcf53e79b181cccc499f4b19aa1e4afcca5d..b541612f73df39e7002aef18e1bc707d4ae9c85e 100644 --- a/cmds/statsd/src/FieldValue.cpp +++ b/cmds/statsd/src/FieldValue.cpp @@ -135,6 +135,8 @@ Value::Value(const Value& from) { case STRING: str_value = from.str_value; break; + default: + break; } } @@ -148,6 +150,8 @@ std::string Value::toString() const { return std::to_string(float_value) + "[F]"; case STRING: return str_value + "[S]"; + default: + return "[UNKNOWN]"; } } @@ -163,6 +167,8 @@ bool Value::operator==(const Value& that) const { return float_value == that.float_value; case STRING: return str_value == that.str_value; + default: + return false; } } @@ -177,6 +183,8 @@ bool Value::operator!=(const Value& that) const { return float_value != that.float_value; case STRING: return str_value != that.str_value; + default: + return false; } } diff --git a/cmds/statsd/src/FieldValue.h b/cmds/statsd/src/FieldValue.h index d17dded8d69108ee531330fc15a5326306ee543b..21f30e288c257b3c0a2c9d27e62bd5bdce69bf20 100644 --- a/cmds/statsd/src/FieldValue.h +++ b/cmds/statsd/src/FieldValue.h @@ -31,7 +31,7 @@ const int32_t kMaxLogDepth = 2; const int32_t kLastBitMask = 0x80; const int32_t kClearLastBitDeco = 0x7f; -enum Type { INT, LONG, FLOAT, STRING }; +enum Type { UNKNOWN, INT, LONG, FLOAT, STRING }; int32_t getEncodedField(int32_t pos[], int32_t depth, bool includeDepth); @@ -82,6 +82,8 @@ private: int32_t mField; public: + Field() {} + Field(int32_t tag, int32_t pos[], int32_t depth) : mTag(tag) { mField = getEncodedField(pos, depth, true); } @@ -229,6 +231,8 @@ struct Matcher { * */ struct Value { + Value() : type(UNKNOWN) {} + Value(int32_t v) { int_value = v; type = INT; @@ -280,15 +284,13 @@ struct Value { bool operator!=(const Value& that) const; bool operator<(const Value& that) const; - -private: - Value(){}; }; /** * Represents a log item, or a dimension item (They are essentially the same). */ struct FieldValue { + FieldValue() {} FieldValue(const Field& field, const Value& value) : mField(field), mValue(value) { } bool operator==(const FieldValue& that) const { diff --git a/cmds/statsd/src/HashableDimensionKey.cpp b/cmds/statsd/src/HashableDimensionKey.cpp index d901bd669591d9a5b4038ee73b7a5b44e008c9e2..1502a00abee92f390fd685213845c17866265ebc 100644 --- a/cmds/statsd/src/HashableDimensionKey.cpp +++ b/cmds/statsd/src/HashableDimensionKey.cpp @@ -16,12 +16,16 @@ #define DEBUG false // STOPSHIP if true #include "Log.h" +#include + #include "HashableDimensionKey.h" #include "FieldValue.h" namespace android { namespace os { namespace statsd { + +using std::string; using std::vector; android::hash_t hashDimension(const HashableDimensionKey& value) { @@ -44,10 +48,12 @@ android::hash_t hashDimension(const HashableDimensionKey& value) { fieldValue.mValue.str_value))); break; case FLOAT: { - float floatVal = fieldValue.mValue.float_value; - hash = android::JenkinsHashMixBytes(hash, (uint8_t*)&floatVal, sizeof(float)); + hash = android::JenkinsHashMix(hash, + android::hash_type(fieldValue.mValue.float_value)); break; } + default: + break; } } return JenkinsHashWhiten(hash); @@ -62,26 +68,32 @@ bool filterValues(const vector& matcherFields, const vector int prevAnyMatcherPrefix = 0; size_t prevPrevFanout = 0; size_t prevFanout = 0; + // For each matcher get matched results. + vector matchedResults(2); for (const auto& matcher : matcherFields) { - vector matchedResults; + size_t num_matches = 0; for (const auto& value : values) { // TODO: potential optimization here to break early because all fields are naturally // sorted. if (value.mField.matches(matcher)) { - matchedResults.push_back(FieldValue( - Field(value.mField.getTag(), (value.mField.getField() & matcher.mMask)), - value.mValue)); + if (num_matches >= matchedResults.size()) { + matchedResults.resize(num_matches * 2); + } + matchedResults[num_matches].mField.setTag(value.mField.getTag()); + matchedResults[num_matches].mField.setField(value.mField.getField() & matcher.mMask); + matchedResults[num_matches].mValue = value.mValue; + num_matches++; } } - if (matchedResults.size() == 0) { + if (num_matches == 0) { VLOG("We can't find a dimension value for matcher (%d)%#x.", matcher.mMatcher.getTag(), matcher.mMatcher.getField()); continue; } - if (matchedResults.size() == 1) { + if (num_matches == 1) { for (auto& dimension : *output) { dimension.addValue(matchedResults[0]); } @@ -117,23 +129,23 @@ bool filterValues(const vector& matcherFields, const vector // First create fanout (fanout size is matchedResults.Size which could be one, // which means we do nothing here) oldSize = output->size(); - for (size_t i = 1; i < matchedResults.size(); i++) { + for (size_t i = 1; i < num_matches; i++) { output->insert(output->end(), output->begin(), output->begin() + oldSize); } prevPrevFanout = oldSize; - prevFanout = matchedResults.size(); + prevFanout = num_matches; } else { // If we should not create fanout, e.g., uid tag from same position should be remain // together. oldSize = prevPrevFanout; - if (prevFanout != matchedResults.size()) { + if (prevFanout != num_matches) { // sanity check. ALOGE("2 Any matcher result in different output"); return false; } } // now add the matched field value to output - for (size_t i = 0; i < matchedResults.size(); i++) { + for (size_t i = 0; i < num_matches; i++) { for (int j = 0; j < oldSize; j++) { (*output)[i * oldSize + j].addValue(matchedResults[i]); } diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index 87dec5d1656d250523df53aad7530a1ca216cb9f..3c9dd68c1cc29697ff8813a32f1c1c27004a7d7c 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -316,7 +316,7 @@ void StatsLogProcessor::flushIfNecessaryLocked( StatsdStats::kMaxMetricsBytesPerConfig) { // Too late. We need to start clearing data. // TODO(b/70571383): By 12/15/2017 add API to drop data directly ProtoOutputStream proto; - metricsManager.onDumpReport(time(nullptr) * NS_PER_SEC, &proto); + metricsManager.onDumpReport(timestampNs, &proto); StatsdStats::getInstance().noteDataDropped(key); VLOG("StatsD had to toss out metrics for %s", key.ToString().c_str()); } else if (totalBytes > .9 * StatsdStats::kMaxMetricsBytesPerConfig) { @@ -340,7 +340,7 @@ void StatsLogProcessor::WriteDataToDisk() { for (auto& pair : mMetricsManagers) { const ConfigKey& key = pair.first; vector data; - onDumpReportLocked(key, time(nullptr) * NS_PER_SEC, &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()); diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index 791fb14a7717d48a1160bdee8a73e49a55452b36..c27b130678cd141aee605ab2da2656b888d4c0dd 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -493,7 +493,7 @@ status_t StatsService::cmd_dump_report(FILE* out, FILE* err, const Vector data; - mProcessor->onDumpReport(ConfigKey(uid, StrToInt64(name)), time(nullptr) * NS_PER_SEC, + mProcessor->onDumpReport(ConfigKey(uid, StrToInt64(name)), getElapsedRealtimeNs(), &data); // TODO: print the returned StatsLogReport to file instead of printing to logcat. if (proto) { @@ -659,6 +659,7 @@ Status StatsService::informOnePackageRemoved(const String16& app, int32_t uid) { "Only system uid can call informOnePackageRemoved"); } mUidMap->removeApp(app, uid); + mConfigManager->RemoveConfigs(uid); return Status::ok(); } @@ -785,7 +786,7 @@ Status StatsService::getData(int64_t key, vector* output) { VLOG("StatsService::getData with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid()); if (checkCallingPermission(String16(kPermissionDump))) { ConfigKey configKey(ipc->getCallingUid(), key); - mProcessor->onDumpReport(configKey, time(nullptr) * NS_PER_SEC, output); + mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(), output); return Status::ok(); } else { return Status::fromExceptionCode(binder::Status::EX_SECURITY); diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp index 443d33d39915d79723740eb5603a210667df6f10..c40eb812f949e0aed3cec3affdc30f362d5e2f37 100644 --- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp +++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp @@ -149,6 +149,10 @@ void AnomalyTracker::addBucketToSum(const shared_ptr& bucket) { int64_t AnomalyTracker::getPastBucketValue(const MetricDimensionKey& key, const int64_t& bucketNum) const { + if (mNumOfPastBuckets == 0) { + return 0; + } + const auto& bucket = mPastBuckets[index(bucketNum)]; if (bucket == nullptr) { return 0; @@ -188,7 +192,7 @@ void AnomalyTracker::declareAnomaly(const uint64_t& timestampNs, const MetricDim if (!mSubscriptions.empty()) { if (mAlert.has_id()) { - ALOGI("An anomaly (%llu) has occurred! Informing subscribers.", mAlert.id()); + ALOGI("An anomaly (%lld) has occurred! Informing subscribers.", mAlert.id()); informSubscribers(key); } else { ALOGI("An anomaly (with no id) has occurred! Not informing any subscribers."); @@ -229,11 +233,19 @@ bool AnomalyTracker::isInRefractoryPeriod(const uint64_t& timestampNs, void AnomalyTracker::informSubscribers(const MetricDimensionKey& key) { VLOG("informSubscribers called."); if (mSubscriptions.empty()) { - ALOGE("Attempt to call with no subscribers."); + // The config just wanted to log the anomaly. That's fine. + VLOG("No Subscriptions were associated with the alert."); return; } for (const Subscription& subscription : mSubscriptions) { + if (subscription.probability_of_informing() < 1 + && ((float)rand() / RAND_MAX) >= subscription.probability_of_informing()) { + // Note that due to float imprecision, 0.0 and 1.0 might not truly mean never/always. + // The config writer was advised to use -0.1 and 1.1 for never/always. + ALOGI("Fate decided that a subscriber would not be informed."); + continue; + } switch (subscription.subscriber_information_case()) { case Subscription::SubscriberInformationCase::kIncidentdDetails: if (!GenerateIncidentReport(subscription.incidentd_details(), mAlert, mConfigKey)) { diff --git a/cmds/statsd/src/anomaly/DurationAnomalyTracker.h b/cmds/statsd/src/anomaly/DurationAnomalyTracker.h index ba687dacf5194fc225cfc35b29bc5f48ad77fbcc..15aef29bc644c97fa4814e94f1ca7c79b42b8f9d 100644 --- a/cmds/statsd/src/anomaly/DurationAnomalyTracker.h +++ b/cmds/statsd/src/anomaly/DurationAnomalyTracker.h @@ -72,7 +72,8 @@ protected: FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm); FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm); FRIEND_TEST(MaxDurationTrackerTest, TestAnomalyDetection); - FRIEND_TEST(MaxDurationTrackerTest, TestAnomalyDetection); + FRIEND_TEST(MaxDurationTrackerTest, TestAnomalyPredictedTimestamp); + FRIEND_TEST(MaxDurationTrackerTest, TestAnomalyPredictedTimestamp_UpdatedOnStop); }; } // namespace statsd diff --git a/cmds/statsd/src/atom_field_options.proto b/cmds/statsd/src/atom_field_options.proto new file mode 100644 index 0000000000000000000000000000000000000000..19d00b7dc4a5bbec6598150d54c2a85e339f83de --- /dev/null +++ b/cmds/statsd/src/atom_field_options.proto @@ -0,0 +1,70 @@ +/* + * 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"; + +package android.os.statsd; +option java_package = "com.android.os"; +option java_multiple_files = true; +option java_outer_classname = "AtomFieldOptions"; + +import "google/protobuf/descriptor.proto"; + +enum StateField { + // Default value for fields that are not primary or exclusive state. + STATE_FIELD_UNSET = 0; + // Fields that represent the key that the state belongs to. + PRIMARY = 1; + // The field that represents the state. It's an exclusive state. + EXCLUSIVE = 2; +} + +// Used to annotate an atom that reprsents a state change. A state change atom must have exactly ONE +// exclusive state field, and any number of primary key fields. +// For example, +// message UidProcessStateChanged { +// optional int32 uid = 1 [(stateFieldOption).option = PRIMARY]; +// optional android.app.ProcessStateEnum state = 2 [(stateFieldOption).option = EXCLUSIVE]; +// } +// Each of this UidProcessStateChanged atom represents a state change for a specific uid. +// A new state automatically overrides the previous state. +// +// If the atom has 2 or more primary fields, it means the combination of the primary fields are +// the primary key. +// For example: +// message ThreadStateChanged { +// optional int32 pid = 1 [(stateFieldOption).option = PRIMARY]; +// optional int32 tid = 2 [(stateFieldOption).option = PRIMARY]; +// optional int32 state = 3 [(stateFieldOption).option = EXCLUSIVE]; +// } +// +// Sometimes, there is no primary key field, when the state is GLOBAL. +// For example, +// +// message ScreenStateChanged { +// optional android.view.DisplayStateEnum state = 1 [(stateFieldOption).option = EXCLUSIVE]; +// } +// +// Only fields of primary types can be annotated. AttributionNode cannot be primary keys (and they +// usually are not). +message StateAtomFieldOption { + optional StateField option = 1 [default = STATE_FIELD_UNSET]; +} + +extend google.protobuf.FieldOptions { + // Flags to decorate an atom that presents a state change. + optional StateAtomFieldOption stateFieldOption = 50000; +} \ No newline at end of file diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 85e209be6413ba859e680df3b5cca59013da8f01..04ebfcd0f4dec236701c5a4e6a52e299c8f46e6f 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -21,6 +21,7 @@ package android.os.statsd; option java_package = "com.android.os"; option java_outer_classname = "AtomsProto"; +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/os/enums.proto"; import "frameworks/base/core/proto/android/server/enums.proto"; @@ -179,7 +180,7 @@ message AttributionNode { */ message ScreenStateChanged { // New screen state, from frameworks/base/core/proto/android/view/enums.proto. - optional android.view.DisplayStateEnum state = 1; + optional android.view.DisplayStateEnum state = 1 [(stateFieldOption).option = EXCLUSIVE]; } /** @@ -189,10 +190,10 @@ message ScreenStateChanged { * frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java */ message UidProcessStateChanged { - optional int32 uid = 1; // TODO: should be a string tagged w/ uid annotation + optional int32 uid = 1 [(stateFieldOption).option = PRIMARY]; // The state, from frameworks/base/core/proto/android/app/enums.proto. - optional android.app.ProcessStateEnum state = 2; + optional android.app.ProcessStateEnum state = 2 [(stateFieldOption).option = EXCLUSIVE]; } /** @@ -939,6 +940,11 @@ message AppStartChanged { // Empty if not set. optional string launch_token = 13; + // The compiler filter used when when the package was optimized. + optional string package_optimization_compilation_filter = 14; + + // The reason why the package was optimized. + optional string package_optimization_compilation_reason = 15; } message AppStartCancelChanged { @@ -993,21 +999,18 @@ message AppStartFullyDrawnChanged { * frameworks/base/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java */ message PictureInPictureStateChanged { + // -1 if it is not available optional int32 uid = 1; - optional string package_name = 2; - - optional string class_name = 3; + optional string short_name = 2; - // Picture-in-Picture action occurred, similar to - // frameworks/base/proto/src/metrics_constants.proto enum State { ENTERED = 1; EXPANDED_TO_FULL_SCREEN = 2; MINIMIZED = 3; DISMISSED = 4; } - optional State state = 4; + optional State state = 3; } /** @@ -1517,5 +1520,4 @@ message RemainingBatteryCapacity { */ message FullBatteryCapacity { optional int32 capacity_uAh = 1; -} - +} \ No newline at end of file diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h index 7baa5e57679e4386d3bf9ed43c1d2694cee52cb3..8c16e4e9c2eb64fbf9400ca8b89a2becc7d9be4f 100644 --- a/cmds/statsd/src/guardrail/StatsdStats.h +++ b/cmds/statsd/src/guardrail/StatsdStats.h @@ -16,7 +16,7 @@ #pragma once #include "config/ConfigKey.h" -#include "frameworks/base/cmds/statsd/src/stats_log.pb.h" +#include "frameworks/base/cmds/statsd/src/stats_log_common.pb.h" #include "statslog.h" #include diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp index f07fc66dbcbb081968fb9d6c61cea9df1b8bf888..d282b86f52bdf7a9459a734fae567ab1b32f600c 100644 --- a/cmds/statsd/src/logd/LogEvent.cpp +++ b/cmds/statsd/src/logd/LogEvent.cpp @@ -26,9 +26,10 @@ namespace os { namespace statsd { using namespace android::util; +using android::util::ProtoOutputStream; using std::ostringstream; using std::string; -using android::util::ProtoOutputStream; +using std::vector; LogEvent::LogEvent(log_msg& msg) { mContext = @@ -130,7 +131,7 @@ bool LogEvent::write(float value) { return false; } -bool LogEvent::write(const std::vector& nodes) { +bool LogEvent::write(const std::vector& nodes) { if (mContext) { if (android_log_write_list_begin(mContext) < 0) { return false; @@ -148,7 +149,7 @@ bool LogEvent::write(const std::vector& nodes) { return false; } -bool LogEvent::write(const AttributionNode& node) { +bool LogEvent::write(const AttributionNodeInternal& node) { if (mContext) { if (android_log_write_list_begin(mContext) < 0) { return false; diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h index b3084d54d8480eaf1cdd1effa42a0da122593dd9..24d624d9d9be45641dad09885ca11ffae0239c9f 100644 --- a/cmds/statsd/src/logd/LogEvent.h +++ b/cmds/statsd/src/logd/LogEvent.h @@ -17,7 +17,6 @@ #pragma once #include "FieldValue.h" -#include "frameworks/base/cmds/statsd/src/stats_log.pb.h" #include #include @@ -32,8 +31,26 @@ namespace android { namespace os { namespace statsd { -using std::string; -using std::vector; +struct AttributionNodeInternal { + void set_uid(int32_t id) { + mUid = id; + } + + void set_tag(const std::string& value) { + mTag = value; + } + + int32_t uid() const { + return mUid; + } + + const std::string& tag() const { + return mTag; + } + + int32_t mUid; + std::string mTag; +}; /** * Wrapper for the log_msg structure. */ @@ -89,15 +106,15 @@ public: bool write(int32_t value); bool write(uint64_t value); bool write(int64_t value); - bool write(const string& value); + bool write(const std::string& value); bool write(float value); - bool write(const std::vector& nodes); - bool write(const AttributionNode& node); + bool write(const std::vector& nodes); + bool write(const AttributionNodeInternal& node); /** * Return a string representation of this event. */ - string ToString() const; + std::string ToString() const; /** * Write this object to a ProtoOutputStream. diff --git a/cmds/statsd/src/matchers/matcher_util.h b/cmds/statsd/src/matchers/matcher_util.h index 872cd8e64575c69bd00a7e511b94ec699a67855b..ae946d16b352e26acd6aa9fc2e8aba52f218abfa 100644 --- a/cmds/statsd/src/matchers/matcher_util.h +++ b/cmds/statsd/src/matchers/matcher_util.h @@ -24,10 +24,10 @@ #include #include #include -#include "frameworks/base/cmds/statsd/src/stats_log.pb.h" +#include "frameworks/base/cmds/statsd/src/stats_log_common.pb.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" -#include "stats_util.h" #include "packages/UidMap.h" +#include "stats_util.h" namespace android { namespace os { diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp index 2585aa3bdbffca3a99fa31569d92a1176dd0c9e5..96d0cfcc5897861b62d6a1edf9fe90d6556e14da 100644 --- a/cmds/statsd/src/metrics/EventMetricProducer.cpp +++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp @@ -129,12 +129,23 @@ void EventMetricProducer::onMatchedLogEventInternalLocked( long long wrapperToken = mProto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA); - mProto->write(FIELD_TYPE_INT64 | FIELD_ID_ELAPSED_TIMESTAMP_NANOS, - (long long)event.GetElapsedTimestampNs()); + const bool truncateTimestamp = + android::util::kNotTruncatingTimestampAtomWhiteList.find(event.GetTagId()) == + android::util::kNotTruncatingTimestampAtomWhiteList.end(); + if (truncateTimestamp) { + mProto->write(FIELD_TYPE_INT64 | FIELD_ID_ELAPSED_TIMESTAMP_NANOS, + (long long)truncateTimestampNsToFiveMinutes(event.GetElapsedTimestampNs())); + mProto->write(FIELD_TYPE_INT64 | FIELD_ID_WALL_CLOCK_TIMESTAMP_NANOS, + (long long)truncateTimestampNsToFiveMinutes(getWallClockNs())); + } else { + mProto->write(FIELD_TYPE_INT64 | FIELD_ID_ELAPSED_TIMESTAMP_NANOS, + (long long)event.GetElapsedTimestampNs()); + mProto->write(FIELD_TYPE_INT64 | FIELD_ID_WALL_CLOCK_TIMESTAMP_NANOS, + (long long)getWallClockNs()); + } + long long eventToken = mProto->start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOMS); event.ToProto(*mProto); - mProto->write(FIELD_TYPE_INT64 | FIELD_ID_WALL_CLOCK_TIMESTAMP_NANOS, - (long long)getWallClockNs()); mProto->end(eventToken); mProto->end(wrapperToken); } diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp index 0daa506ba42d26244eb009c44ce52e618faaf13f..7d09ff9ffc8e9c8ddbbb604239df99dc2017762a 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp @@ -173,11 +173,15 @@ void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, writeFieldValueTreeToStream(mTagId, *(atom.mFields), protoOutput); } protoOutput->end(atomsToken); - for (const auto& atom : bucket.mGaugeAtoms) { + const bool truncateTimestamp = + android::util::kNotTruncatingTimestampAtomWhiteList.find(mTagId) == + android::util::kNotTruncatingTimestampAtomWhiteList.end(); + int64_t timestampNs = truncateTimestamp ? + truncateTimestampNsToFiveMinutes(atom.mTimestamps) : atom.mTimestamps; protoOutput->write( FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_ELAPSED_ATOM_TIMESTAMP, - (long long)atom.mTimestamps); + (long long)timestampNs); } } protoOutput->end(bucketInfoToken); diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp index 95df5ae6e8bd3af117cf242f4088e99d7ae9d83a..b225560e76a8c3d35a61d6f1f2108a3ee6cbcdbe 100644 --- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp +++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp @@ -93,6 +93,7 @@ void MaxDurationTracker::noteStart(const HashableDimensionKey& key, bool conditi } else { duration.state = DurationState::kStarted; duration.lastStartTime = eventTime; + startAnomalyAlarm(eventTime); } duration.startCount = 1; break; @@ -116,12 +117,18 @@ void MaxDurationTracker::noteStop(const HashableDimensionKey& key, const uint64_ case DurationState::kStarted: { duration.startCount--; if (forceStop || !mNested || duration.startCount <= 0) { + stopAnomalyAlarm(); duration.state = DurationState::kStopped; int64_t durationTime = eventTime - duration.lastStartTime; VLOG("Max, key %s, Stop %lld %lld %lld", key.c_str(), (long long)duration.lastStartTime, (long long)eventTime, (long long)durationTime); duration.lastDuration += durationTime; + if (anyStarted()) { + // In case any other dimensions are still started, we need to keep the alarm + // set. + startAnomalyAlarm(eventTime); + } VLOG(" record duration: %lld ", (long long)duration.lastDuration); } break; @@ -146,6 +153,15 @@ void MaxDurationTracker::noteStop(const HashableDimensionKey& key, const uint64_ } } +bool MaxDurationTracker::anyStarted() { + for (auto& pair : mInfos) { + if (pair.second.state == kStarted) { + return true; + } + } + return false; +} + void MaxDurationTracker::noteStopAll(const uint64_t eventTime) { std::set keys; for (const auto& pair : mInfos) { @@ -251,35 +267,52 @@ void MaxDurationTracker::noteConditionChanged(const HashableDimensionKey& key, b switch (it->second.state) { case kStarted: - // if condition becomes false, kStarted -> kPaused. Record the current duration. + // If condition becomes false, kStarted -> kPaused. Record the current duration and + // stop anomaly alarm. if (!conditionMet) { + stopAnomalyAlarm(); it->second.state = DurationState::kPaused; it->second.lastDuration += (timestamp - it->second.lastStartTime); + if (anyStarted()) { + // In case any other dimensions are still started, we need to set the alarm. + startAnomalyAlarm(timestamp); + } VLOG("MaxDurationTracker Key: %s Started->Paused ", key.c_str()); } break; case kStopped: - // nothing to do if it's stopped. + // Nothing to do if it's stopped. break; case kPaused: - // if condition becomes true, kPaused -> kStarted. and the start time is the condition + // If condition becomes true, kPaused -> kStarted. and the start time is the condition // change time. if (conditionMet) { it->second.state = DurationState::kStarted; it->second.lastStartTime = timestamp; + startAnomalyAlarm(timestamp); VLOG("MaxDurationTracker Key: %s Paused->Started", key.c_str()); } break; } - if (it->second.lastDuration > mDuration) { - mDuration = it->second.lastDuration; - } + // Note that we don't update mDuration here since it's only updated during noteStop. } int64_t MaxDurationTracker::predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker, const uint64_t currentTimestamp) const { - ALOGE("Max duration producer does not support anomaly timestamp prediction!!!"); - return currentTimestamp; + // The allowed time we can continue in the current state is the + // (anomaly threshold) - max(elapsed time of the started mInfos). + int64_t maxElapsed = 0; + for (auto it = mInfos.begin(); it != mInfos.end(); ++it) { + if (it->second.state == DurationState::kStarted) { + int64_t duration = + it->second.lastDuration + (currentTimestamp - it->second.lastStartTime); + if (duration > maxElapsed) { + maxElapsed = duration; + } + } + } + int64_t threshold = anomalyTracker.getAnomalyThreshold(); + return currentTimestamp + threshold - maxElapsed; } void MaxDurationTracker::dumpStates(FILE* out, bool verbose) const { diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h index 95863b60a192c339a436966776b6ad3ebc78c4ca..c731b75018811b5f5a6e2bb1b88d471824292275 100644 --- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h +++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h @@ -60,6 +60,9 @@ public: void dumpStates(FILE* out, bool verbose) const override; private: + // Returns true if at least one of the mInfos is started. + bool anyStarted(); + std::unordered_map mInfos; void noteConditionChanged(const HashableDimensionKey& key, bool conditionMet, @@ -72,6 +75,8 @@ private: FRIEND_TEST(MaxDurationTrackerTest, TestCrossBucketBoundary); FRIEND_TEST(MaxDurationTrackerTest, TestMaxDurationWithCondition); FRIEND_TEST(MaxDurationTrackerTest, TestStopAll); + FRIEND_TEST(MaxDurationTrackerTest, TestAnomalyDetection); + FRIEND_TEST(MaxDurationTrackerTest, TestAnomalyPredictedTimestamp); }; } // namespace statsd diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h index f1da452bf5b9325ca7c1a204a8c851fffce8e44a..c41e0aaca3d229a710024e2970d27c042c4623ef 100644 --- a/cmds/statsd/src/packages/UidMap.h +++ b/cmds/statsd/src/packages/UidMap.h @@ -18,7 +18,7 @@ #include "config/ConfigKey.h" #include "config/ConfigListener.h" -#include "frameworks/base/cmds/statsd/src/stats_log.pb.h" +#include "frameworks/base/cmds/statsd/src/stats_log_common.pb.h" #include "packages/PackageInfoListener.h" #include diff --git a/cmds/statsd/src/perfetto/perfetto_config.proto b/cmds/statsd/src/perfetto/perfetto_config.proto index dc868f997a633169f5ae76ae3c2b4f9254d686d6..56d12f8d81d460c6e79c4ae14521b3e5a1e7387a 100644 --- a/cmds/statsd/src/perfetto/perfetto_config.proto +++ b/cmds/statsd/src/perfetto/perfetto_config.proto @@ -15,7 +15,6 @@ */ syntax = "proto2"; -option optimize_for = LITE_RUNTIME; package perfetto.protos; diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto index b427485fd70506d48724ef63b9a6c699c524e29e..272e90be662da6eb9395f7e34e546f16d5ce593c 100644 --- a/cmds/statsd/src/stats_log.proto +++ b/cmds/statsd/src/stats_log.proto @@ -15,7 +15,6 @@ */ syntax = "proto2"; -option optimize_for = LITE_RUNTIME; package android.os.statsd; @@ -23,6 +22,7 @@ option java_package = "com.android.os"; option java_outer_classname = "StatsLog"; import "frameworks/base/cmds/statsd/src/atoms.proto"; +import "frameworks/base/cmds/statsd/src/stats_log_common.proto"; message DimensionsValue { optional int32 field = 1; @@ -115,33 +115,6 @@ message GaugeMetricData { repeated GaugeBucketInfo bucket_info = 3; } -message UidMapping { - message PackageInfoSnapshot { - message PackageInfo { - optional string name = 1; - - optional int64 version = 2; - - optional int32 uid = 3; - } - optional int64 elapsed_timestamp_nanos = 1; - - repeated PackageInfo package_info = 2; - } - repeated PackageInfoSnapshot snapshots = 1; - - message Change { - optional bool deletion = 1; - - optional int64 elapsed_timestamp_nanos = 2; - optional string app = 3; - optional int32 uid = 4; - - optional int64 version = 5; - } - repeated Change changes = 2; -} - message StatsLogReport { optional int64 metric_id = 1; @@ -191,87 +164,4 @@ message ConfigMetricsReportList { optional ConfigKey config_key = 1; repeated ConfigMetricsReport reports = 2; -} - -message StatsdStatsReport { - optional int32 stats_begin_time_sec = 1; - - optional int32 stats_end_time_sec = 2; - - message MatcherStats { - optional int64 id = 1; - optional int32 matched_times = 2; - } - - message ConditionStats { - optional int64 id = 1; - optional int32 max_tuple_counts = 2; - } - - message MetricStats { - optional int64 id = 1; - optional int32 max_tuple_counts = 2; - } - - message AlertStats { - optional int64 id = 1; - optional int32 alerted_times = 2; - } - - message ConfigStats { - optional int32 uid = 1; - optional int64 id = 2; - optional int32 creation_time_sec = 3; - optional int32 deletion_time_sec = 4; - optional int32 metric_count = 5; - optional int32 condition_count = 6; - optional int32 matcher_count = 7; - optional int32 alert_count = 8; - optional bool is_valid = 9; - - repeated int32 broadcast_sent_time_sec = 10; - repeated int32 data_drop_time_sec = 11; - repeated int32 dump_report_time_sec = 12; - repeated MatcherStats matcher_stats = 13; - repeated ConditionStats condition_stats = 14; - repeated MetricStats metric_stats = 15; - repeated AlertStats alert_stats = 16; - } - - repeated ConfigStats config_stats = 3; - - message AtomStats { - optional int32 tag = 1; - optional int32 count = 2; - } - - repeated AtomStats atom_stats = 7; - - message UidMapStats { - optional int32 snapshots = 1; - optional int32 changes = 2; - optional int32 bytes_used = 3; - optional int32 dropped_snapshots = 4; - optional int32 dropped_changes = 5; - } - optional UidMapStats uidmap_stats = 8; - - message AnomalyAlarmStats { - optional int32 alarms_registered = 1; - } - optional AnomalyAlarmStats anomaly_alarm_stats = 9; - - message PulledAtomStats { - optional int32 atom_id = 1; - optional int64 total_pull = 2; - optional int64 total_pull_from_cache = 3; - optional int64 min_pull_interval_sec = 4; - } - repeated PulledAtomStats pulled_atom_stats = 10; - - message LoggerErrorStats { - optional int32 logger_disconnection_sec = 1; - optional int32 error_code = 2; - } - repeated LoggerErrorStats logger_error_stats = 11; } \ No newline at end of file diff --git a/cmds/statsd/src/stats_log_common.proto b/cmds/statsd/src/stats_log_common.proto new file mode 100644 index 0000000000000000000000000000000000000000..aeecd23c65f4be1a1a773127292de54a4678db11 --- /dev/null +++ b/cmds/statsd/src/stats_log_common.proto @@ -0,0 +1,132 @@ +/* + * 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. + */ + +syntax = "proto2"; + +package android.os.statsd; + +option java_package = "com.android.os"; +option java_outer_classname = "StatsLogCommon"; + +message UidMapping { + message PackageInfoSnapshot { + message PackageInfo { + optional string name = 1; + + optional int64 version = 2; + + optional int32 uid = 3; + } + optional int64 elapsed_timestamp_nanos = 1; + + repeated PackageInfo package_info = 2; + } + repeated PackageInfoSnapshot snapshots = 1; + + message Change { + optional bool deletion = 1; + + optional int64 elapsed_timestamp_nanos = 2; + optional string app = 3; + optional int32 uid = 4; + + optional int64 version = 5; + } + repeated Change changes = 2; +} + +message StatsdStatsReport { + optional int32 stats_begin_time_sec = 1; + + optional int32 stats_end_time_sec = 2; + + message MatcherStats { + optional int64 id = 1; + optional int32 matched_times = 2; + } + + message ConditionStats { + optional int64 id = 1; + optional int32 max_tuple_counts = 2; + } + + message MetricStats { + optional int64 id = 1; + optional int32 max_tuple_counts = 2; + } + + message AlertStats { + optional int64 id = 1; + optional int32 alerted_times = 2; + } + + message ConfigStats { + optional int32 uid = 1; + optional int64 id = 2; + optional int32 creation_time_sec = 3; + optional int32 deletion_time_sec = 4; + optional int32 metric_count = 5; + optional int32 condition_count = 6; + optional int32 matcher_count = 7; + optional int32 alert_count = 8; + optional bool is_valid = 9; + + repeated int32 broadcast_sent_time_sec = 10; + repeated int32 data_drop_time_sec = 11; + repeated int32 dump_report_time_sec = 12; + repeated MatcherStats matcher_stats = 13; + repeated ConditionStats condition_stats = 14; + repeated MetricStats metric_stats = 15; + repeated AlertStats alert_stats = 16; + } + + repeated ConfigStats config_stats = 3; + + message AtomStats { + optional int32 tag = 1; + optional int32 count = 2; + } + + repeated AtomStats atom_stats = 7; + + message UidMapStats { + optional int32 snapshots = 1; + optional int32 changes = 2; + optional int32 bytes_used = 3; + optional int32 dropped_snapshots = 4; + optional int32 dropped_changes = 5; + } + optional UidMapStats uidmap_stats = 8; + + message AnomalyAlarmStats { + optional int32 alarms_registered = 1; + } + optional AnomalyAlarmStats anomaly_alarm_stats = 9; + + message PulledAtomStats { + optional int32 atom_id = 1; + optional int64 total_pull = 2; + optional int64 total_pull_from_cache = 3; + optional int64 min_pull_interval_sec = 4; + } + repeated PulledAtomStats pulled_atom_stats = 10; + + message LoggerErrorStats { + optional int32 logger_disconnection_sec = 1; + optional int32 error_code = 2; + } + repeated LoggerErrorStats logger_error_stats = 11; +} \ No newline at end of file diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp index 30eef4fef166f63775d57fe028d1fb27ad584290..78ebe3380b8ed1c7d412d69e11db9f5a3fda4eb8 100644 --- a/cmds/statsd/src/stats_log_util.cpp +++ b/cmds/statsd/src/stats_log_util.cpp @@ -183,6 +183,8 @@ void writeFieldValueTreeToStreamHelper(const std::vector& dims, size case STRING: protoOutput->write(FIELD_TYPE_STRING | fieldNum, dim.mValue.str_value); break; + default: + break; } (*index)++; } else if (valueDepth > depth && valuePrefix == prefix) { @@ -290,6 +292,10 @@ int64_t getWallClockMillis() { return time(nullptr) * MS_PER_SEC; } +int64_t truncateTimestampNsToFiveMinutes(int64_t timestampNs) { + return timestampNs / NS_PER_SEC / (5 * 60) * NS_PER_SEC * (5 * 60); +} + } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h index 6a5123d8c84425b7b2b3b83a15b561c1a35bed72..c512e3c63bcfc1842c522137000e2b6f1d2d67b8 100644 --- a/cmds/statsd/src/stats_log_util.h +++ b/cmds/statsd/src/stats_log_util.h @@ -19,7 +19,7 @@ #include #include "FieldValue.h" #include "HashableDimensionKey.h" -#include "frameworks/base/cmds/statsd/src/stats_log.pb.h" +#include "frameworks/base/cmds/statsd/src/stats_log_common.pb.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" #include "guardrail/StatsdStats.h" @@ -73,6 +73,9 @@ bool parseProtoOutputStream(util::ProtoOutputStream& protoOutput, T* message) { return message->ParseFromArray(pbBytes.c_str(), pbBytes.size()); } +// Returns the truncated timestamp. +int64_t truncateTimestampNsToFiveMinutes(int64_t timestampNs); + } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/src/stats_util.h b/cmds/statsd/src/stats_util.h index 31f51a7ac0a43650878d2f85be3638d89c232dbb..c4b47dcea8a204fb5a2008e70112197f0793f187 100644 --- a/cmds/statsd/src/stats_util.h +++ b/cmds/statsd/src/stats_util.h @@ -18,7 +18,7 @@ #include #include "HashableDimensionKey.h" -#include "frameworks/base/cmds/statsd/src/stats_log.pb.h" +#include "frameworks/base/cmds/statsd/src/stats_log_common.pb.h" #include "logd/LogReader.h" #include diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto index 5a326a47eb2472521ec305d682e6418db9f1e116..a31385470c9fcc7fb68cd966b9e889d2abcda8d4 100644 --- a/cmds/statsd/src/statsd_config.proto +++ b/cmds/statsd/src/statsd_config.proto @@ -15,7 +15,6 @@ */ syntax = "proto2"; -option optimize_for = LITE_RUNTIME; package android.os.statsd; @@ -308,6 +307,8 @@ message Subscription { PerfettoDetails perfetto_details = 5; BroadcastSubscriberDetails broadcast_subscriber_details = 6; } + + optional float probability_of_informing = 7 [default = 1.1]; } message StatsdConfig { diff --git a/cmds/statsd/src/subscriber/SubscriberReporter.cpp b/cmds/statsd/src/subscriber/SubscriberReporter.cpp index 9f68fc4c20be1f06a0745c1dab17cdbb779c857b..95ecf8033f4c631a4a63158bca500ab9583cdc00 100644 --- a/cmds/statsd/src/subscriber/SubscriberReporter.cpp +++ b/cmds/statsd/src/subscriber/SubscriberReporter.cpp @@ -27,6 +27,8 @@ namespace android { namespace os { namespace statsd { +using std::vector; + void SubscriberReporter::setBroadcastSubscriber(const ConfigKey& configKey, int64_t subscriberId, const sp& intentSender) { diff --git a/cmds/statsd/src/subscriber/SubscriberReporter.h b/cmds/statsd/src/subscriber/SubscriberReporter.h index c7d1a5ba9425bf7866f653d549d22be4db2741a0..50100df56ff8de92206ed7f8231474648f412387 100644 --- a/cmds/statsd/src/subscriber/SubscriberReporter.h +++ b/cmds/statsd/src/subscriber/SubscriberReporter.h @@ -21,7 +21,6 @@ #include "config/ConfigKey.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" // subscription -#include "frameworks/base/cmds/statsd/src/stats_log.pb.h" // DimensionsValue #include "android/os/StatsDimensionsValue.h" #include "HashableDimensionKey.h" diff --git a/cmds/statsd/tests/FieldValue_test.cpp b/cmds/statsd/tests/FieldValue_test.cpp index f1ad0c88b24224c14d72269564691c4f1794fcef..5846761cb8e9884de0abc5b8a73d087f400cb6e6 100644 --- a/cmds/statsd/tests/FieldValue_test.cpp +++ b/cmds/statsd/tests/FieldValue_test.cpp @@ -14,9 +14,10 @@ * limitations under the License. */ #include -#include "src/logd/LogEvent.h" +#include "frameworks/base/cmds/statsd/src/stats_log.pb.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" #include "matchers/matcher_util.h" +#include "src/logd/LogEvent.h" #include "stats_log_util.h" #include "stats_util.h" #include "subscriber/SubscriberReporter.h" @@ -64,19 +65,19 @@ TEST(AtomMatcherTest, TestFilter) { vector matchers; translateFieldMatcher(matcher1, &matchers); - AttributionNode attribution_node1; + AttributionNodeInternal attribution_node1; attribution_node1.set_uid(1111); attribution_node1.set_tag("location1"); - AttributionNode attribution_node2; + AttributionNodeInternal attribution_node2; attribution_node2.set_uid(2222); attribution_node2.set_tag("location2"); - AttributionNode attribution_node3; + AttributionNodeInternal attribution_node3; attribution_node3.set_uid(3333); attribution_node3.set_tag("location3"); - std::vector attribution_nodes = {attribution_node1, attribution_node2, - attribution_node3}; + std::vector attribution_nodes = {attribution_node1, attribution_node2, + attribution_node3}; // Set up the event LogEvent event(10, 12345); @@ -154,19 +155,19 @@ TEST(AtomMatcherTest, TestSubDimension) { } TEST(AtomMatcherTest, TestMetric2ConditionLink) { - AttributionNode attribution_node1; + AttributionNodeInternal attribution_node1; attribution_node1.set_uid(1111); attribution_node1.set_tag("location1"); - AttributionNode attribution_node2; + AttributionNodeInternal attribution_node2; attribution_node2.set_uid(2222); attribution_node2.set_tag("location2"); - AttributionNode attribution_node3; + AttributionNodeInternal attribution_node3; attribution_node3.set_uid(3333); attribution_node3.set_tag("location3"); - std::vector attribution_nodes = {attribution_node1, attribution_node2, - attribution_node3}; + std::vector attribution_nodes = {attribution_node1, attribution_node2, + attribution_node3}; // Set up the event LogEvent event(10, 12345); @@ -298,15 +299,15 @@ TEST(AtomMatcherTest, TestWriteDimensionToProto) { } TEST(AtomMatcherTest, TestWriteAtomToProto) { - AttributionNode attribution_node1; + AttributionNodeInternal attribution_node1; attribution_node1.set_uid(1111); attribution_node1.set_tag("location1"); - AttributionNode attribution_node2; + AttributionNodeInternal attribution_node2; attribution_node2.set_uid(2222); attribution_node2.set_tag("location2"); - std::vector attribution_nodes = {attribution_node1, attribution_node2}; + std::vector attribution_nodes = {attribution_node1, attribution_node2}; // Set up the event LogEvent event(4, 12345); diff --git a/cmds/statsd/tests/LogEntryMatcher_test.cpp b/cmds/statsd/tests/LogEntryMatcher_test.cpp index 1023ea40aa55b763d1af0767916a2114fd6634c3..2320a9d89f6b1f4d6de7881236e1672b9c9915b5 100644 --- a/cmds/statsd/tests/LogEntryMatcher_test.cpp +++ b/cmds/statsd/tests/LogEntryMatcher_test.cpp @@ -60,19 +60,19 @@ TEST(AtomMatcherTest, TestSimpleMatcher) { TEST(AtomMatcherTest, TestAttributionMatcher) { UidMap uidMap; - AttributionNode attribution_node1; + AttributionNodeInternal attribution_node1; attribution_node1.set_uid(1111); attribution_node1.set_tag("location1"); - AttributionNode attribution_node2; + AttributionNodeInternal attribution_node2; attribution_node2.set_uid(2222); attribution_node2.set_tag("location2"); - AttributionNode attribution_node3; + AttributionNodeInternal attribution_node3; attribution_node3.set_uid(3333); attribution_node3.set_tag("location3"); - std::vector attribution_nodes = - { attribution_node1, attribution_node2, attribution_node3 }; + std::vector attribution_nodes = {attribution_node1, attribution_node2, + attribution_node3}; // Set up the event LogEvent event(TAG_ID, 0); diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp index b6492150127568934163fd1cb6621dfbb39bba4a..2fcde29fbbdb487e6f401d29de2698835287dd9f 100644 --- a/cmds/statsd/tests/LogEvent_test.cpp +++ b/cmds/statsd/tests/LogEvent_test.cpp @@ -25,14 +25,14 @@ namespace statsd { TEST(LogEventTest, TestLogParsing) { LogEvent event1(1, 2000); - std::vector nodes; + std::vector nodes; - AttributionNode node1; + AttributionNodeInternal node1; node1.set_uid(1000); node1.set_tag("tag1"); nodes.push_back(node1); - AttributionNode node2; + AttributionNodeInternal node2; node2.set_uid(2000); node2.set_tag("tag2"); nodes.push_back(node2); @@ -92,17 +92,17 @@ TEST(LogEventTest, TestLogParsing) { TEST(LogEventTest, TestLogParsing2) { LogEvent event1(1, 2000); - std::vector nodes; + std::vector nodes; event1.write("hello"); // repeated msg can be in the middle - AttributionNode node1; + AttributionNodeInternal node1; node1.set_uid(1000); node1.set_tag("tag1"); nodes.push_back(node1); - AttributionNode node2; + AttributionNodeInternal node2; node2.set_uid(2000); node2.set_tag("tag2"); nodes.push_back(node2); diff --git a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp index 038d44936838390a7f18a0792e184ea71a882254..3dc3fd1160f19e55d7db2d50156b79d8c5710142 100644 --- a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp +++ b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp @@ -58,9 +58,9 @@ SimplePredicate getWakeLockHeldCondition(bool countNesting, bool defaultFalse, } void writeAttributionNodesToEvent(LogEvent* event, const std::vector &uids) { - std::vector nodes; + std::vector nodes; for (size_t i = 0; i < uids.size(); ++i) { - AttributionNode node; + AttributionNodeInternal node; node.set_uid(uids[i]); nodes.push_back(node); } diff --git a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp index 022800427b117d1a0f541d08491932fdd2ea5e9b..7a7e000fb98ff5686ffbbe33a99e7a61e55d0057 100644 --- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp @@ -75,41 +75,40 @@ TEST(AttributionE2eTest, TestAttributionMatchAndSlice) { android::String16("APP3"), 333 /* uid */, 2 /* version code*/); // GMS core node is in the middle. - std::vector attributions1 = - {CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(333, "App3")}; + std::vector attributions1 = {CreateAttribution(111, "App1"), + CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(333, "App3")}; // GMS core node is the last one. - std::vector attributions2 = - {CreateAttribution(111, "App1"), CreateAttribution(333, "App3"), - CreateAttribution(222, "GMSCoreModule1")}; + std::vector attributions2 = {CreateAttribution(111, "App1"), + CreateAttribution(333, "App3"), + CreateAttribution(222, "GMSCoreModule1")}; // GMS core node is the first one. - std::vector attributions3 = - {CreateAttribution(222, "GMSCoreModule1"), CreateAttribution(333, "App3")}; + std::vector attributions3 = {CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(333, "App3")}; // Single GMS core node. - std::vector attributions4 = - {CreateAttribution(222, "GMSCoreModule1")}; + std::vector attributions4 = {CreateAttribution(222, "GMSCoreModule1")}; // GMS core has another uid. - std::vector attributions5 = - {CreateAttribution(111, "App1"), CreateAttribution(444, "GMSCoreModule2"), - CreateAttribution(333, "App3")}; + std::vector attributions5 = {CreateAttribution(111, "App1"), + CreateAttribution(444, "GMSCoreModule2"), + CreateAttribution(333, "App3")}; // Multiple GMS core nodes. - std::vector attributions6 = - {CreateAttribution(444, "GMSCoreModule2"), CreateAttribution(222, "GMSCoreModule1")}; + std::vector attributions6 = {CreateAttribution(444, "GMSCoreModule2"), + CreateAttribution(222, "GMSCoreModule1")}; // No GMS core nodes. - std::vector attributions7 = - {CreateAttribution(111, "App1"), CreateAttribution(333, "App3")}; - std::vector attributions8 = {CreateAttribution(111, "App1")}; + std::vector attributions7 = {CreateAttribution(111, "App1"), + CreateAttribution(333, "App3")}; + std::vector attributions8 = {CreateAttribution(111, "App1")}; // GMS core node with isolated uid. const int isolatedUid = 666; - std::vector attributions9 = - {CreateAttribution(isolatedUid, "GMSCoreModule3")}; + std::vector attributions9 = { + CreateAttribution(isolatedUid, "GMSCoreModule3")}; std::vector> events; // Events 1~4 are in the 1st bucket. diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp index 4dffd13bef66e5b82a6d9b8ee7e282dbbac21fec..01348bd664aa81c0bc4f1a237d0c81251d3babdd 100644 --- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp @@ -78,13 +78,13 @@ TEST(DimensionInConditionE2eTest, TestCountMetricNoLink) { EXPECT_EQ(processor->mMetricsManagers.size(), 1u); EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); - std::vector attributions1 = {CreateAttribution(111, "App1"), - CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(222, "GMSCoreModule2")}; + std::vector attributions1 = {CreateAttribution(111, "App1"), + CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(222, "GMSCoreModule2")}; - std::vector attributions2 = {CreateAttribution(333, "App2"), - CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; + std::vector attributions2 = {CreateAttribution(333, "App2"), + CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(555, "GMSCoreModule2")}; std::vector> events; events.push_back( @@ -284,13 +284,13 @@ TEST(DimensionInConditionE2eTest, TestCountMetricWithLink) { auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey); EXPECT_EQ(processor->mMetricsManagers.size(), 1u); EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); - std::vector attributions1 = {CreateAttribution(111, "App1"), - CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(222, "GMSCoreModule2")}; + std::vector attributions1 = {CreateAttribution(111, "App1"), + CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(222, "GMSCoreModule2")}; - std::vector attributions2 = {CreateAttribution(333, "App2"), - CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; + std::vector attributions2 = {CreateAttribution(333, "App2"), + CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(555, "GMSCoreModule2")}; std::vector> events; @@ -464,13 +464,13 @@ TEST(DimensionInConditionE2eTest, TestDurationMetricNoLink) { EXPECT_EQ(processor->mMetricsManagers.size(), 1u); EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); - std::vector attributions1 = {CreateAttribution(111, "App1"), - CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(222, "GMSCoreModule2")}; + std::vector attributions1 = { + CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(222, "GMSCoreModule2")}; - std::vector attributions2 = {CreateAttribution(333, "App2"), - CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; + std::vector attributions2 = { + CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(555, "GMSCoreModule2")}; std::vector> events; @@ -629,13 +629,13 @@ TEST(DimensionInConditionE2eTest, TestDurationMetricWithLink) { EXPECT_EQ(processor->mMetricsManagers.size(), 1u); EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); - std::vector attributions1 = {CreateAttribution(111, "App1"), - CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(222, "GMSCoreModule2")}; + std::vector attributions1 = { + CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(222, "GMSCoreModule2")}; - std::vector attributions2 = {CreateAttribution(333, "App2"), - CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; + std::vector attributions2 = { + CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(555, "GMSCoreModule2")}; std::vector> events; diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp index 1b51780a59bc9e31f619ae56f185540d792c20a3..c874d92a1b019b21ae2604b3cc695c550d16b4d7 100644 --- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp @@ -134,8 +134,8 @@ TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks1) { CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 2 * bucketSizeNs - 100); - std::vector attributions = - {CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")}; + std::vector attributions = { + CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")}; auto syncOnEvent1 = CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50); auto syncOffEvent1 = @@ -249,8 +249,8 @@ TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks2) { CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 2 * bucketSizeNs - 100); - std::vector attributions = {CreateAttribution(appUid, "App1"), - CreateAttribution(appUid + 1, "GMSCoreModule1")}; + std::vector attributions = { + CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")}; auto syncOnEvent1 = CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50); auto syncOffEvent1 = CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300); diff --git a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp index efdab9822984f74274eb61997d3fdc52329dd2aa..9153795365a2081e02ad94679a600929d59a7fca 100644 --- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp @@ -60,13 +60,13 @@ StatsdConfig CreateStatsdConfig(DurationMetric::AggregationType aggregationType) return config; } -std::vector attributions1 = {CreateAttribution(111, "App1"), - CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(222, "GMSCoreModule2")}; +std::vector attributions1 = {CreateAttribution(111, "App1"), + CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(222, "GMSCoreModule2")}; -std::vector attributions2 = {CreateAttribution(111, "App2"), - CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(222, "GMSCoreModule2")}; +std::vector attributions2 = {CreateAttribution(111, "App2"), + CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(222, "GMSCoreModule2")}; /* Events: diff --git a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp index 3397f144cfbcc122b9ae1a1f172152fb6965c8f2..a164c12134b592878c23df6ede896b8dd2663118 100644 --- a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp +++ b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp @@ -204,8 +204,53 @@ TEST(MaxDurationTrackerTest, TestCrossBucketBoundary_nested) { } TEST(MaxDurationTrackerTest, TestMaxDurationWithCondition) { + const std::vector conditionKey = {key1}; + + vector dimensionInCondition; + sp wizard = new NaggyMock(); + + ConditionKey conditionKey1; + MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 1, "1"); + conditionKey1[StringToId("APP_BACKGROUND")] = conditionKey; + + /** + Start in first bucket, stop in second bucket. Condition turns on and off in the first bucket + and again turns on and off in the second bucket. + */ + uint64_t bucketStartTimeNs = 10000000000; + uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs; + uint64_t eventStartTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC; + uint64_t conditionStarts1 = bucketStartTimeNs + 11 * NS_PER_SEC; + uint64_t conditionStops1 = bucketStartTimeNs + 14 * NS_PER_SEC; + uint64_t conditionStarts2 = bucketStartTimeNs + bucketSizeNs + 5 * NS_PER_SEC; + uint64_t conditionStops2 = conditionStarts2 + 10 * NS_PER_SEC; + uint64_t eventStopTimeNs = conditionStops2 + 8 * NS_PER_SEC; + + int64_t metricId = 1; + MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + false, bucketStartTimeNs, 0, bucketStartTimeNs, bucketSizeNs, true, + {}); + EXPECT_TRUE(tracker.mAnomalyTrackers.empty()); + + tracker.noteStart(key1, false, eventStartTimeNs, conditionKey1); + tracker.noteConditionChanged(key1, true, conditionStarts1); + tracker.noteConditionChanged(key1, false, conditionStops1); + unordered_map> buckets; + tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets); + EXPECT_EQ(0U, buckets.size()); + + tracker.noteConditionChanged(key1, true, conditionStarts2); + tracker.noteConditionChanged(key1, false, conditionStops2); + tracker.noteStop(key1, eventStopTimeNs, false); + tracker.flushIfNeeded(bucketStartTimeNs + 2 * bucketSizeNs + 1, &buckets); + EXPECT_EQ(1U, buckets.size()); + vector item = buckets.begin()->second; + EXPECT_EQ(1UL, item.size()); + EXPECT_EQ(13ULL * NS_PER_SEC, item[0].mDuration); +} + +TEST(MaxDurationTrackerTest, TestAnomalyDetection) { const std::vector conditionKey = {getMockedDimensionKey(TagId, 4, "1")}; - const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1"); vector dimensionInCondition; sp wizard = new NaggyMock(); @@ -214,34 +259,149 @@ TEST(MaxDurationTrackerTest, TestMaxDurationWithCondition) { MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 2, "maps"); conditionKey1[StringToId("APP_BACKGROUND")] = conditionKey; - EXPECT_CALL(*wizard, query(_, conditionKey1, _, _)) // #4 - .WillOnce(Return(ConditionState::kFalse)); - unordered_map> buckets; uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; uint64_t bucketStartTimeNs = 10000000000; uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs; uint64_t bucketNum = 0; - uint64_t eventStartTimeNs = bucketStartTimeNs + 1; + uint64_t eventStartTimeNs = 13000000000; int64_t durationTimeNs = 2 * 1000; int64_t metricId = 1; + Alert alert; + alert.set_id(101); + alert.set_metric_id(1); + alert.set_trigger_if_sum_gt(40 * NS_PER_SEC); + alert.set_num_buckets(2); + const int32_t refPeriodSec = 45; + alert.set_refractory_period_secs(refPeriodSec); + sp anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey); MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, - true, {}); - EXPECT_TRUE(tracker.mAnomalyTrackers.empty()); + true, {anomalyTracker}); tracker.noteStart(key1, true, eventStartTimeNs, conditionKey1); + sp alarm = anomalyTracker->mAlarms.begin()->second; + EXPECT_EQ((long long)(53ULL * NS_PER_SEC), (long long)(alarm->timestampSec * NS_PER_SEC)); + + // Remove the anomaly alarm when the duration is no longer fully met. + tracker.noteConditionChanged(key1, false, eventStartTimeNs + 15 * NS_PER_SEC); + EXPECT_EQ(0U, anomalyTracker->mAlarms.size()); + + // Since the condition was off for 10 seconds, the anomaly should trigger 10 sec later. + tracker.noteConditionChanged(key1, true, eventStartTimeNs + 25 * NS_PER_SEC); + EXPECT_EQ(1U, anomalyTracker->mAlarms.size()); + alarm = anomalyTracker->mAlarms.begin()->second; + EXPECT_EQ((long long)(63ULL * NS_PER_SEC), (long long)(alarm->timestampSec * NS_PER_SEC)); +} + +// This tests that we correctly compute the predicted time of an anomaly assuming that the current +// state continues forward as-is. +TEST(MaxDurationTrackerTest, TestAnomalyPredictedTimestamp) { + const std::vector conditionKey = {getMockedDimensionKey(TagId, 4, "1")}; - tracker.onSlicedConditionMayChange(eventStartTimeNs + 5); + vector dimensionInCondition; + sp wizard = new NaggyMock(); - tracker.noteStop(key1, eventStartTimeNs + durationTimeNs, false); + ConditionKey conditionKey1; + MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 2, "maps"); + conditionKey1[StringToId("APP_BACKGROUND")] = conditionKey; + ConditionKey conditionKey2; + conditionKey2[StringToId("APP_BACKGROUND")] = {getMockedDimensionKey(TagId, 4, "2")}; - tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets); - EXPECT_TRUE(buckets.find(eventKey) != buckets.end()); - EXPECT_EQ(1u, buckets[eventKey].size()); - EXPECT_EQ(5ULL, buckets[eventKey][0].mDuration); + unordered_map> buckets; + + /** + * Suppose we have two sub-dimensions that we're taking the MAX over. In the first of these + * nested dimensions, we enter the pause state after 3 seconds. When we resume, the second + * dimension has already been running for 4 seconds. Thus, we have 40-4=36 seconds remaining + * before we trigger the anomaly. + */ + uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; + uint64_t bucketStartTimeNs = 10000000000; + uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs; + uint64_t bucketNum = 0; + uint64_t eventStartTimeNs = bucketStartTimeNs + 5 * NS_PER_SEC; // Condition is off at start. + uint64_t conditionStarts1 = bucketStartTimeNs + 11 * NS_PER_SEC; + uint64_t conditionStops1 = bucketStartTimeNs + 14 * NS_PER_SEC; + uint64_t conditionStarts2 = bucketStartTimeNs + 20 * NS_PER_SEC; + uint64_t eventStartTimeNs2 = conditionStarts2 - 4 * NS_PER_SEC; + + int64_t metricId = 1; + Alert alert; + alert.set_id(101); + alert.set_metric_id(1); + alert.set_trigger_if_sum_gt(40 * NS_PER_SEC); + alert.set_num_buckets(2); + const int32_t refPeriodSec = 45; + alert.set_refractory_period_secs(refPeriodSec); + sp anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey); + MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, + true, {anomalyTracker}); + + tracker.noteStart(key1, false, eventStartTimeNs, conditionKey1); + tracker.noteConditionChanged(key1, true, conditionStarts1); + tracker.noteConditionChanged(key1, false, conditionStops1); + tracker.noteStart(key2, true, eventStartTimeNs2, conditionKey2); // Condition is on already. + tracker.noteConditionChanged(key1, true, conditionStarts2); + EXPECT_EQ(1U, anomalyTracker->mAlarms.size()); + auto alarm = anomalyTracker->mAlarms.begin()->second; + EXPECT_EQ(conditionStarts2 + 36 * NS_PER_SEC, + (unsigned long long)(alarm->timestampSec * NS_PER_SEC)); +} + +// Suppose that within one tracker there are two dimensions A and B. +// Suppose A starts, then B starts, and then A stops. We still need to set an anomaly based on the +// elapsed duration of B. +TEST(MaxDurationTrackerTest, TestAnomalyPredictedTimestamp_UpdatedOnStop) { + const std::vector conditionKey = {getMockedDimensionKey(TagId, 4, "1")}; + + vector dimensionInCondition; + sp wizard = new NaggyMock(); + + ConditionKey conditionKey1; + MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 2, "maps"); + conditionKey1[StringToId("APP_BACKGROUND")] = conditionKey; + ConditionKey conditionKey2; + conditionKey2[StringToId("APP_BACKGROUND")] = {getMockedDimensionKey(TagId, 4, "2")}; + + unordered_map> buckets; + + /** + * Suppose we have two sub-dimensions that we're taking the MAX over. In the first of these + * nested dimensions, are started for 8 seconds. When we stop, the other nested dimension has + * been started for 5 seconds. So we can only allow 35 more seconds from now. + */ + uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; + uint64_t bucketStartTimeNs = 10000000000; + uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs; + uint64_t bucketNum = 0; + uint64_t eventStartTimeNs1 = bucketStartTimeNs + 5 * NS_PER_SEC; // Condition is off at start. + uint64_t eventStopTimeNs1 = bucketStartTimeNs + 13 * NS_PER_SEC; + uint64_t eventStartTimeNs2 = bucketStartTimeNs + 8 * NS_PER_SEC; + + int64_t metricId = 1; + Alert alert; + alert.set_id(101); + alert.set_metric_id(1); + alert.set_trigger_if_sum_gt(40 * NS_PER_SEC); + alert.set_num_buckets(2); + const int32_t refPeriodSec = 45; + alert.set_refractory_period_secs(refPeriodSec); + sp anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey); + MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, + true, {anomalyTracker}); + + tracker.noteStart(key1, true, eventStartTimeNs1, conditionKey1); + tracker.noteStart(key2, true, eventStartTimeNs2, conditionKey2); + tracker.noteStop(key1, eventStopTimeNs1, false); + EXPECT_EQ(1U, anomalyTracker->mAlarms.size()); + auto alarm = anomalyTracker->mAlarms.begin()->second; + EXPECT_EQ(eventStopTimeNs1 + 35 * NS_PER_SEC, + (unsigned long long)(alarm->timestampSec * NS_PER_SEC)); } } // namespace statsd diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp index b7acef75fafb05b25c3bd4cfb237cf4666f6385e..7568348108c40e7f5813d678cf9b7731b20c5811 100644 --- a/cmds/statsd/tests/statsd_test_util.cpp +++ b/cmds/statsd/tests/statsd_test_util.cpp @@ -291,8 +291,8 @@ std::unique_ptr CreateScreenBrightnessChangedEvent( } std::unique_ptr CreateWakelockStateChangedEvent( - const std::vector& attributions, const string& wakelockName, - const WakelockStateChanged::State state, uint64_t timestampNs) { + const std::vector& attributions, const string& wakelockName, + const WakelockStateChanged::State state, uint64_t timestampNs) { auto event = std::make_unique(android::util::WAKELOCK_STATE_CHANGED, timestampNs); event->write(attributions); event->write(android::os::WakeLockLevelEnum::PARTIAL_WAKE_LOCK); @@ -303,15 +303,15 @@ std::unique_ptr CreateWakelockStateChangedEvent( } std::unique_ptr CreateAcquireWakelockEvent( - const std::vector& attributions, - const string& wakelockName, uint64_t timestampNs) { + const std::vector& attributions, const string& wakelockName, + uint64_t timestampNs) { return CreateWakelockStateChangedEvent( attributions, wakelockName, WakelockStateChanged::ACQUIRE, timestampNs); } std::unique_ptr CreateReleaseWakelockEvent( - const std::vector& attributions, - const string& wakelockName, uint64_t timestampNs) { + const std::vector& attributions, const string& wakelockName, + uint64_t timestampNs) { return CreateWakelockStateChangedEvent( attributions, wakelockName, WakelockStateChanged::RELEASE, timestampNs); } @@ -339,8 +339,8 @@ std::unique_ptr CreateMoveToForegroundEvent(const int uid, uint64_t ti } std::unique_ptr CreateSyncStateChangedEvent( - const std::vector& attributions, - const string& name, const SyncStateChanged::State state, uint64_t timestampNs) { + const std::vector& attributions, const string& name, + const SyncStateChanged::State state, uint64_t timestampNs) { auto event = std::make_unique(android::util::SYNC_STATE_CHANGED, timestampNs); event->write(attributions); event->write(name); @@ -350,12 +350,14 @@ std::unique_ptr CreateSyncStateChangedEvent( } std::unique_ptr CreateSyncStartEvent( - const std::vector& attributions, const string& name, uint64_t timestampNs){ + const std::vector& attributions, const string& name, + uint64_t timestampNs) { return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::ON, timestampNs); } std::unique_ptr CreateSyncEndEvent( - const std::vector& attributions, const string& name, uint64_t timestampNs) { + const std::vector& attributions, const string& name, + uint64_t timestampNs) { return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::OFF, timestampNs); } @@ -396,8 +398,8 @@ sp CreateStatsLogProcessor(const long timeBaseSec, const Stat return processor; } -AttributionNode CreateAttribution(const int& uid, const string& tag) { - AttributionNode attribution; +AttributionNodeInternal CreateAttribution(const int& uid, const string& tag) { + AttributionNodeInternal attribution; attribution.set_uid(uid); attribution.set_tag(tag); return attribution; diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h index 5d83ed7c1666048db91697dd683bda00cda8f814..1708cc31bf14f8ce7447787ee2eeaf31897895c7 100644 --- a/cmds/statsd/tests/statsd_test_util.h +++ b/cmds/statsd/tests/statsd_test_util.h @@ -15,10 +15,11 @@ #pragma once #include +#include "frameworks/base/cmds/statsd/src/stats_log.pb.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" -#include "statslog.h" -#include "src/logd/LogEvent.h" #include "src/StatsLogProcessor.h" +#include "src/logd/LogEvent.h" +#include "statslog.h" namespace android { namespace os { @@ -119,11 +120,13 @@ std::unique_ptr CreateMoveToForegroundEvent(const int uid, uint64_t ti // Create log event when the app sync starts. std::unique_ptr CreateSyncStartEvent( - const std::vector& attributions, const string& name, uint64_t timestampNs); + const std::vector& attributions, const string& name, + uint64_t timestampNs); // Create log event when the app sync ends. std::unique_ptr CreateSyncEndEvent( - const std::vector& attributions, const string& name, uint64_t timestampNs); + const std::vector& attributions, const string& name, + uint64_t timestampNs); // Create log event when the app sync ends. std::unique_ptr CreateAppCrashEvent( @@ -131,20 +134,20 @@ std::unique_ptr CreateAppCrashEvent( // Create log event for acquiring wakelock. std::unique_ptr CreateAcquireWakelockEvent( - const std::vector& attributions, - const string& wakelockName, uint64_t timestampNs); + const std::vector& attributions, const string& wakelockName, + uint64_t timestampNs); // Create log event for releasing wakelock. std::unique_ptr CreateReleaseWakelockEvent( - const std::vector& attributions, - const string& wakelockName, uint64_t timestampNs); + const std::vector& attributions, const string& wakelockName, + uint64_t timestampNs); // Create log event for releasing wakelock. std::unique_ptr CreateIsolatedUidChangedEvent( int isolatedUid, int hostUid, bool is_create, uint64_t timestampNs); -// Helper function to create an AttributionNode proto. -AttributionNode CreateAttribution(const int& uid, const string& tag); +// Helper function to create an AttributionNodeInternal proto. +AttributionNodeInternal CreateAttribution(const int& uid, const string& tag); // Create a statsd log event processor upon the start time in seconds, config and key. sp CreateStatsLogProcessor(const long timeBaseSec, const StatsdConfig& config, diff --git a/cmds/statsd/tools/Android.mk b/cmds/statsd/tools/Android.mk index faf2d2c7d4e7eefc9bf9bbc35d280d6e87e64f43..7253c9637026b930ba5246662dd1cfd1e712f35d 100644 --- a/cmds/statsd/tools/Android.mk +++ b/cmds/statsd/tools/Android.mk @@ -16,5 +16,5 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -# Include the sub-makefiles +#Include the sub-makefiles include $(call all-makefiles-under,$(LOCAL_PATH)) \ No newline at end of file diff --git a/cmds/statsd/tools/dogfood/Android.mk b/cmds/statsd/tools/dogfood/Android.mk index a65095f4188d56ea00f2628d935dc2f8786c14ed..c7e4c7b717937c50cd92e8e387c15f8bc54a5791 100644 --- a/cmds/statsd/tools/dogfood/Android.mk +++ b/cmds/statsd/tools/dogfood/Android.mk @@ -24,7 +24,6 @@ LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res LOCAL_STATIC_JAVA_LIBRARIES := platformprotoslite \ statsdprotolite -LOCAL_PROTOC_OPTIMIZE_TYPE := lite LOCAL_PRIVILEGED_MODULE := true LOCAL_DEX_PREOPT := false LOCAL_CERTIFICATE := platform diff --git a/cmds/statsd/tools/loadtest/Android.mk b/cmds/statsd/tools/loadtest/Android.mk index f5722c2c3d19a12e34dc709dc861ed6b6358088f..091f184ad3046ffc4c4d865fe08ab5ed74b17063 100644 --- a/cmds/statsd/tools/loadtest/Android.mk +++ b/cmds/statsd/tools/loadtest/Android.mk @@ -19,15 +19,11 @@ include $(CLEAR_VARS) LOCAL_PACKAGE_NAME := StatsdLoadtest LOCAL_SRC_FILES := $(call all-java-files-under, src) -LOCAL_SRC_FILES += ../../src/stats_log.proto \ - ../../src/atoms.proto \ - ../../src/perfetto/perfetto_config.proto \ - ../../src/statsd_config.proto -LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/../../src/ + LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res -LOCAL_STATIC_JAVA_LIBRARIES := platformprotoslite +LOCAL_STATIC_JAVA_LIBRARIES := platformprotoslite \ + statsdprotolite -LOCAL_PROTOC_OPTIMIZE_TYPE := lite LOCAL_CERTIFICATE := platform LOCAL_PRIVILEGED_MODULE := true LOCAL_DEX_PREOPT := false diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java index bed4d980969230bf48aa7441be7b671301888756..a12def0db9fb71139be1a190a6d08ae88fc3c640 100644 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java +++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java @@ -50,7 +50,7 @@ import android.widget.Toast; import com.android.os.StatsLog.ConfigMetricsReport; import com.android.os.StatsLog.ConfigMetricsReportList; -import com.android.os.StatsLog.StatsdStatsReport; +import com.android.os.StatsLogCommon.StatsdStatsReport; import com.android.internal.os.StatsdConfigProto.TimeUnit; import java.util.ArrayList; diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/StatsdStatsRecorder.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/StatsdStatsRecorder.java index e63150f95316cca414e1c22a08a0a4b65b70bdf1..58cbcd89581e59ea08a41862f4fd145e3d267a86 100644 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/StatsdStatsRecorder.java +++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/StatsdStatsRecorder.java @@ -16,11 +16,8 @@ package com.android.statsd.loadtest; import android.content.Context; -import android.util.Log; -import com.android.os.StatsLog.StatsdStatsReport; +import com.android.os.StatsLogCommon.StatsdStatsReport; import com.android.internal.os.StatsdConfigProto.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; public class StatsdStatsRecorder extends PerfDataRecorder { private static final String TAG = "loadtest.StatsdStatsRecorder"; diff --git a/cmds/webview_zygote/Android.mk b/cmds/webview_zygote/Android.mk deleted file mode 100644 index 955e58ed933b9c2b0c36c5f316514df2fd6e39d1..0000000000000000000000000000000000000000 --- a/cmds/webview_zygote/Android.mk +++ /dev/null @@ -1,51 +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. -# - -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE := webview_zygote - -LOCAL_SRC_FILES := webview_zygote.cpp - -LOCAL_CFLAGS := -Wall -Werror - -LOCAL_SHARED_LIBRARIES := \ - libandroid_runtime \ - libbinder \ - liblog \ - libcutils \ - libutils - -LOCAL_LDFLAGS_32 := -Wl,--version-script,art/sigchainlib/version-script32.txt -Wl,--export-dynamic -LOCAL_LDFLAGS_64 := -Wl,--version-script,art/sigchainlib/version-script64.txt -Wl,--export-dynamic - -LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain - -LOCAL_INIT_RC := webview_zygote32.rc - -# Always include the 32-bit version of webview_zygote. If the target is 64-bit, -# also include the 64-bit webview_zygote. -ifeq ($(TARGET_SUPPORTS_64_BIT_APPS),true) - LOCAL_INIT_RC += webview_zygote64.rc -endif - -LOCAL_MULTILIB := both - -LOCAL_MODULE_STEM_32 := webview_zygote32 -LOCAL_MODULE_STEM_64 := webview_zygote64 - -include $(BUILD_EXECUTABLE) diff --git a/cmds/webview_zygote/webview_zygote.cpp b/cmds/webview_zygote/webview_zygote.cpp deleted file mode 100644 index 88fee645b3eec98612486d42c0e87e3ccbeaaa00..0000000000000000000000000000000000000000 --- a/cmds/webview_zygote/webview_zygote.cpp +++ /dev/null @@ -1,76 +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. - */ - - -#define LOG_TAG "WebViewZygote" - -#include - -#include -#include -#include -#include -#include -#include - -namespace android { - -class WebViewRuntime : public AndroidRuntime { -public: - WebViewRuntime(char* argBlockStart, size_t argBlockSize) - : AndroidRuntime(argBlockStart, argBlockSize) {} - - ~WebViewRuntime() override {} - - void onStarted() override { - // Nothing to do since this is a zygote server. - } - - void onVmCreated(JNIEnv*) override { - // Nothing to do when the VM is created in the zygote. - } - - void onZygoteInit() override { - // Called after a new process is forked. - sp proc = ProcessState::self(); - proc->startThreadPool(); - } - - void onExit(int code) override { - IPCThreadState::self()->stopProcess(); - AndroidRuntime::onExit(code); - } -}; - -} // namespace android - -int main(int argc, char* const argv[]) { - if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) { - LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno)); - return 12; - } - - size_t argBlockSize = 0; - for (int i = 0; i < argc; ++i) { - argBlockSize += strlen(argv[i]) + 1; - } - - android::WebViewRuntime runtime(argv[0], argBlockSize); - runtime.addOption("-Xzygote"); - - android::Vector args; - runtime.start("com.android.internal.os.WebViewZygoteInit", args, /*zygote=*/ true); -} diff --git a/cmds/webview_zygote/webview_zygote32.rc b/cmds/webview_zygote/webview_zygote32.rc deleted file mode 100644 index b7decc8eba3b198de050f636a39b490d712e8f5f..0000000000000000000000000000000000000000 --- a/cmds/webview_zygote/webview_zygote32.rc +++ /dev/null @@ -1,22 +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. -# - -service webview_zygote32 /system/bin/webview_zygote32 - user webview_zygote - socket webview_zygote stream 660 webview_zygote system - -on property:init.svc.zygote=stopped - stop webview_zygote32 diff --git a/cmds/webview_zygote/webview_zygote64.rc b/cmds/webview_zygote/webview_zygote64.rc deleted file mode 100644 index 2935b28cff550d8e3879942c67123045a2720130..0000000000000000000000000000000000000000 --- a/cmds/webview_zygote/webview_zygote64.rc +++ /dev/null @@ -1,22 +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. -# - -service webview_zygote64 /system/bin/webview_zygote64 - user webview_zygote - socket webview_zygote stream 660 webview_zygote system - -on property:init.svc.zygote=stopped - stop webview_zygote64 diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt index a7d07e3417284b70ee7e3ed5f494a89f1c923718..752b662e050dc5f53dda5c1e5ebb38e6a403efa2 100644 --- a/config/hiddenapi-light-greylist.txt +++ b/config/hiddenapi-light-greylist.txt @@ -78,8 +78,10 @@ Landroid/app/ActivityThread;->getProcessName()Ljava/lang/String; Landroid/app/ActivityThread;->getSystemContext()Landroid/app/ContextImpl; Landroid/app/ActivityThread$H;->BIND_SERVICE:I Landroid/app/ActivityThread$H;->CREATE_SERVICE:I +Landroid/app/ActivityThread$H;->DUMP_PROVIDER:I Landroid/app/ActivityThread$H;->EXIT_APPLICATION:I Landroid/app/ActivityThread$H;->GC_WHEN_IDLE:I +Landroid/app/ActivityThread$H;->INSTALL_PROVIDER:I Landroid/app/ActivityThread$H;->RECEIVER:I Landroid/app/ActivityThread$H;->REMOVE_PROVIDER:I Landroid/app/ActivityThread$H;->SERVICE_ARGS:I @@ -278,8 +280,10 @@ Landroid/app/IUiModeManager$Stub$Proxy;->(Landroid/os/IBinder;)V Landroid/app/IWallpaperManager;->getWallpaper(Ljava/lang/String;Landroid/app/IWallpaperManagerCallback;ILandroid/os/Bundle;I)Landroid/os/ParcelFileDescriptor; Landroid/app/job/IJobScheduler$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/job/IJobScheduler; Landroid/app/job/IJobScheduler$Stub$Proxy;->(Landroid/os/IBinder;)V +Landroid/app/LoadedApk;->getAssets()Landroid/content/res/AssetManager; Landroid/app/LoadedApk;->getClassLoader()Ljava/lang/ClassLoader; Landroid/app/LoadedApk;->getDataDirFile()Ljava/io/File; +Landroid/app/LoadedApk;->getResources()Landroid/content/res/Resources; Landroid/app/LoadedApk;->mActivityThread:Landroid/app/ActivityThread; Landroid/app/LoadedApk;->makeApplication(ZLandroid/app/Instrumentation;)Landroid/app/Application; Landroid/app/LoadedApk;->mAppDir:Ljava/lang/String; @@ -295,6 +299,7 @@ Landroid/app/LoadedApk;->mReceivers:Landroid/util/ArrayMap; Landroid/app/LoadedApk;->mResDir:Ljava/lang/String; Landroid/app/LoadedApk;->mResources:Landroid/content/res/Resources; Landroid/app/LoadedApk;->mSplitResDirs:[Ljava/lang/String; +Landroid/app/LoadedApk;->rewriteRValues(Ljava/lang/ClassLoader;Ljava/lang/String;I)V Landroid/app/LocalActivityManager;->mActivities:Ljava/util/Map; Landroid/app/LocalActivityManager;->mActivityArray:Ljava/util/ArrayList; Landroid/app/NativeActivity;->hideIme(I)V @@ -560,6 +565,7 @@ Landroid/content/res/ColorStateList$ColorStateListFactory;->(Landroid/cont Landroid/content/res/ColorStateList;->mColors:[I Landroid/content/res/ColorStateList;->mDefaultColor:I Landroid/content/res/ColorStateList;->mFactory:Landroid/content/res/ColorStateList$ColorStateListFactory; +Landroid/content/res/CompatibilityInfo;->applicationScale:F Landroid/content/res/CompatibilityInfo;->DEFAULT_COMPATIBILITY_INFO:Landroid/content/res/CompatibilityInfo; Landroid/content/res/DrawableCache;->getInstance(JLandroid/content/res/Resources;Landroid/content/res/Resources$Theme;)Landroid/graphics/drawable/Drawable; Landroid/content/res/ObbInfo;->salt:[B @@ -1685,10 +1691,12 @@ Landroid/view/accessibility/IAccessibilityManager$Stub;->asInterface(Landroid/os Landroid/view/accessibility/IAccessibilityManager$Stub$Proxy;->(Landroid/os/IBinder;)V Landroid/view/ActionMode;->isUiFocusable()Z Landroid/view/animation/Animation;->mListener:Landroid/view/animation/Animation$AnimationListener; +Landroid/view/Choreographer$CallbackQueue;->addCallbackLocked(JLjava/lang/Object;Ljava/lang/Object;)V Landroid/view/Choreographer;->doFrame(JI)V Landroid/view/Choreographer;->getFrameTime()J 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 @@ -1816,7 +1824,7 @@ Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;- Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionModified(IILandroid/view/textclassifier/TextSelection;)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent; Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionStarted(I)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent; Landroid/view/textservice/TextServicesManager;->isSpellCheckerEnabled()Z -Landroid/view/TextureView;->mLayer:Landroid/view/HardwareLayer; +Landroid/view/TextureView;->mLayer:Landroid/view/TextureLayer; Landroid/view/TextureView;->mNativeWindow:J Landroid/view/TextureView;->mSurface:Landroid/graphics/SurfaceTexture; Landroid/view/TextureView;->mUpdateListener:Landroid/graphics/SurfaceTexture$OnFrameAvailableListener; @@ -2397,11 +2405,45 @@ Lcom/android/okhttp/OkHttpClient;->dns:Lcom/android/okhttp/Dns; Lcom/android/okhttp/OkHttpClient;->setProtocols(Ljava/util/List;)Lcom/android/okhttp/OkHttpClient; Lcom/android/okhttp/okio/ByteString;->readObject(Ljava/io/ObjectInputStream;)V Lcom/android/okhttp/okio/ByteString;->writeObject(Ljava/io/ObjectOutputStream;)V +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; +Lcom/android/org/conscrypt/AbstractConscryptSocket;->getChannelId()[B +Lcom/android/org/conscrypt/AbstractConscryptSocket;->getHandshakeApplicationProtocol()Ljava/lang/String; +Lcom/android/org/conscrypt/AbstractConscryptSocket;->getHostname()Ljava/lang/String; +Lcom/android/org/conscrypt/AbstractConscryptSocket;->getHostnameOrIP()Ljava/lang/String; +Lcom/android/org/conscrypt/AbstractConscryptSocket;->getNpnSelectedProtocol()[B +Lcom/android/org/conscrypt/AbstractConscryptSocket;->getSoWriteTimeout()I +Lcom/android/org/conscrypt/AbstractConscryptSocket;->setAlpnProtocols([Ljava/lang/String;)V +Lcom/android/org/conscrypt/AbstractConscryptSocket;->setAlpnProtocols([B)V +Lcom/android/org/conscrypt/AbstractConscryptSocket;->setApplicationProtocols([Ljava/lang/String;)V +Lcom/android/org/conscrypt/AbstractConscryptSocket;->setChannelIdEnabled(Z)V +Lcom/android/org/conscrypt/AbstractConscryptSocket;->setChannelIdPrivateKey(Ljava/security/PrivateKey;)V +Lcom/android/org/conscrypt/AbstractConscryptSocket;->setHandshakeTimeout(I)V +Lcom/android/org/conscrypt/AbstractConscryptSocket;->setHostname(Ljava/lang/String;)V +Lcom/android/org/conscrypt/AbstractConscryptSocket;->setNpnProtocols([B)V +Lcom/android/org/conscrypt/AbstractConscryptSocket;->setSoWriteTimeout(I)V +Lcom/android/org/conscrypt/AbstractConscryptSocket;->setUseSessionTickets(Z)V +Lcom/android/org/conscrypt/ConscryptSocketBase;->getHostname()Ljava/lang/String; +Lcom/android/org/conscrypt/ConscryptSocketBase;->getHostnameOrIP()Ljava/lang/String; +Lcom/android/org/conscrypt/ConscryptSocketBase;->getSoWriteTimeout()I +Lcom/android/org/conscrypt/ConscryptSocketBase;->setHandshakeTimeout(I)V +Lcom/android/org/conscrypt/ConscryptSocketBase;->setHostname(Ljava/lang/String;)V +Lcom/android/org/conscrypt/ConscryptSocketBase;->setSoWriteTimeout(I)V Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getAlpnSelectedProtocol()[B +Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getChannelId()[B +Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getHostname()Ljava/lang/String; +Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getHostnameOrIP()Ljava/lang/String; Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getNpnSelectedProtocol()[B +Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getSoWriteTimeout()I +Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setAlpnProtocols([Ljava/lang/String;)V Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setAlpnProtocols([B)V +Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setChannelIdEnabled(Z)V +Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setChannelIdPrivateKey(Ljava/security/PrivateKey;)V +Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setHandshakeTimeout(I)V Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setHostname(Ljava/lang/String;)V Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setNpnProtocols([B)V +Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setSoWriteTimeout(I)V Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setUseSessionTickets(Z)V Lcom/android/org/conscrypt/TrustManagerImpl;->(Ljava/security/KeyStore;)V Ldalvik/system/BaseDexClassLoader;->getLdLibraryPath()Ljava/lang/String; diff --git a/config/preloaded-classes b/config/preloaded-classes index 784c3f8782ee4abe2beebaa5accded7943f7de88..95c2b2c45de10dbbe27b9eaf1100bb5ac22aded5 100644 --- a/config/preloaded-classes +++ b/config/preloaded-classes @@ -2289,7 +2289,7 @@ android.view.GestureDetector$SimpleOnGestureListener android.view.Gravity android.view.HandlerActionQueue android.view.HandlerActionQueue$HandlerAction -android.view.HardwareLayer +android.view.TextureLayer android.view.IGraphicsStats android.view.IGraphicsStats$Stub android.view.IGraphicsStats$Stub$Proxy diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 83fe4dd0038a57a96eb87169b62c79f5342d969d..3d04e2c64bee2cd492204de0aefdce77946f837b 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -751,6 +751,14 @@ public class Activity extends ContextThemeWrapper private static final String KEYBOARD_SHORTCUTS_RECEIVER_PKG_NAME = "com.android.systemui"; + private static final int LOG_AM_ON_CREATE_CALLED = 30057; + private static final int LOG_AM_ON_START_CALLED = 30059; + private static final int LOG_AM_ON_RESUME_CALLED = 30022; + private static final int LOG_AM_ON_PAUSE_CALLED = 30021; + private static final int LOG_AM_ON_STOP_CALLED = 30049; + private static final int LOG_AM_ON_RESTART_CALLED = 30058; + private static final int LOG_AM_ON_DESTROY_CALLED = 30060; + private static class ManagedDialog { Dialog mDialog; Bundle mArgs; @@ -1392,6 +1400,7 @@ public class Activity extends ContextThemeWrapper * * {@hide} */ + @Override public int getNextAutofillId() { if (mLastAutofillId == Integer.MAX_VALUE - 1) { mLastAutofillId = View.LAST_APP_AUTOFILL_ID; @@ -1402,6 +1411,14 @@ public class Activity extends ContextThemeWrapper return mLastAutofillId; } + /** + * @hide + */ + @Override + public AutofillId autofillClientGetNextAutofillId() { + return new AutofillId(getNextAutofillId()); + } + /** * Check whether this activity is running as part of a voice interaction with the user. * If true, it should perform its interaction with the user through the @@ -4144,9 +4161,10 @@ public class Activity extends ContextThemeWrapper *

You can override this function to force global search, e.g. in response to a dedicated * search key, or to block search entirely (by simply returning false). * - *

Note: when running in a {@link Configuration#UI_MODE_TYPE_TELEVISION}, the default - * implementation changes to simply return false and you must supply your own custom - * implementation if you want to support search.

+ *

Note: when running in a {@link Configuration#UI_MODE_TYPE_TELEVISION} or + * {@link Configuration#UI_MODE_TYPE_WATCH}, the default implementation changes to simply + * return false and you must supply your own custom implementation if you want to support + * search. * * @param searchEvent The {@link SearchEvent} that signaled this search. * @return Returns {@code true} if search launched, and {@code false} if the activity does @@ -4166,8 +4184,10 @@ public class Activity extends ContextThemeWrapper * @see #onSearchRequested(SearchEvent) */ public boolean onSearchRequested() { - if ((getResources().getConfiguration().uiMode&Configuration.UI_MODE_TYPE_MASK) - != Configuration.UI_MODE_TYPE_TELEVISION) { + final int uiMode = getResources().getConfiguration().uiMode + & Configuration.UI_MODE_TYPE_MASK; + if (uiMode != Configuration.UI_MODE_TYPE_TELEVISION + && uiMode != Configuration.UI_MODE_TYPE_WATCH) { startSearch(null, false, null, false); return true; } else { @@ -4196,6 +4216,9 @@ public class Activity extends ContextThemeWrapper * is to inject specific data such as context data, it is preferred to override * onSearchRequested(), so that any callers to it will benefit from the override. * + *

Note: when running in a {@link Configuration#UI_MODE_TYPE_WATCH}, use of this API is + * not supported. + * * @param initialQuery Any non-null non-empty string will be inserted as * pre-entered text in the search query box. * @param selectInitialQuery If true, the initial query will be preselected, which means that @@ -5553,13 +5576,7 @@ public class Activity extends ContextThemeWrapper if (mParent != null) { throw new IllegalStateException("Can only be called on top-level activity"); } - if (Looper.myLooper() != mMainThread.getLooper()) { - throw new IllegalStateException("Must be called from main thread"); - } - try { - ActivityManager.getService().requestActivityRelaunch(mToken); - } catch (RemoteException e) { - } + mMainThread.handleRelaunchActivityLocally(mToken); } /** @@ -7103,6 +7120,7 @@ public class Activity extends ContextThemeWrapper } else { onCreate(icicle); } + writeEventLog(LOG_AM_ON_CREATE_CALLED, "performCreate"); mActivityTransitionState.readState(icicle); mVisibleFromClient = !mWindow.getWindowStyle().getBoolean( @@ -7116,12 +7134,14 @@ public class Activity extends ContextThemeWrapper onNewIntent(intent); } - final void performStart() { + final void performStart(String reason) { mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions()); mFragments.noteStateNotSaved(); mCalled = false; mFragments.execPendingActions(); mInstrumentation.callActivityOnStart(this); + writeEventLog(LOG_AM_ON_START_CALLED, reason); + if (!mCalled) { throw new SuperNotCalledException( "Activity " + mComponent.toShortString() + @@ -7190,7 +7210,7 @@ public class Activity extends ContextThemeWrapper * The option to not start immediately is needed in case a transaction with * multiple lifecycle transitions is in progress. */ - final void performRestart(boolean start) { + final void performRestart(boolean start, String reason) { mCanEnterPictureInPicture = true; mFragments.noteStateNotSaved(); @@ -7223,19 +7243,20 @@ public class Activity extends ContextThemeWrapper mCalled = false; mInstrumentation.callActivityOnRestart(this); + writeEventLog(LOG_AM_ON_RESTART_CALLED, reason); if (!mCalled) { throw new SuperNotCalledException( "Activity " + mComponent.toShortString() + " did not call through to super.onRestart()"); } if (start) { - performStart(); + performStart(reason); } } } - final void performResume(boolean followedByPause) { - performRestart(true /* start */); + final void performResume(boolean followedByPause, String reason) { + performRestart(true /* start */, reason); mFragments.execPendingActions(); @@ -7254,6 +7275,7 @@ public class Activity extends ContextThemeWrapper mCalled = false; // mResumed is set by the instrumentation mInstrumentation.callActivityOnResume(this); + writeEventLog(LOG_AM_ON_RESUME_CALLED, reason); if (!mCalled) { throw new SuperNotCalledException( "Activity " + mComponent.toShortString() + @@ -7290,6 +7312,7 @@ public class Activity extends ContextThemeWrapper mFragments.dispatchPause(); mCalled = false; onPause(); + writeEventLog(LOG_AM_ON_PAUSE_CALLED, "performPause"); mResumed = false; if (!mCalled && getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.GINGERBREAD) { @@ -7297,7 +7320,6 @@ public class Activity extends ContextThemeWrapper "Activity " + mComponent.toShortString() + " did not call through to super.onPause()"); } - mResumed = false; } final void performUserLeaving() { @@ -7305,7 +7327,7 @@ public class Activity extends ContextThemeWrapper onUserLeaveHint(); } - final void performStop(boolean preserveWindow) { + final void performStop(boolean preserveWindow, String reason) { mDoReportFullyDrawn = false; mFragments.doLoaderStop(mChangingConfigurations /*retain*/); @@ -7328,6 +7350,7 @@ public class Activity extends ContextThemeWrapper mCalled = false; mInstrumentation.callActivityOnStop(this); + writeEventLog(LOG_AM_ON_STOP_CALLED, reason); if (!mCalled) { throw new SuperNotCalledException( "Activity " + mComponent.toShortString() + @@ -7355,6 +7378,7 @@ public class Activity extends ContextThemeWrapper mWindow.destroy(); mFragments.dispatchDestroy(); onDestroy(); + writeEventLog(LOG_AM_ON_DESTROY_CALLED, "performDestroy"); mFragments.doLoaderDestroy(); if (mVoiceInteractor != null) { mVoiceInteractor.detachActivity(); @@ -7613,6 +7637,19 @@ public class Activity extends ContextThemeWrapper return !wasShowing && mAutofillPopupWindow.isShowing(); } + /** @hide */ + @Override + public final void autofillClientDispatchUnhandledKey(@NonNull View anchor, + @NonNull KeyEvent keyEvent) { + ViewRootImpl rootImpl = anchor.getViewRootImpl(); + if (rootImpl != null) { + // dont care if anchorView is current focus, for example a custom view may only receive + // touchEvent, not focusable but can still trigger autofill window. The Key handling + // might be inside parent of the custom view. + rootImpl.dispatchKeyFromAutofill(keyEvent); + } + } + /** @hide */ @Override public final boolean autofillClientRequestHideFillUi() { @@ -7730,7 +7767,7 @@ public class Activity extends ContextThemeWrapper /** @hide */ @Override - public final boolean autofillIsCompatibilityModeEnabled() { + public final boolean autofillClientIsCompatibilityModeEnabled() { return isAutofillCompatibilityEnabled(); } @@ -7829,6 +7866,12 @@ public class Activity extends ContextThemeWrapper } } + /** Log a lifecycle event for current user id and component class. */ + private void writeEventLog(int event, String reason) { + EventLog.writeEvent(event, UserHandle.myUserId(), getComponentName().getClassName(), + reason); + } + class HostCallbacks extends FragmentHostCallback { public HostCallbacks() { super(Activity.this /*activity*/); diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 0c98267cfd68f3201a409c56d00ac42f24d19d28..feeb0f23e751bed75d8901cfe8ad4eba3acb3f5b 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -154,8 +154,8 @@ public abstract class ActivityManagerInternal { * Callback for window manager to let activity manager know that we are finally starting the * app transition; * - * @param reasons A map from stack id to a reason integer why the transition was started,, which - * must be one of the APP_TRANSITION_* values. + * @param reasons A map from windowing mode to a reason integer why the transition was started, + * which must be one of the APP_TRANSITION_* values. * @param timestamp The time at which the app transition started in * {@link SystemClock#uptimeMillis()} timebase. */ diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index d5430f05d65b433b3a8e7346cdb48a88698c43c1..09dcbf213459fb8b9d3adc048a30b1633eebc6c6 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -164,7 +164,7 @@ public class ActivityOptions { /** * Whether the activity should be launched into LockTask mode. - * @see #setLockTaskMode(boolean) + * @see #setLockTaskEnabled(boolean) */ private static final String KEY_LOCK_TASK_MODE = "android:activity.lockTaskMode"; @@ -1148,7 +1148,7 @@ public class ActivityOptions { * @see Activity#startLockTask() * @see android.app.admin.DevicePolicyManager#setLockTaskPackages(ComponentName, String[]) */ - public ActivityOptions setLockTaskMode(boolean lockTaskMode) { + public ActivityOptions setLockTaskEnabled(boolean lockTaskMode) { mLockTaskMode = lockTaskMode; return this; } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index a96f484ccf117c4815623a94cebd06e98d17f50c..4754588cbd27b9b3c66667cdfbadee1fac160c2a 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -208,9 +208,6 @@ public final class ActivityThread extends ClientTransactionHandler { public static final boolean DEBUG_ORDER = false; private static final long MIN_TIME_BETWEEN_GCS = 5*1000; private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003; - private static final int LOG_AM_ON_PAUSE_CALLED = 30021; - private static final int LOG_AM_ON_RESUME_CALLED = 30022; - private static final int LOG_AM_ON_STOP_CALLED = 30049; /** Type for IActivityManager.serviceDoneExecuting: anonymous operation */ public static final int SERVICE_DONE_EXECUTING_ANON = 0; @@ -2924,7 +2921,7 @@ public final class ActivityThread extends ClientTransactionHandler { } // Start - activity.performStart(); + activity.performStart("handleStartActivity"); r.setState(ON_START); if (pendingActions == null) { @@ -3113,7 +3110,7 @@ public final class ActivityThread extends ClientTransactionHandler { checkAndBlockForNetworkAccess(); deliverNewIntents(r, intents); if (resumed) { - r.activity.performResume(false); + r.activity.performResume(false, "performNewIntents"); r.activity.mTemporaryPause = false; } @@ -3735,10 +3732,7 @@ public final class ActivityThread extends ClientTransactionHandler { deliverResults(r, r.pendingResults); r.pendingResults = null; } - r.activity.performResume(r.startsNotResumed); - - EventLog.writeEvent(LOG_AM_ON_RESUME_CALLED, UserHandle.myUserId(), - r.activity.getComponentName().getClassName(), reason); + r.activity.performResume(r.startsNotResumed, reason); r.state = null; r.persistentState = null; @@ -3906,7 +3900,8 @@ public final class ActivityThread extends ClientTransactionHandler { @Override public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving, - int configChanges, boolean dontReport, PendingTransactionActions pendingActions) { + int configChanges, boolean dontReport, PendingTransactionActions pendingActions, + String reason) { ActivityClientRecord r = mActivities.get(token); if (r != null) { if (userLeaving) { @@ -3914,7 +3909,7 @@ public final class ActivityThread extends ClientTransactionHandler { } r.activity.mConfigChangeFlags |= configChanges; - performPauseActivity(r, finished, "handlePauseActivity", pendingActions); + performPauseActivity(r, finished, reason, pendingActions); // Make sure any pending writes are now committed. if (r.isPreHoneycomb()) { @@ -4007,8 +4002,6 @@ public final class ActivityThread extends ClientTransactionHandler { try { r.activity.mCalled = false; mInstrumentation.callActivityOnPause(r.activity); - EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(), - r.activity.getComponentName().getClassName(), reason); if (!r.activity.mCalled) { throw new SuperNotCalledException("Activity " + safeToComponentShortString(r.intent) + " did not call through to super.onPause()"); @@ -4119,7 +4112,7 @@ public final class ActivityThread extends ClientTransactionHandler { } try { - r.activity.performStop(false /*preserveWindow*/); + r.activity.performStop(false /*preserveWindow*/, reason); } catch (SuperNotCalledException e) { throw e; } catch (Exception e) { @@ -4131,8 +4124,6 @@ public final class ActivityThread extends ClientTransactionHandler { } } r.setState(ON_STOP); - EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(), - r.activity.getComponentName().getClassName(), reason); if (shouldSaveState && !isPreP) { callActivityOnSaveInstanceState(r); @@ -4169,12 +4160,12 @@ public final class ActivityThread extends ClientTransactionHandler { @Override public void handleStopActivity(IBinder token, boolean show, int configChanges, - PendingTransactionActions pendingActions) { + PendingTransactionActions pendingActions, String reason) { final ActivityClientRecord r = mActivities.get(token); r.activity.mConfigChangeFlags |= configChanges; final StopInfo stopInfo = new StopInfo(); - performStopActivityInner(r, stopInfo, show, true, "handleStopActivity"); + performStopActivityInner(r, stopInfo, show, true, reason); if (localLOGV) Slog.v( TAG, "Finishing stop of " + r + ": show=" + show @@ -4209,7 +4200,7 @@ public final class ActivityThread extends ClientTransactionHandler { public void performRestartActivity(IBinder token, boolean start) { ActivityClientRecord r = mActivities.get(token); if (r.stopped) { - r.activity.performRestart(start); + r.activity.performRestart(start, "performRestartActivity"); if (start) { r.setState(ON_START); } @@ -4232,7 +4223,7 @@ public final class ActivityThread extends ClientTransactionHandler { // we are back active so skip it. unscheduleGcIdler(); - r.activity.performRestart(true /* start */); + r.activity.performRestart(true /* start */, "handleWindowVisibility"); r.setState(ON_START); } if (r.activity.mDecor != null) { @@ -4272,7 +4263,7 @@ public final class ActivityThread extends ClientTransactionHandler { } } else { if (r.stopped && r.activity.mVisibleFromServer) { - r.activity.performRestart(true /* start */); + r.activity.performRestart(true /* start */, "handleSleeping"); r.setState(ON_START); } } @@ -4292,19 +4283,15 @@ public final class ActivityThread extends ClientTransactionHandler { View.mDebugViewAttributes = debugViewAttributes; // request all activities to relaunch for the changes to take place - requestRelaunchAllActivities(); + relaunchAllActivities(); } } - private void requestRelaunchAllActivities() { + private void relaunchAllActivities() { for (Map.Entry entry : mActivities.entrySet()) { final Activity activity = entry.getValue().activity; if (!activity.mFinished) { - try { - ActivityManager.getService().requestActivityRelaunch(entry.getKey()); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + handleRelaunchActivityLocally(entry.getKey()); } } } @@ -4384,7 +4371,7 @@ public final class ActivityThread extends ClientTransactionHandler { checkAndBlockForNetworkAccess(); deliverResults(r, results); if (resumed) { - r.activity.performResume(false); + r.activity.performResume(false, "handleSendResult"); r.activity.mTemporaryPause = false; } } @@ -4679,42 +4666,81 @@ public final class ActivityThread extends ClientTransactionHandler { throw e.rethrowFromSystemServer(); } + handleRelaunchActivityInner(r, configChanges, tmp.pendingResults, tmp.pendingIntents, + pendingActions, tmp.startsNotResumed, tmp.overrideConfig, "handleRelaunchActivity"); + + if (pendingActions != null) { + // Only report a successful relaunch to WindowManager. + pendingActions.setReportRelaunchToWindowManager(true); + } + } + + /** Performs the activity relaunch locally vs. requesting from system-server. */ + void handleRelaunchActivityLocally(IBinder token) { + if (Looper.myLooper() != getLooper()) { + throw new IllegalStateException("Must be called from main thread"); + } + + final ActivityClientRecord r = mActivities.get(token); + if (r == null) { + return; + } + + final int prevState = r.getLifecycleState(); + + if (prevState < ON_RESUME) { + Log.w(TAG, "Activity needs to be already resumed in other to be relaunched."); + return; + } + + // TODO(b/73747058): Investigate converting this to use transaction to relaunch. + handleRelaunchActivityInner(r, 0 /* configChanges */, null /* pendingResults */, + null /* pendingIntents */, null /* pendingActions */, prevState != ON_RESUME, + r.overrideConfig, "handleRelaunchActivityLocally"); + + // Restore back to the previous state before relaunch if needed. + if (prevState != r.getLifecycleState()) { + mTransactionExecutor.cycleToPath(r, prevState); + } + } + + private void handleRelaunchActivityInner(ActivityClientRecord r, int configChanges, + List pendingResults, List pendingIntents, + PendingTransactionActions pendingActions, boolean startsNotResumed, + Configuration overrideConfig, String reason) { // Need to ensure state is saved. if (!r.paused) { - performPauseActivity(r, false, "handleRelaunchActivity", - null /* pendingActions */); + performPauseActivity(r, false, reason, null /* pendingActions */); } if (!r.stopped) { - callActivityOnStop(r, true /* saveState */, "handleRelaunchActivity"); + callActivityOnStop(r, true /* saveState */, reason); } - handleDestroyActivity(r.token, false, configChanges, true, "handleRelaunchActivity"); + handleDestroyActivity(r.token, false, configChanges, true, reason); r.activity = null; r.window = null; r.hideForNow = false; r.nextIdle = null; // Merge any pending results and pending intents; don't just replace them - if (tmp.pendingResults != null) { + if (pendingResults != null) { if (r.pendingResults == null) { - r.pendingResults = tmp.pendingResults; + r.pendingResults = pendingResults; } else { - r.pendingResults.addAll(tmp.pendingResults); + r.pendingResults.addAll(pendingResults); } } - if (tmp.pendingIntents != null) { + if (pendingIntents != null) { if (r.pendingIntents == null) { - r.pendingIntents = tmp.pendingIntents; + r.pendingIntents = pendingIntents; } else { - r.pendingIntents.addAll(tmp.pendingIntents); + r.pendingIntents.addAll(pendingIntents); } } - r.startsNotResumed = tmp.startsNotResumed; - r.overrideConfig = tmp.overrideConfig; + r.startsNotResumed = startsNotResumed; + r.overrideConfig = overrideConfig; handleLaunchActivity(r, pendingActions); - // Only report a successful relaunch to WindowManager. - pendingActions.setReportRelaunchToWindowManager(true); } @Override @@ -5117,7 +5143,7 @@ public final class ActivityThread extends ClientTransactionHandler { newConfig.assetsSeq = (mConfiguration != null ? mConfiguration.assetsSeq : 0) + 1; handleConfigurationChanged(newConfig, null); - requestRelaunchAllActivities(); + relaunchAllActivities(); } static void freeTextLayoutCachesIfNeeded(int configDiff) { diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 1026550b9b6bfa6455adbd61797dd130a4e31f5b..c5b3a4acd339fd96064c6314b8711cfd035d32a4 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -17,6 +17,7 @@ package android.app; import android.Manifest; +import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; @@ -34,8 +35,10 @@ import android.os.UserHandle; import android.os.UserManager; import android.util.ArrayMap; +import com.android.internal.app.IAppOpsActiveCallback; import com.android.internal.app.IAppOpsCallback; import com.android.internal.app.IAppOpsService; +import com.android.internal.util.Preconditions; import java.util.ArrayList; import java.util.Arrays; @@ -74,8 +77,9 @@ public class AppOpsManager { final Context mContext; final IAppOpsService mService; - final ArrayMap mModeWatchers - = new ArrayMap(); + final ArrayMap mModeWatchers = new ArrayMap<>(); + final ArrayMap mActiveWatchers = + new ArrayMap<>(); static IBinder sToken; @@ -1531,6 +1535,23 @@ public class AppOpsManager { public void onOpChanged(String op, String packageName); } + /** + * Callback for notification of changes to operation active state. + * + * @hide + */ + public interface OnOpActiveChangedListener { + /** + * Called when the active state of an app op changes. + * + * @param code The op code. + * @param uid The UID performing the operation. + * @param packageName The package performing the operation. + * @param active Whether the operation became active or inactive. + */ + void onOpActiveChanged(int code, int uid, String packageName, boolean active); + } + /** * Callback for notification of changes to operation state. * This allows you to see the raw op codes instead of strings. @@ -1695,6 +1716,8 @@ public class AppOpsManager { /** * Monitor for changes to the operating mode for the given op in the given app package. + * You can watch op changes only for your UID. + * * @param op The operation to monitor, one of OPSTR_*. * @param packageName The name of the application to monitor. * @param callback Where to report changes. @@ -1706,11 +1729,17 @@ public class AppOpsManager { /** * Monitor for changes to the operating mode for the given op in the given app package. + * + *

If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission + * to watch changes only for your UID. + * * @param op The operation to monitor, one of OP_*. * @param packageName The name of the application to monitor. * @param callback Where to report changes. * @hide */ + // TODO: Uncomment below annotation once b/73559440 is fixed + // @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true) public void startWatchingMode(int op, String packageName, final OnOpChangedListener callback) { synchronized (mModeWatchers) { IAppOpsCallback cb = mModeWatchers.get(callback); @@ -1752,6 +1781,74 @@ public class AppOpsManager { } } + /** + * Start watching for changes to the active state of app ops. An app op may be + * long running and it has a clear start and stop delimiters. If an op is being + * started or stopped by any package you will get a callback. To change the + * watched ops for a registered callback you need to unregister and register it + * again. + * + * @param ops The ops to watch. + * @param callback Where to report changes. + * + * @see #isOperationActive(int, int, String) + * @see #stopWatchingActive(OnOpActiveChangedListener) + * @see #startOp(int, int, String) + * @see #finishOp(int, int, String) + * + * @hide + */ + @RequiresPermission(Manifest.permission.WATCH_APPOPS) + public void startWatchingActive(@NonNull int[] ops, + @NonNull OnOpActiveChangedListener callback) { + Preconditions.checkNotNull(ops, "ops cannot be null"); + Preconditions.checkNotNull(callback, "callback cannot be null"); + IAppOpsActiveCallback cb; + synchronized (mActiveWatchers) { + cb = mActiveWatchers.get(callback); + if (cb != null) { + return; + } + cb = new IAppOpsActiveCallback.Stub() { + @Override + public void opActiveChanged(int op, int uid, String packageName, boolean active) { + callback.onOpActiveChanged(op, uid, packageName, active); + } + }; + mActiveWatchers.put(callback, cb); + } + try { + mService.startWatchingActive(ops, cb); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Stop watching for changes to the active state of an app op. An app op may be + * long running and it has a clear start and stop delimiters. Unregistering a + * non-registered callback has no effect. + * + * @see #isOperationActive#(int, int, String) + * @see #startWatchingActive(int[], OnOpActiveChangedListener) + * @see #startOp(int, int, String) + * @see #finishOp(int, int, String) + * + * @hide + */ + public void stopWatchingActive(@NonNull OnOpActiveChangedListener callback) { + synchronized (mActiveWatchers) { + final IAppOpsActiveCallback cb = mActiveWatchers.get(callback); + if (cb != null) { + try { + mService.stopWatchingActive(cb); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + } + private String buildSecurityExceptionMsg(int op, int uid, String packageName) { return packageName + " from uid " + uid + " not allowed to perform " + sOpNames[op]; } @@ -2145,6 +2242,7 @@ public class AppOpsManager { } /** @hide */ + @RequiresPermission(Manifest.permission.WATCH_APPOPS) public boolean isOperationActive(int code, int uid, String packageName) { try { return mService.isOperationActive(code, uid, packageName); diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 13117bcbc9298f07efdf07e1f34beb35a94111eb..f8f50a2785110c664d06c6d303351dff529235a1 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -2802,4 +2802,13 @@ public class ApplicationPackageManager extends PackageManager { return mArtManager; } } + + @Override + public String getSystemTextClassifierPackageName() { + try { + return mPM.getSystemTextClassifierPackageName(); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } } diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java index 310965e475b8adecab8f515b3ae8c9ee1d5c9156..cb52a855e7ca128fb554331281a8536178b7da59 100644 --- a/core/java/android/app/ClientTransactionHandler.java +++ b/core/java/android/app/ClientTransactionHandler.java @@ -65,7 +65,8 @@ public abstract class ClientTransactionHandler { /** Pause the activity. */ public abstract void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving, - int configChanges, boolean dontReport, PendingTransactionActions pendingActions); + int configChanges, boolean dontReport, PendingTransactionActions pendingActions, + String reason); /** Resume the activity. */ public abstract void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, @@ -73,7 +74,7 @@ public abstract class ClientTransactionHandler { /** Stop the activity. */ public abstract void handleStopActivity(IBinder token, boolean show, int configChanges, - PendingTransactionActions pendingActions); + PendingTransactionActions pendingActions, String reason); /** Report that activity was stopped to server. */ public abstract void reportStop(PendingTransactionActions pendingActions); diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java index eb260265c15fccc76efde23e4c663102cc9fd0a4..4a168fe11c20edc973dbc4fc3184e1280815d9d4 100644 --- a/core/java/android/app/Dialog.java +++ b/core/java/android/app/Dialog.java @@ -291,7 +291,10 @@ public class Dialog implements DialogInterface, Window.Callback, if (mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) { mWindow.invalidatePanelMenu(Window.FEATURE_ACTION_BAR); } - mDecor.setVisibility(View.VISIBLE); + if (mDecor.getVisibility() != View.VISIBLE) { + mDecor.setVisibility(View.VISIBLE); + sendShowMessage(); + } } return; } diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 54fd0c45a811d2fa3fba8a58fdc0ba8e85f07e96..ac301b3cc59550318fde302a6c4352dd0af5f737 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -630,7 +630,6 @@ interface IActivityManager { void setHasTopUi(boolean hasTopUi); // Start of O transactions - void requestActivityRelaunch(in IBinder token); /** * Updates override configuration applied to specific display. * @param values Update values for display configuration. If null is passed it will request the diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index e80610b0fa831f6e07834cf27f6c9f76a6e06b41..233e09d90f9b7bdf4485c6e45c837fe9a4878c5d 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -1332,6 +1332,10 @@ public class Notification implements Parcelable */ public static final int SEMANTIC_ACTION_THUMBS_DOWN = 9; + /** + * {@code SemanticAction}: Call a contact, group, etc. + */ + public static final int SEMANTIC_ACTION_CALL = 10; private final Bundle mExtras; private Icon mIcon; @@ -1821,6 +1825,7 @@ public class Notification implements Parcelable * @param label the label to display while the action is being prepared to execute * @return this object for method chaining */ + @Deprecated public WearableExtender setInProgressLabel(CharSequence label) { mInProgressLabel = label; return this; @@ -1832,6 +1837,7 @@ public class Notification implements Parcelable * * @return the label to display while the action is being prepared to execute */ + @Deprecated public CharSequence getInProgressLabel() { return mInProgressLabel; } @@ -1843,6 +1849,7 @@ public class Notification implements Parcelable * @param label the label to confirm the action should be executed * @return this object for method chaining */ + @Deprecated public WearableExtender setConfirmLabel(CharSequence label) { mConfirmLabel = label; return this; @@ -1854,6 +1861,7 @@ public class Notification implements Parcelable * * @return the label to confirm the action should be executed */ + @Deprecated public CharSequence getConfirmLabel() { return mConfirmLabel; } @@ -1865,6 +1873,7 @@ public class Notification implements Parcelable * @param label the label to display to cancel the action * @return this object for method chaining */ + @Deprecated public WearableExtender setCancelLabel(CharSequence label) { mCancelLabel = label; return this; @@ -1876,6 +1885,7 @@ public class Notification implements Parcelable * * @return the label to display to cancel the action */ + @Deprecated public CharSequence getCancelLabel() { return mCancelLabel; } @@ -1946,7 +1956,8 @@ public class Notification implements Parcelable SEMANTIC_ACTION_MUTE, SEMANTIC_ACTION_UNMUTE, SEMANTIC_ACTION_THUMBS_UP, - SEMANTIC_ACTION_THUMBS_DOWN + SEMANTIC_ACTION_THUMBS_DOWN, + SEMANTIC_ACTION_CALL }) @Retention(RetentionPolicy.SOURCE) public @interface SemanticAction {} @@ -4582,7 +4593,8 @@ public class Notification implements Parcelable big.setViewVisibility(R.id.notification_material_reply_text_3, View.GONE); big.setTextViewText(R.id.notification_material_reply_text_3, null); - big.setViewLayoutMarginBottomDimen(R.id.notification_action_list_margin_target, 0); + big.setViewLayoutMarginBottomDimen(R.id.notification_action_list_margin_target, + R.dimen.notification_content_margin); } private RemoteViews applyStandardTemplateWithActions(int layoutId) { @@ -4603,16 +4615,7 @@ public class Notification implements Parcelable if (N > 0) { big.setViewVisibility(R.id.actions_container, View.VISIBLE); big.setViewVisibility(R.id.actions, View.VISIBLE); - if (p.ambient) { - big.setInt(R.id.actions, "setBackgroundColor", Color.TRANSPARENT); - } else if (isColorized()) { - big.setInt(R.id.actions, "setBackgroundColor", getActionBarColor()); - } else { - big.setInt(R.id.actions, "setBackgroundColor", mContext.getColor( - R.color.notification_action_list)); - } - big.setViewLayoutMarginBottomDimen(R.id.notification_action_list_margin_target, - R.dimen.notification_action_list_height); + big.setViewLayoutMarginBottomDimen(R.id.notification_action_list_margin_target, 0); if (N>MAX_ACTION_BUTTONS) N=MAX_ACTION_BUTTONS; for (int i=0; i= Build.VERSION_CODES.P && (mUser == null || mUser.getName() == null)) { + throw new RuntimeException("User must be valid and have a name."); } } @@ -8066,6 +8088,7 @@ public class Notification implements Parcelable /** * Set an icon that goes with the content of this notification. */ + @Deprecated public WearableExtender setContentIcon(int icon) { mContentIcon = icon; return this; @@ -8074,6 +8097,7 @@ public class Notification implements Parcelable /** * Get an icon that goes with the content of this notification. */ + @Deprecated public int getContentIcon() { return mContentIcon; } @@ -8084,6 +8108,7 @@ public class Notification implements Parcelable * {@link android.view.Gravity#END}. The default value is {@link android.view.Gravity#END}. * @see #setContentIcon */ + @Deprecated public WearableExtender setContentIconGravity(int contentIconGravity) { mContentIconGravity = contentIconGravity; return this; @@ -8095,6 +8120,7 @@ public class Notification implements Parcelable * {@link android.view.Gravity#END}. The default value is {@link android.view.Gravity#END}. * @see #getContentIcon */ + @Deprecated public int getContentIconGravity() { return mContentIconGravity; } @@ -8142,6 +8168,7 @@ public class Notification implements Parcelable * {@link android.view.Gravity#CENTER_VERTICAL} and {@link android.view.Gravity#BOTTOM}. * The default value is {@link android.view.Gravity#BOTTOM}. */ + @Deprecated public WearableExtender setGravity(int gravity) { mGravity = gravity; return this; @@ -8153,6 +8180,7 @@ public class Notification implements Parcelable * {@link android.view.Gravity#CENTER_VERTICAL} and {@link android.view.Gravity#BOTTOM}. * The default value is {@link android.view.Gravity#BOTTOM}. */ + @Deprecated public int getGravity() { return mGravity; } @@ -8166,6 +8194,7 @@ public class Notification implements Parcelable * documentation for the preset in question. See also * {@link #setCustomContentHeight} and {@link #getCustomSizePreset}. */ + @Deprecated public WearableExtender setCustomSizePreset(int sizePreset) { mCustomSizePreset = sizePreset; return this; @@ -8179,6 +8208,7 @@ public class Notification implements Parcelable * using {@link #setDisplayIntent}. Check the documentation for the preset in question. * See also {@link #setCustomContentHeight} and {@link #setCustomSizePreset}. */ + @Deprecated public int getCustomSizePreset() { return mCustomSizePreset; } @@ -8190,6 +8220,7 @@ public class Notification implements Parcelable * {@link android.app.Notification.WearableExtender#setCustomSizePreset} and * {@link #getCustomContentHeight}. */ + @Deprecated public WearableExtender setCustomContentHeight(int height) { mCustomContentHeight = height; return this; @@ -8201,6 +8232,7 @@ public class Notification implements Parcelable * using {@link #setDisplayIntent}. See also {@link #setCustomSizePreset} and * {@link #setCustomContentHeight}. */ + @Deprecated public int getCustomContentHeight() { return mCustomContentHeight; } @@ -8251,6 +8283,7 @@ public class Notification implements Parcelable * @param hintHideIcon {@code true} to hide the icon, {@code false} otherwise. * @return this object for method chaining */ + @Deprecated public WearableExtender setHintHideIcon(boolean hintHideIcon) { setFlag(FLAG_HINT_HIDE_ICON, hintHideIcon); return this; @@ -8261,6 +8294,7 @@ public class Notification implements Parcelable * @return {@code true} if this icon should not be displayed, false otherwise. * The default value is {@code false} if this was never set. */ + @Deprecated public boolean getHintHideIcon() { return (mFlags & FLAG_HINT_HIDE_ICON) != 0; } @@ -8270,6 +8304,7 @@ public class Notification implements Parcelable * displayed, and other semantic content should be hidden. This hint is only applicable * to sub-pages added using {@link #addPage}. */ + @Deprecated public WearableExtender setHintShowBackgroundOnly(boolean hintShowBackgroundOnly) { setFlag(FLAG_HINT_SHOW_BACKGROUND_ONLY, hintShowBackgroundOnly); return this; @@ -8280,6 +8315,7 @@ public class Notification implements Parcelable * displayed, and other semantic content should be hidden. This hint is only applicable * to sub-pages added using {@link android.app.Notification.WearableExtender#addPage}. */ + @Deprecated public boolean getHintShowBackgroundOnly() { return (mFlags & FLAG_HINT_SHOW_BACKGROUND_ONLY) != 0; } @@ -8291,6 +8327,7 @@ public class Notification implements Parcelable * @param hintAvoidBackgroundClipping {@code true} to avoid clipping if possible. * @return this object for method chaining */ + @Deprecated public WearableExtender setHintAvoidBackgroundClipping( boolean hintAvoidBackgroundClipping) { setFlag(FLAG_HINT_AVOID_BACKGROUND_CLIPPING, hintAvoidBackgroundClipping); @@ -8304,6 +8341,7 @@ public class Notification implements Parcelable * @return {@code true} if it's ok if the background is clipped on the screen, false * otherwise. The default value is {@code false} if this was never set. */ + @Deprecated public boolean getHintAvoidBackgroundClipping() { return (mFlags & FLAG_HINT_AVOID_BACKGROUND_CLIPPING) != 0; } @@ -8315,6 +8353,7 @@ public class Notification implements Parcelable * {@link #SCREEN_TIMEOUT_SHORT} or {@link #SCREEN_TIMEOUT_LONG}. * @return this object for method chaining */ + @Deprecated public WearableExtender setHintScreenTimeout(int timeout) { mHintScreenTimeout = timeout; return this; @@ -8326,6 +8365,7 @@ public class Notification implements Parcelable * @return the duration in milliseconds if > 0, or either one of the sentinel values * {@link #SCREEN_TIMEOUT_SHORT} or {@link #SCREEN_TIMEOUT_LONG}. */ + @Deprecated public int getHintScreenTimeout() { return mHintScreenTimeout; } diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java index ea990ad2924e49f4bc15a68c4e80f84b5e1c7b2e..4e2cb646e714a4d0cb5d4c33f5a3f0292341f919 100644 --- a/core/java/android/app/SearchManager.java +++ b/core/java/android/app/SearchManager.java @@ -48,6 +48,9 @@ import java.util.List; * and the {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} * {@link android.content.Intent Intent}. * + *

+ * {@link Configuration#UI_MODE_TYPE_WATCH} does not support this system service. + * *

*

Developer Guides

*

For more information about using the search dialog and adding search diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 14b2119b4e4b2fe0513546a0d327fb69d36583ee..16e36bc54ef20eb542a924acded6dc255d60900e 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -25,6 +25,7 @@ import android.annotation.RequiresFeature; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.StringDef; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; @@ -58,6 +59,7 @@ import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.provider.ContactsContract.Directory; +import android.provider.Settings; import android.security.AttestedKeyPair; import android.security.Credentials; import android.security.KeyChain; @@ -1644,11 +1646,15 @@ public class DevicePolicyManager { public static final int LOCK_TASK_FEATURE_HOME = 1 << 2; /** - * Enable the Recents button and the Recents screen during LockTask mode. + * Enable the Overview button and the Overview screen during LockTask mode. This feature flag + * can only be used in combination with {@link #LOCK_TASK_FEATURE_HOME}, and + * {@link #setLockTaskFeatures(ComponentName, int)} will throw an + * {@link IllegalArgumentException} if this feature flag is defined without + * {@link #LOCK_TASK_FEATURE_HOME}. * * @see #setLockTaskFeatures(ComponentName, int) */ - public static final int LOCK_TASK_FEATURE_RECENTS = 1 << 3; + public static final int LOCK_TASK_FEATURE_OVERVIEW = 1 << 3; /** * Enable the global actions dialog during LockTask mode. This is the dialog that shows up when @@ -1680,7 +1686,7 @@ public class DevicePolicyManager { LOCK_TASK_FEATURE_SYSTEM_INFO, LOCK_TASK_FEATURE_NOTIFICATIONS, LOCK_TASK_FEATURE_HOME, - LOCK_TASK_FEATURE_RECENTS, + LOCK_TASK_FEATURE_OVERVIEW, LOCK_TASK_FEATURE_GLOBAL_ACTIONS, LOCK_TASK_FEATURE_KEYGUARD }) @@ -2852,8 +2858,8 @@ public class DevicePolicyManager { * When called by a profile owner of a managed profile returns true if the profile uses unified * challenge with its parent user. * - * Note: This method is not concerned with password quality and will return false if - * the profile has empty password as a separate challenge. + * Note: This method is not concerned with password quality and will return + * false if the profile has empty password as a separate challenge. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @throws SecurityException if {@code admin} is not a profile owner of a managed profile. @@ -3489,18 +3495,18 @@ public class DevicePolicyManager { * that uses {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA} * @throws IllegalArgumentException if the input reason string is null or empty. */ - public void wipeDataWithReason(int flags, @NonNull CharSequence reason) { - throwIfParentInstance("wipeDataWithReason"); + public void wipeData(int flags, @NonNull CharSequence reason) { + throwIfParentInstance("wipeData"); Preconditions.checkNotNull(reason, "CharSequence is null"); wipeDataInternal(flags, reason.toString()); } /** * Internal function for both {@link #wipeData(int)} and - * {@link #wipeDataWithReason(int, CharSequence)} to call. + * {@link #wipeData(int, CharSequence)} to call. * * @see #wipeData(int) - * @see #wipeDataWithReason(int, CharSequence) + * @see #wipeData(int, CharSequence) * @hide */ private void wipeDataInternal(int flags, @NonNull String wipeReasonForUser) { @@ -7191,7 +7197,7 @@ public class DevicePolicyManager { * {@link #LOCK_TASK_FEATURE_SYSTEM_INFO}, * {@link #LOCK_TASK_FEATURE_NOTIFICATIONS}, * {@link #LOCK_TASK_FEATURE_HOME}, - * {@link #LOCK_TASK_FEATURE_RECENTS}, + * {@link #LOCK_TASK_FEATURE_OVERVIEW}, * {@link #LOCK_TASK_FEATURE_GLOBAL_ACTIONS}, * {@link #LOCK_TASK_FEATURE_KEYGUARD} * @throws SecurityException if {@code admin} is not the device owner, the profile owner of an @@ -7281,6 +7287,15 @@ public class DevicePolicyManager { } } + /** @hide */ + @StringDef({ + Settings.System.SCREEN_BRIGHTNESS_MODE, + Settings.System.SCREEN_BRIGHTNESS, + Settings.System.SCREEN_OFF_TIMEOUT + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SystemSettingsWhitelist {} + /** * Called by device owner to update {@link android.provider.Settings.System} settings. * Validation that the value of the setting is in the correct form for the setting type should @@ -7300,8 +7315,8 @@ public class DevicePolicyManager { * @param value The value to update the setting to. * @throws SecurityException if {@code admin} is not a device owner. */ - public void setSystemSetting(@NonNull ComponentName admin, @NonNull String setting, - String value) { + public void setSystemSetting(@NonNull ComponentName admin, + @NonNull @SystemSettingsWhitelist String setting, String value) { throwIfParentInstance("setSystemSetting"); if (mService != null) { try { @@ -9539,12 +9554,19 @@ public class DevicePolicyManager { /** * Returns the data passed from the current administrator to the new administrator during an * ownership transfer. This is the same {@code bundle} passed in - * {@link #transferOwnership(ComponentName, ComponentName, PersistableBundle)}. + * {@link #transferOwnership(ComponentName, ComponentName, PersistableBundle)}. The bundle is + * persisted until the profile owner or device owner is removed. + * + *

This is the same bundle received in the + * {@link DeviceAdminReceiver#onTransferOwnershipComplete(Context, PersistableBundle)}. + * Use this method to retrieve it after the transfer as long as the new administrator is the + * active device or profile owner. * *

Returns null if no ownership transfer was started for the calling user. * * @see #transferOwnership * @see DeviceAdminReceiver#onTransferOwnershipComplete(Context, PersistableBundle) + * @throws SecurityException if the caller is not a device or profile owner. */ @Nullable public PersistableBundle getTransferOwnershipBundle() { diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java index faaa0043cce8b3b45e76df8b1ffee1807bc11d50..38b4f8ff8d6718fd4ade53f78714733502541ee6 100644 --- a/core/java/android/app/admin/SecurityLog.java +++ b/core/java/android/app/admin/SecurityLog.java @@ -295,7 +295,7 @@ public class SecurityLog { *

  • [1] admin user ID ({@code Integer}) *
  • [2] target user ID ({@code Integer}) *
  • [3] new maximum number of failed password attempts ({@code Integer}) - * @see DevicePolicyManager#setMaximumTimeToLock(ComponentName, long) + * @see DevicePolicyManager#setMaximumFailedPasswordsForWipe(ComponentName, int) */ public static final int TAG_MAX_PASSWORD_ATTEMPTS_SET = SecurityLogTags.SECURITY_MAX_PASSWORD_ATTEMPTS_SET; @@ -370,7 +370,7 @@ public class SecurityLog { SecurityLogTags.SECURITY_CERT_AUTHORITY_INSTALLED; /** - * Indicates that a new oot certificate has been removed from system's trusted credential + * Indicates that a new root certificate has been removed from system's trusted credential * storage. The log entry contains the following information about the event, encapsulated in an * {@link Object} array and accessible via {@link SecurityEvent#getData()}: *
  • [0] result ({@code Integer}, 0 if operation failed, 1 if succeeded) diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java index d36a794ac0468b77c11dcf35c140b8266ea15bf6..d1c957b8fedc6a56d31b45db688ce0a047f2b24d 100644 --- a/core/java/android/app/backup/BackupAgent.java +++ b/core/java/android/app/backup/BackupAgent.java @@ -18,6 +18,7 @@ package android.app.backup; import android.app.IBackupAgent; import android.app.QueuedWork; +import android.app.backup.FullBackup.BackupScheme.PathWithRequiredFlags; import android.content.Context; import android.content.ContextWrapper; import android.content.pm.ApplicationInfo; @@ -343,8 +344,8 @@ public abstract class BackupAgent extends ContextWrapper { return; } - Map> manifestIncludeMap; - ArraySet manifestExcludeSet; + Map> manifestIncludeMap; + ArraySet manifestExcludeSet; try { manifestIncludeMap = backupScheme.maybeParseAndGetCanonicalIncludePaths(); @@ -514,14 +515,13 @@ public abstract class BackupAgent extends ContextWrapper { /** * Check whether the xml yielded any tag for the provided domainToken. * If so, perform a {@link #fullBackupFileTree} which backs up the file or recurses if the path - * is a directory. + * is a directory, but only if all the required flags of the include rule are satisfied by + * the transport. */ private void applyXmlFiltersAndDoFullBackupForDomain(String packageName, String domainToken, - Map> includeMap, - ArraySet filterSet, - ArraySet traversalExcludeSet, - FullBackupDataOutput data) - throws IOException { + Map> includeMap, + ArraySet filterSet, ArraySet traversalExcludeSet, + FullBackupDataOutput data) throws IOException { if (includeMap == null || includeMap.size() == 0) { // Do entire sub-tree for the provided token. fullBackupFileTree(packageName, domainToken, @@ -530,13 +530,22 @@ public abstract class BackupAgent extends ContextWrapper { } else if (includeMap.get(domainToken) != null) { // This will be null if the xml parsing didn't yield any rules for // this domain (there may still be rules for other domains). - for (String includeFile : includeMap.get(domainToken)) { - fullBackupFileTree(packageName, domainToken, includeFile, filterSet, - traversalExcludeSet, data); + for (PathWithRequiredFlags includeFile : includeMap.get(domainToken)) { + if (areIncludeRequiredTransportFlagsSatisfied(includeFile.getRequiredFlags(), + data.getTransportFlags())) { + fullBackupFileTree(packageName, domainToken, includeFile.getPath(), filterSet, + traversalExcludeSet, data); + } } } } + private boolean areIncludeRequiredTransportFlagsSatisfied(int includeFlags, + int transportFlags) { + // all bits that are set in includeFlags must also be set in transportFlags + return (transportFlags & includeFlags) == includeFlags; + } + /** * Write an entire file as part of a full-backup operation. The file's contents * will be delivered to the backup destination along with the metadata necessary @@ -683,7 +692,7 @@ public abstract class BackupAgent extends ContextWrapper { * @hide */ protected final void fullBackupFileTree(String packageName, String domain, String startingPath, - ArraySet manifestExcludes, + ArraySet manifestExcludes, ArraySet systemExcludes, FullBackupDataOutput output) { // Pull out the domain and set it aside to use when making the tarball. @@ -714,7 +723,8 @@ public abstract class BackupAgent extends ContextWrapper { filePath = file.getCanonicalPath(); // prune this subtree? - if (manifestExcludes != null && manifestExcludes.contains(filePath)) { + if (manifestExcludes != null + && manifestExcludesContainFilePath(manifestExcludes, filePath)) { continue; } if (systemExcludes != null && systemExcludes.contains(filePath)) { @@ -750,6 +760,17 @@ public abstract class BackupAgent extends ContextWrapper { } } + private boolean manifestExcludesContainFilePath( + ArraySet manifestExcludes, String filePath) { + for (PathWithRequiredFlags exclude : manifestExcludes) { + String excludePath = exclude.getPath(); + if (excludePath != null && excludePath.equals(filePath)) { + return true; + } + } + return false; + } + /** * Handle the data delivered via the given file descriptor during a full restore * operation. The agent is given the path to the file's original location as well @@ -796,8 +817,8 @@ public abstract class BackupAgent extends ContextWrapper { return false; } - Map> includes = null; - ArraySet excludes = null; + Map> includes = null; + ArraySet excludes = null; final String destinationCanonicalPath = destination.getCanonicalPath(); try { includes = bs.maybeParseAndGetCanonicalIncludePaths(); @@ -826,7 +847,7 @@ public abstract class BackupAgent extends ContextWrapper { // Rather than figure out the domain based on the path (a lot of code, and // it's a small list), we'll go through and look for it. boolean explicitlyIncluded = false; - for (Set domainIncludes : includes.values()) { + for (Set domainIncludes : includes.values()) { explicitlyIncluded |= isFileSpecifiedInPathList(destination, domainIncludes); if (explicitlyIncluded) { break; @@ -849,9 +870,10 @@ public abstract class BackupAgent extends ContextWrapper { * @return True if the provided file is either directly in the provided list, or the provided * file is within a directory in the list. */ - private boolean isFileSpecifiedInPathList(File file, Collection canonicalPathList) - throws IOException { - for (String canonicalPath : canonicalPathList) { + private boolean isFileSpecifiedInPathList(File file, + Collection canonicalPathList) throws IOException { + for (PathWithRequiredFlags canonical : canonicalPathList) { + String canonicalPath = canonical.getPath(); File fileFromList = new File(canonicalPath); if (fileFromList.isDirectory()) { if (file.isDirectory()) { diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java index 6ec0969771c6729a721569927e458c2f372e30fc..debc32bd83eb1a3cceae320ef63600b0b26c20f0 100644 --- a/core/java/android/app/backup/BackupManager.java +++ b/core/java/android/app/backup/BackupManager.java @@ -19,6 +19,7 @@ package android.app.backup; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -715,6 +716,92 @@ public class BackupManager { } } + /** + * Returns an {@link Intent} for the specified transport's configuration UI. + * This value is set by {@link #updateTransportAttributes(ComponentName, String, Intent, String, + * Intent, String)}. + * @param transportName The name of the registered transport. + * @hide + */ + @SystemApi + @TestApi + @RequiresPermission(android.Manifest.permission.BACKUP) + public Intent getConfigurationIntent(String transportName) { + if (sService != null) { + try { + return sService.getConfigurationIntent(transportName); + } catch (RemoteException e) { + Log.e(TAG, "getConfigurationIntent() couldn't connect"); + } + } + return null; + } + + /** + * Returns a {@link String} describing where the specified transport is sending data. + * This value is set by {@link #updateTransportAttributes(ComponentName, String, Intent, String, + * Intent, String)}. + * @param transportName The name of the registered transport. + * @hide + */ + @SystemApi + @TestApi + @RequiresPermission(android.Manifest.permission.BACKUP) + public String getDestinationString(String transportName) { + if (sService != null) { + try { + return sService.getDestinationString(transportName); + } catch (RemoteException e) { + Log.e(TAG, "getDestinationString() couldn't connect"); + } + } + return null; + } + + /** + * Returns an {@link Intent} for the specified transport's data management UI. + * This value is set by {@link #updateTransportAttributes(ComponentName, String, Intent, String, + * Intent, String)}. + * @param transportName The name of the registered transport. + * @hide + */ + @SystemApi + @TestApi + @RequiresPermission(android.Manifest.permission.BACKUP) + public Intent getDataManagementIntent(String transportName) { + if (sService != null) { + try { + return sService.getDataManagementIntent(transportName); + } catch (RemoteException e) { + Log.e(TAG, "getDataManagementIntent() couldn't connect"); + } + } + return null; + } + + /** + * Returns a {@link String} describing what the specified transport's data management intent is + * used for. + * This value is set by {@link #updateTransportAttributes(ComponentName, String, Intent, String, + * Intent, String)}. + * + * @param transportName The name of the registered transport. + * @hide + */ + @SystemApi + @TestApi + @RequiresPermission(android.Manifest.permission.BACKUP) + public String getDataManagementLabel(String transportName) { + if (sService != null) { + try { + return sService.getDataManagementLabel(transportName); + } catch (RemoteException e) { + Log.e(TAG, "getDataManagementLabel() couldn't connect"); + } + } + return null; + } + /* * We wrap incoming binder calls with a private class implementation that * redirects them into main-thread actions. This serializes the backup diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java index a5dd5bd30d63171a7a31179dc92341179ac123e6..fb1c2d085df6e71f863db134a1e8b727e9dd3dd5 100644 --- a/core/java/android/app/backup/FullBackup.java +++ b/core/java/android/app/backup/FullBackup.java @@ -82,6 +82,9 @@ public class FullBackup { public static final String FULL_RESTORE_INTENT_ACTION = "fullrest"; public static final String CONF_TOKEN_INTENT_EXTRA = "conftoken"; + public static final String FLAG_REQUIRED_CLIENT_SIDE_ENCRYPTION = "clientSideEncryption"; + public static final String FLAG_REQUIRED_DEVICE_TO_DEVICE_TRANSFER = "deviceToDeviceTransfer"; + /** * @hide */ @@ -224,6 +227,9 @@ public class FullBackup { private final File EXTERNAL_DIR; + private final static String TAG_INCLUDE = "include"; + private final static String TAG_EXCLUDE = "exclude"; + final int mFullBackupContent; final PackageManager mPackageManager; final StorageManager mStorageManager; @@ -303,15 +309,45 @@ public class FullBackup { } /** - * A map of domain -> list of canonical file names in that domain that are to be included. - * We keep track of the domain so that we can go through the file system in order later on. - */ - Map> mIncludes; - /**e - * List that will be populated with the canonical names of each file or directory that is - * to be excluded. + * Represents a path attribute specified in an rule along with optional + * transport flags required from the transport to include file(s) under that path as + * specified by requiredFlags attribute. If optional requiredFlags attribute is not + * provided, default requiredFlags to 0. + * Note: since our parsing codepaths were the same for and tags, + * this structure is also used for tags to preserve that, however you can expect + * the getRequiredFlags() to always return 0 for exclude rules. + */ + public static class PathWithRequiredFlags { + private final String mPath; + private final int mRequiredFlags; + + public PathWithRequiredFlags(String path, int requiredFlags) { + mPath = path; + mRequiredFlags = requiredFlags; + } + + public String getPath() { + return mPath; + } + + public int getRequiredFlags() { + return mRequiredFlags; + } + } + + /** + * A map of domain -> set of pairs (canonical file; required transport flags) in that + * domain that are to be included if the transport has decared the required flags. + * We keep track of the domain so that we can go through the file system in order later on. + */ + Map> mIncludes; + + /** + * Set that will be populated with pairs (canonical file; requiredFlags=0) for each file or + * directory that is to be excluded. Note that for excludes, the requiredFlags attribute is + * ignored and the value should be always set to 0. */ - ArraySet mExcludes; + ArraySet mExcludes; BackupScheme(Context context) { mFullBackupContent = context.getApplicationInfo().fullBackupContent; @@ -356,13 +392,14 @@ public class FullBackup { } /** - * @return A mapping of domain -> canonical paths within that domain. Each of these paths - * specifies a file that the client has explicitly included in their backup set. If this - * map is empty we will back up the entire data directory (including managed external - * storage). + * @return A mapping of domain -> set of pairs (canonical file; required transport flags) + * in that domain that are to be included if the transport has decared the required flags. + * Each of these paths specifies a file that the client has explicitly included in their + * backup set. If this map is empty we will back up the entire data directory (including + * managed external storage). */ - public synchronized Map> maybeParseAndGetCanonicalIncludePaths() - throws IOException, XmlPullParserException { + public synchronized Map> + maybeParseAndGetCanonicalIncludePaths() throws IOException, XmlPullParserException { if (mIncludes == null) { maybeParseBackupSchemeLocked(); } @@ -370,9 +407,10 @@ public class FullBackup { } /** - * @return A set of canonical paths that are to be excluded from the backup/restore set. + * @return A set of (canonical paths; requiredFlags=0) that are to be excluded from the + * backup/restore set. */ - public synchronized ArraySet maybeParseAndGetCanonicalExcludePaths() + public synchronized ArraySet maybeParseAndGetCanonicalExcludePaths() throws IOException, XmlPullParserException { if (mExcludes == null) { maybeParseBackupSchemeLocked(); @@ -382,8 +420,8 @@ public class FullBackup { private void maybeParseBackupSchemeLocked() throws IOException, XmlPullParserException { // This not being null is how we know that we've tried to parse the xml already. - mIncludes = new ArrayMap>(); - mExcludes = new ArraySet(); + mIncludes = new ArrayMap>(); + mExcludes = new ArraySet(); if (mFullBackupContent == 0) { // android:fullBackupContent="true" which means that we'll do everything. @@ -415,8 +453,8 @@ public class FullBackup { @VisibleForTesting public void parseBackupSchemeFromXmlLocked(XmlPullParser parser, - Set excludes, - Map> includes) + Set excludes, + Map> includes) throws IOException, XmlPullParserException { int event = parser.getEventType(); // START_DOCUMENT while (event != XmlPullParser.START_TAG) { @@ -441,8 +479,7 @@ public class FullBackup { case XmlPullParser.START_TAG: validateInnerTagContents(parser); final String domainFromXml = parser.getAttributeValue(null, "domain"); - final File domainDirectory = - getDirectoryForCriteriaDomain(domainFromXml); + final File domainDirectory = getDirectoryForCriteriaDomain(domainFromXml); if (domainDirectory == null) { if (Log.isLoggable(TAG_XML_PARSER, Log.VERBOSE)) { Log.v(TAG_XML_PARSER, "...parsing \"" + parser.getName() + "\": " @@ -457,12 +494,23 @@ public class FullBackup { break; } - Set activeSet = parseCurrentTagForDomain( + int requiredFlags = 0; // no transport flags are required by default + if (TAG_INCLUDE.equals(parser.getName())) { + // requiredFlags are only supported for tag, for + // we should always leave them as the default = 0 + requiredFlags = getRequiredFlagsFromString( + parser.getAttributeValue(null, "requireFlags")); + } + + // retrieve the include/exclude set we'll be adding this rule to + Set activeSet = parseCurrentTagForDomain( parser, excludes, includes, domainFromXml); - activeSet.add(canonicalFile.getCanonicalPath()); + activeSet.add(new PathWithRequiredFlags(canonicalFile.getCanonicalPath(), + requiredFlags)); if (Log.isLoggable(TAG_XML_PARSER, Log.VERBOSE)) { Log.v(TAG_XML_PARSER, "...parsed " + canonicalFile.getCanonicalPath() - + " for domain \"" + domainFromXml + "\""); + + " for domain \"" + domainFromXml + "\", requiredFlags + \"" + + requiredFlags + "\""); } // Special case journal files (not dirs) for sqlite database. frowny-face. @@ -472,14 +520,16 @@ public class FullBackup { if ("database".equals(domainFromXml) && !canonicalFile.isDirectory()) { final String canonicalJournalPath = canonicalFile.getCanonicalPath() + "-journal"; - activeSet.add(canonicalJournalPath); + activeSet.add(new PathWithRequiredFlags(canonicalJournalPath, + requiredFlags)); if (Log.isLoggable(TAG_XML_PARSER, Log.VERBOSE)) { Log.v(TAG_XML_PARSER, "...automatically generated " + canonicalJournalPath + ". Ignore if nonexistent."); } final String canonicalWalPath = canonicalFile.getCanonicalPath() + "-wal"; - activeSet.add(canonicalWalPath); + activeSet.add(new PathWithRequiredFlags(canonicalWalPath, + requiredFlags)); if (Log.isLoggable(TAG_XML_PARSER, Log.VERBOSE)) { Log.v(TAG_XML_PARSER, "...automatically generated " + canonicalWalPath + ". Ignore if nonexistent."); @@ -491,7 +541,8 @@ public class FullBackup { !canonicalFile.getCanonicalPath().endsWith(".xml")) { final String canonicalXmlPath = canonicalFile.getCanonicalPath() + ".xml"; - activeSet.add(canonicalXmlPath); + activeSet.add(new PathWithRequiredFlags(canonicalXmlPath, + requiredFlags)); if (Log.isLoggable(TAG_XML_PARSER, Log.VERBOSE)) { Log.v(TAG_XML_PARSER, "...automatically generated " + canonicalXmlPath + ". Ignore if nonexistent."); @@ -508,10 +559,12 @@ public class FullBackup { Log.v(TAG_XML_PARSER, " ...nothing specified (This means the entirety of app" + " data minus excludes)"); } else { - for (Map.Entry> entry : includes.entrySet()) { + for (Map.Entry> entry + : includes.entrySet()) { Log.v(TAG_XML_PARSER, " domain=" + entry.getKey()); - for (String includeData : entry.getValue()) { - Log.v(TAG_XML_PARSER, " " + includeData); + for (PathWithRequiredFlags includeData : entry.getValue()) { + Log.v(TAG_XML_PARSER, " path: " + includeData.getPath() + + " requiredFlags: " + includeData.getRequiredFlags()); } } } @@ -520,8 +573,9 @@ public class FullBackup { if (excludes.isEmpty()) { Log.v(TAG_XML_PARSER, " ...nothing to exclude."); } else { - for (String excludeData : excludes) { - Log.v(TAG_XML_PARSER, " " + excludeData); + for (PathWithRequiredFlags excludeData : excludes) { + Log.v(TAG_XML_PARSER, " path: " + excludeData.getPath() + + " requiredFlags: " + excludeData.getRequiredFlags()); } } @@ -531,20 +585,41 @@ public class FullBackup { } } - private Set parseCurrentTagForDomain(XmlPullParser parser, - Set excludes, - Map> includes, - String domain) + private int getRequiredFlagsFromString(String requiredFlags) { + int flags = 0; + if (requiredFlags == null || requiredFlags.length() == 0) { + // requiredFlags attribute was missing or empty in tag + return flags; + } + String[] flagsStr = requiredFlags.split("\\|"); + for (String f : flagsStr) { + switch (f) { + case FLAG_REQUIRED_CLIENT_SIDE_ENCRYPTION: + flags |= BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED; + break; + case FLAG_REQUIRED_DEVICE_TO_DEVICE_TRANSFER: + flags |= BackupAgent.FLAG_DEVICE_TO_DEVICE_TRANSFER; + break; + default: + Log.w(TAG, "Unrecognized requiredFlag provided, value: \"" + f + "\""); + } + } + return flags; + } + + private Set parseCurrentTagForDomain(XmlPullParser parser, + Set excludes, + Map> includes, String domain) throws XmlPullParserException { - if ("include".equals(parser.getName())) { + if (TAG_INCLUDE.equals(parser.getName())) { final String domainToken = getTokenForXmlDomain(domain); - Set includeSet = includes.get(domainToken); + Set includeSet = includes.get(domainToken); if (includeSet == null) { - includeSet = new ArraySet(); + includeSet = new ArraySet(); includes.put(domainToken, includeSet); } return includeSet; - } else if ("exclude".equals(parser.getName())) { + } else if (TAG_EXCLUDE.equals(parser.getName())) { return excludes; } else { // Unrecognised tag => hard failure. @@ -589,8 +664,8 @@ public class FullBackup { /** * * @param domain Directory where the specified file should exist. Not null. - * @param filePathFromXml parsed from xml. Not sanitised before calling this function so may be - * null. + * @param filePathFromXml parsed from xml. Not sanitised before calling this function so may + * be null. * @return The canonical path of the file specified or null if no such file exists. */ private File extractCanonicalFile(File domain, String filePathFromXml) { @@ -650,15 +725,27 @@ public class FullBackup { * Let's be strict about the type of xml the client can write. If we see anything untoward, * throw an XmlPullParserException. */ - private void validateInnerTagContents(XmlPullParser parser) - throws XmlPullParserException { - if (parser.getAttributeCount() > 2) { - throw new XmlPullParserException("At most 2 tag attributes allowed for \"" - + parser.getName() + "\" tag (\"domain\" & \"path\"."); + private void validateInnerTagContents(XmlPullParser parser) throws XmlPullParserException { + if (parser == null) { + return; } - if (!"include".equals(parser.getName()) && !"exclude".equals(parser.getName())) { - throw new XmlPullParserException("A valid tag is one of \"\" or" + - " \". You provided \"" + parser.getName() + "\""); + switch (parser.getName()) { + case TAG_INCLUDE: + if (parser.getAttributeCount() > 3) { + throw new XmlPullParserException("At most 3 tag attributes allowed for " + + "\"include\" tag (\"domain\" & \"path\"" + + " & optional \"requiredFlags\")."); + } + break; + case TAG_EXCLUDE: + if (parser.getAttributeCount() > 2) { + throw new XmlPullParserException("At most 2 tag attributes allowed for " + + "\"exclude\" tag (\"domain\" & \"path\"."); + } + break; + default: + throw new XmlPullParserException("A valid tag is one of \"\" or" + + " \". You provided \"" + parser.getName() + "\""); } } } diff --git a/core/java/android/app/servertransaction/PauseActivityItem.java b/core/java/android/app/servertransaction/PauseActivityItem.java index 91e73cd5b1cdda7c6bed097b4cd9fac41622ec2e..578f0e3d24cb657080c8d458ba49826aaa928a6d 100644 --- a/core/java/android/app/servertransaction/PauseActivityItem.java +++ b/core/java/android/app/servertransaction/PauseActivityItem.java @@ -43,7 +43,7 @@ public class PauseActivityItem extends ActivityLifecycleItem { PendingTransactionActions pendingActions) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause"); client.handlePauseActivity(token, mFinished, mUserLeaving, mConfigChanges, mDontReport, - pendingActions); + pendingActions, "PAUSE_ACTIVITY_ITEM"); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } diff --git a/core/java/android/app/servertransaction/StopActivityItem.java b/core/java/android/app/servertransaction/StopActivityItem.java index f955a903d649f7f201f4c0b4c41f51605df2f367..0a61fab2a8ea1ec5141d86e37d86f11b5120a419 100644 --- a/core/java/android/app/servertransaction/StopActivityItem.java +++ b/core/java/android/app/servertransaction/StopActivityItem.java @@ -38,7 +38,8 @@ public class StopActivityItem extends ActivityLifecycleItem { public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStop"); - client.handleStopActivity(token, mShowWindow, mConfigChanges, pendingActions); + client.handleStopActivity(token, mShowWindow, mConfigChanges, pendingActions, + "STOP_ACTIVITY_ITEM"); 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 840fef80a5fffab8ffc6ec0fa10e7d1c8652b126..b66d61b76d5fa7386d8082670c25cf1c28ce8e74 100644 --- a/core/java/android/app/servertransaction/TransactionExecutor.java +++ b/core/java/android/app/servertransaction/TransactionExecutor.java @@ -186,11 +186,11 @@ public class TransactionExecutor { case ON_PAUSE: mTransactionHandler.handlePauseActivity(r.token, false /* finished */, false /* userLeaving */, 0 /* configChanges */, - true /* dontReport */, mPendingActions); + true /* dontReport */, mPendingActions, "LIFECYCLER_PAUSE_ACTIVITY"); break; case ON_STOP: mTransactionHandler.handleStopActivity(r.token, false /* show */, - 0 /* configChanges */, mPendingActions); + 0 /* configChanges */, mPendingActions, "LIFECYCLER_STOP_ACTIVITY"); break; case ON_DESTROY: mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */, diff --git a/core/java/android/app/slice/ISliceManager.aidl b/core/java/android/app/slice/ISliceManager.aidl index 38d9025cc82f87503a82289ae9d6501b1284a6bf..20ec75a36ad3e7e834c7405cdf3aaaaf837defa2 100644 --- a/core/java/android/app/slice/ISliceManager.aidl +++ b/core/java/android/app/slice/ISliceManager.aidl @@ -16,17 +16,13 @@ package android.app.slice; -import android.app.slice.ISliceListener; import android.app.slice.SliceSpec; import android.net.Uri; /** @hide */ interface ISliceManager { - void addSliceListener(in Uri uri, String pkg, in ISliceListener listener, - in SliceSpec[] specs); - void removeSliceListener(in Uri uri, String pkg, in ISliceListener listener); - void pinSlice(String pkg, in Uri uri, in SliceSpec[] specs); - void unpinSlice(String pkg, in Uri uri); + void pinSlice(String pkg, in Uri uri, in SliceSpec[] specs, in IBinder token); + void unpinSlice(String pkg, in Uri uri, in IBinder token); boolean hasSliceAccess(String pkg); SliceSpec[] getPinnedSpecs(in Uri uri, String pkg); int checkSlicePermission(in Uri uri, String pkg, int pid, int uid); diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java index 126deefae282e72d6dddc582f92724784ff6ee45..0a5795e471f5af71b1ad7be71920cb920747d10d 100644 --- a/core/java/android/app/slice/Slice.java +++ b/core/java/android/app/slice/Slice.java @@ -70,16 +70,6 @@ public final class Slice implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface SliceHint {} - /** - * The meta-data key that allows an activity to easily be linked directly to a slice. - *

    - * An activity can be statically linked to a slice uri by including a meta-data item - * for this key that contains a valid slice uri for the same application declaring - * the activity. - * @hide - */ - public static final String SLICE_METADATA_KEY = "android.metadata.SLICE_URI"; - /** * Hint that this content is a title of other content in the slice. This can also indicate that * the content should be used in the shortcut representation of the slice (icon, label, action), diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java index 3f13fffb385760088737f8ca1b664d55c7aab553..ae1d8d79caf0ab1e6673191322d60845c5c6db43 100644 --- a/core/java/android/app/slice/SliceManager.java +++ b/core/java/android/app/slice/SliceManager.java @@ -24,10 +24,13 @@ import android.content.ContentProviderClient; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.Uri; +import android.os.Binder; import android.os.Bundle; import android.os.Handler; +import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; @@ -60,10 +63,20 @@ public class SliceManager { public static final String ACTION_REQUEST_SLICE_PERMISSION = "android.intent.action.REQUEST_SLICE_PERMISSION"; + /** + * The meta-data key that allows an activity to easily be linked directly to a slice. + *

    + * An activity can be statically linked to a slice uri by including a meta-data item + * for this key that contains a valid slice uri for the same application declaring + * the activity. + */ + public static final String SLICE_METADATA_KEY = "android.metadata.SLICE_URI"; + private final ISliceManager mService; private final Context mContext; private final ArrayMap, ISliceListener> mListenerLookup = new ArrayMap<>(); + private final IBinder mToken = new Binder(); /** * Permission denied. @@ -96,7 +109,6 @@ public class SliceManager { @Deprecated public void registerSliceCallback(@NonNull Uri uri, @NonNull SliceCallback callback, @NonNull List specs) { - registerSliceCallback(uri, specs, mContext.getMainExecutor(), callback); } /** @@ -105,7 +117,6 @@ public class SliceManager { @Deprecated public void registerSliceCallback(@NonNull Uri uri, @NonNull SliceCallback callback, @NonNull List specs, Executor executor) { - registerSliceCallback(uri, specs, executor, callback); } /** @@ -123,7 +134,6 @@ public class SliceManager { */ public void registerSliceCallback(@NonNull Uri uri, @NonNull List specs, @NonNull SliceCallback callback) { - registerSliceCallback(uri, specs, mContext.getMainExecutor(), callback); } /** @@ -141,32 +151,7 @@ public class SliceManager { */ public void registerSliceCallback(@NonNull Uri uri, @NonNull List specs, @NonNull @CallbackExecutor Executor executor, @NonNull SliceCallback callback) { - try { - mService.addSliceListener(uri, mContext.getPackageName(), - getListener(uri, callback, new ISliceListener.Stub() { - @Override - public void onSliceUpdated(Slice s) throws RemoteException { - executor.execute(() -> callback.onSliceUpdated(s)); - } - }), specs.toArray(new SliceSpec[specs.size()])); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - private ISliceListener getListener(Uri uri, SliceCallback callback, - ISliceListener listener) { - Pair key = new Pair<>(uri, callback); - if (mListenerLookup.containsKey(key)) { - try { - mService.removeSliceListener(uri, mContext.getPackageName(), - mListenerLookup.get(key)); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - mListenerLookup.put(key, listener); - return listener; } /** @@ -180,12 +165,7 @@ public class SliceManager { * @see #registerSliceCallback */ public void unregisterSliceCallback(@NonNull Uri uri, @NonNull SliceCallback callback) { - try { - mService.removeSliceListener(uri, mContext.getPackageName(), - mListenerLookup.remove(new Pair<>(uri, callback))); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + } /** @@ -206,7 +186,7 @@ public class SliceManager { public void pinSlice(@NonNull Uri uri, @NonNull List specs) { try { mService.pinSlice(mContext.getPackageName(), uri, - specs.toArray(new SliceSpec[specs.size()])); + specs.toArray(new SliceSpec[specs.size()]), mToken); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -228,7 +208,7 @@ public class SliceManager { */ public void unpinSlice(@NonNull Uri uri) { try { - mService.unpinSlice(mContext.getPackageName(), uri); + mService.unpinSlice(mContext.getPackageName(), uri, mToken); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -316,12 +296,10 @@ public class SliceManager { } /** - * Turns a slice intent into a slice uri. Expects an explicit intent. If there is no - * {@link android.content.ContentProvider} associated with the given intent this will throw - * {@link IllegalArgumentException}. + * Turns a slice intent into a slice uri. Expects an explicit intent. * * @param intent The intent associated with a slice. - * @return The Slice Uri provided by the app or null if none is given. + * @return The Slice Uri provided by the app or null if none exists. * @see Slice * @see SliceProvider#onMapIntentToUri(Intent) * @see Intent @@ -341,7 +319,16 @@ public class SliceManager { List providers = mContext.getPackageManager().queryIntentContentProviders(intent, 0); if (providers == null || providers.isEmpty()) { - throw new IllegalArgumentException("Unable to resolve intent " + intent); + // There are no providers, see if this activity has a direct link. + ResolveInfo resolve = mContext.getPackageManager().resolveActivity(intent, + PackageManager.GET_META_DATA); + if (resolve != null && resolve.activityInfo != null + && resolve.activityInfo.metaData != null + && resolve.activityInfo.metaData.containsKey(SLICE_METADATA_KEY)) { + return Uri.parse( + resolve.activityInfo.metaData.getString(SLICE_METADATA_KEY)); + } + return null; } String authority = providers.get(0).providerInfo.authority; Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) @@ -392,7 +379,16 @@ public class SliceManager { List providers = mContext.getPackageManager().queryIntentContentProviders(intent, 0); if (providers == null || providers.isEmpty()) { - throw new IllegalArgumentException("Unable to resolve intent " + intent); + // There are no providers, see if this activity has a direct link. + ResolveInfo resolve = mContext.getPackageManager().resolveActivity(intent, + PackageManager.GET_META_DATA); + if (resolve != null && resolve.activityInfo != null + && resolve.activityInfo.metaData != null + && resolve.activityInfo.metaData.containsKey(SLICE_METADATA_KEY)) { + return bindSlice(Uri.parse(resolve.activityInfo.metaData + .getString(SLICE_METADATA_KEY)), supportedSpecs); + } + return null; } String authority = providers.get(0).providerInfo.authority; Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) diff --git a/core/java/android/app/timezone/RulesManager.java b/core/java/android/app/timezone/RulesManager.java index dc792569417603838648bcfe68a98ca90ef7b26b..fe83113b5d5619f5be287720794ee772650ab86f 100644 --- a/core/java/android/app/timezone/RulesManager.java +++ b/core/java/android/app/timezone/RulesManager.java @@ -36,7 +36,7 @@ import java.util.Arrays; *

    This interface is intended for use with the default APK-based time zone rules update * application but it can also be used by OEMs if that mechanism is turned off using configuration. * All callers must possess the {@link android.Manifest.permission#UPDATE_TIME_ZONE_RULES} system - * permission. + * permission unless otherwise stated. * *

    When using the default mechanism, when properly configured the Android system will send a * {@link RulesUpdaterContract#ACTION_TRIGGER_RULES_UPDATE_CHECK} intent with a @@ -120,9 +120,12 @@ public final class RulesManager { /** * Returns information about the current time zone rules state such as the IANA version of - * the system and any currently installed distro. This method is intended to allow clients to - * determine if the current state can be improved; for example by passing the information to a - * server that may provide a new distro for download. + * the system and any currently installed distro. This method allows clients to determine the + * current device state, perhaps to see if it can be improved; for example by passing the + * information to a server that may provide a new distro for download. + * + *

    Callers must possess the {@link android.Manifest.permission#QUERY_TIME_ZONE_RULES} system + * permission. */ public RulesState getRulesState() { try { diff --git a/core/java/android/app/usage/AppStandbyInfo.java b/core/java/android/app/usage/AppStandbyInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..51fe0e2745bef906c81db001d853a742b29a0706 --- /dev/null +++ b/core/java/android/app/usage/AppStandbyInfo.java @@ -0,0 +1,64 @@ +/* + * 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.app.usage; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * A pair of {package, bucket} to denote the app standby bucket for a given package. + * Used as a vehicle of data across the binder IPC. + * @hide + */ +public final class AppStandbyInfo implements Parcelable { + + public String mPackageName; + public @UsageStatsManager.StandbyBuckets int mStandbyBucket; + + private AppStandbyInfo(Parcel in) { + mPackageName = in.readString(); + mStandbyBucket = in.readInt(); + } + + public AppStandbyInfo(String packageName, int bucket) { + mPackageName = packageName; + mStandbyBucket = bucket; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(mPackageName); + dest.writeInt(mStandbyBucket); + } + + public static final Creator CREATOR = new Creator() { + @Override + public AppStandbyInfo createFromParcel(Parcel source) { + return new AppStandbyInfo(source); + } + + @Override + public AppStandbyInfo[] newArray(int size) { + return new AppStandbyInfo[size]; + } + }; +} diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl index f089c127d03f44253900e32b94203e4c3d286f1a..e72b84d248024c177a63b3c075a3cc6821efdf52 100644 --- a/core/java/android/app/usage/IUsageStatsManager.aidl +++ b/core/java/android/app/usage/IUsageStatsManager.aidl @@ -40,6 +40,6 @@ interface IUsageStatsManager { in String[] annotations, String action); int getAppStandbyBucket(String packageName, String callingPackage, int userId); void setAppStandbyBucket(String packageName, int bucket, int userId); - Map getAppStandbyBuckets(String callingPackage, int userId); - void setAppStandbyBuckets(in Map appBuckets, int userId); + ParceledListSlice getAppStandbyBuckets(String callingPackage, int userId); + void setAppStandbyBuckets(in ParceledListSlice appBuckets, int userId); } diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java index 6b573e99f1fab66b71d6165a3a5723215abe6449..521ab4edc4c561212491595a7b9a1cca072a0fc2 100644 --- a/core/java/android/app/usage/UsageEvents.java +++ b/core/java/android/app/usage/UsageEvents.java @@ -109,7 +109,8 @@ public final class UsageEvents implements Parcelable { public static final int NOTIFICATION_SEEN = 10; /** - * An event type denoting a change in App Standby Bucket. + * An event type denoting a change in App Standby Bucket. Additional bucket information + * is contained in mBucketAndReason. * @hide */ @SystemApi @@ -180,11 +181,12 @@ public final class UsageEvents implements Parcelable { public String[] mContentAnnotations; /** - * The app standby bucket assigned. + * The app standby bucket assigned and reason. Bucket is the high order 16 bits, reason + * is the low order 16 bits. * Only present for {@link #STANDBY_BUCKET_CHANGED} event types * {@hide} */ - public int mBucket; + public int mBucketAndReason; /** @hide */ @EventFlags @@ -205,7 +207,7 @@ public final class UsageEvents implements Parcelable { mContentType = orig.mContentType; mContentAnnotations = orig.mContentAnnotations; mFlags = orig.mFlags; - mBucket = orig.mBucket; + mBucketAndReason = orig.mBucketAndReason; } /** @@ -268,7 +270,19 @@ public final class UsageEvents implements Parcelable { */ @SystemApi public int getStandbyBucket() { - return mBucket; + return (mBucketAndReason & 0xFFFF0000) >>> 16; + } + + /** + * Returns the reason for the bucketing, if the event is of type + * {@link #STANDBY_BUCKET_CHANGED}, otherwise returns 0. Reason values include + * the main reason which is one of REASON_MAIN_*, OR'ed with REASON_SUB_*, if there + * are sub-reasons for the main reason, such as REASON_SUB_USAGE_* when the main reason + * is REASON_MAIN_USAGE. + * @hide + */ + public int getStandbyReason() { + return mBucketAndReason & 0x0000FFFF; } /** @hide */ @@ -428,7 +442,7 @@ public final class UsageEvents implements Parcelable { p.writeStringArray(event.mContentAnnotations); break; case Event.STANDBY_BUCKET_CHANGED: - p.writeInt(event.mBucket); + p.writeInt(event.mBucketAndReason); break; } } @@ -474,7 +488,7 @@ public final class UsageEvents implements Parcelable { eventOut.mContentAnnotations = p.createStringArray(); break; case Event.STANDBY_BUCKET_CHANGED: - eventOut.mBucket = p.readInt(); + eventOut.mBucketAndReason = p.readInt(); break; } } diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java index cf359026105d069fd49dca0d4bf114baecc5972a..5a57b067f2c435f7c40d36feff774319331a9afa 100644 --- a/core/java/android/app/usage/UsageStatsManager.java +++ b/core/java/android/app/usage/UsageStatsManager.java @@ -28,6 +28,7 @@ import android.util.ArrayMap; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @@ -131,24 +132,37 @@ public final class UsageStatsManager { @SystemApi public static final int STANDBY_BUCKET_NEVER = 50; - /** {@hide} Reason for bucketing -- default initial state */ - public static final String REASON_DEFAULT = "default"; - - /** {@hide} Reason for bucketing -- timeout */ - public static final String REASON_TIMEOUT = "timeout"; - - /** {@hide} Reason for bucketing -- usage */ - public static final String REASON_USAGE = "usage"; - - /** {@hide} Reason for bucketing -- forced by user / shell command */ - public static final String REASON_FORCED = "forced"; + /** @hide */ + public static final int REASON_MAIN_MASK = 0xFF00; + /** @hide */ + public static final int REASON_MAIN_DEFAULT = 0x0100; + /** @hide */ + public static final int REASON_MAIN_TIMEOUT = 0x0200; + /** @hide */ + public static final int REASON_MAIN_USAGE = 0x0300; + /** @hide */ + public static final int REASON_MAIN_FORCED = 0x0400; + /** @hide */ + public static final int REASON_MAIN_PREDICTED = 0x0500; - /** - * {@hide} - * Reason for bucketing -- predicted. This is a prefix and the UID of the bucketeer will - * be appended. - */ - public static final String REASON_PREDICTED = "predicted"; + /** @hide */ + public static final int REASON_SUB_MASK = 0x00FF; + /** @hide */ + public static final int REASON_SUB_USAGE_SYSTEM_INTERACTION = 0x0001; + /** @hide */ + public static final int REASON_SUB_USAGE_NOTIFICATION_SEEN = 0x0002; + /** @hide */ + public static final int REASON_SUB_USAGE_USER_INTERACTION = 0x0003; + /** @hide */ + public static final int REASON_SUB_USAGE_MOVE_TO_FOREGROUND = 0x0004; + /** @hide */ + public static final int REASON_SUB_USAGE_MOVE_TO_BACKGROUND = 0x0005; + /** @hide */ + public static final int REASON_SUB_USAGE_SYSTEM_UPDATE = 0x0006; + /** @hide */ + public static final int REASON_SUB_USAGE_ACTIVE_TIMEOUT = 0x0007; + /** @hide */ + public static final int REASON_SUB_USAGE_SYNC_ADAPTER = 0x0008; /** @hide */ @IntDef(flag = false, prefix = { "STANDBY_BUCKET_" }, value = { @@ -388,8 +402,16 @@ public final class UsageStatsManager { @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public Map getAppStandbyBuckets() { try { - return (Map) mService.getAppStandbyBuckets( + final ParceledListSlice slice = mService.getAppStandbyBuckets( mContext.getOpPackageName(), mContext.getUserId()); + final List bucketList = slice.getList(); + final ArrayMap bucketMap = new ArrayMap<>(); + final int n = bucketList.size(); + for (int i = 0; i < n; i++) { + final AppStandbyInfo bucketInfo = bucketList.get(i); + bucketMap.put(bucketInfo.mPackageName, bucketInfo.mStandbyBucket); + } + return bucketMap; } catch (RemoteException e) { } return Collections.EMPTY_MAP; @@ -404,12 +426,69 @@ public final class UsageStatsManager { @SystemApi @RequiresPermission(android.Manifest.permission.CHANGE_APP_IDLE_STATE) public void setAppStandbyBuckets(Map appBuckets) { + if (appBuckets == null) { + return; + } + final List bucketInfoList = new ArrayList<>(appBuckets.size()); + for (Map.Entry bucketEntry : appBuckets.entrySet()) { + bucketInfoList.add(new AppStandbyInfo(bucketEntry.getKey(), bucketEntry.getValue())); + } + final ParceledListSlice slice = new ParceledListSlice<>(bucketInfoList); try { - mService.setAppStandbyBuckets(appBuckets, mContext.getUserId()); + mService.setAppStandbyBuckets(slice, mContext.getUserId()); } catch (RemoteException e) { } } + /** @hide */ + public static String reasonToString(int standbyReason) { + StringBuilder sb = new StringBuilder(); + switch (standbyReason & REASON_MAIN_MASK) { + case REASON_MAIN_DEFAULT: + sb.append("d"); + break; + case REASON_MAIN_FORCED: + sb.append("f"); + break; + case REASON_MAIN_PREDICTED: + sb.append("p"); + break; + case REASON_MAIN_TIMEOUT: + sb.append("t"); + break; + case REASON_MAIN_USAGE: + sb.append("u-"); + switch (standbyReason & REASON_SUB_MASK) { + case REASON_SUB_USAGE_SYSTEM_INTERACTION: + sb.append("si"); + break; + case REASON_SUB_USAGE_NOTIFICATION_SEEN: + sb.append("ns"); + break; + case REASON_SUB_USAGE_USER_INTERACTION: + sb.append("ui"); + break; + case REASON_SUB_USAGE_MOVE_TO_FOREGROUND: + sb.append("mf"); + break; + case REASON_SUB_USAGE_MOVE_TO_BACKGROUND: + sb.append("mb"); + break; + case REASON_SUB_USAGE_SYSTEM_UPDATE: + sb.append("su"); + break; + case REASON_SUB_USAGE_ACTIVE_TIMEOUT: + sb.append("at"); + break; + case REASON_SUB_USAGE_SYNC_ADAPTER: + sb.append("sa"); + break; + } + break; + } + return sb.toString(); + } + /** * {@hide} * Temporarily whitelist the specified app for a short duration. This is to allow an app diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java index 5d6a989ffef84135a0f63d40b9e9f37b57283e6f..b62b1ee0492b0a22d4c447110076f28e41eb15b9 100644 --- a/core/java/android/app/usage/UsageStatsManagerInternal.java +++ b/core/java/android/app/usage/UsageStatsManagerInternal.java @@ -139,7 +139,7 @@ public abstract class UsageStatsManagerInternal { /** Callback to inform listeners that the idle state has changed to a new bucket. */ public abstract void onAppIdleStateChanged(String packageName, @UserIdInt int userId, - boolean idle, int bucket); + boolean idle, int bucket, int reason); /** * Callback to inform listeners that the parole state has changed. This means apps are diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java index 0a0d2149803264c036d4c662940dee378ace56c4..605dbd21993f2f43a7fadf24a98796881ef01a75 100644 --- a/core/java/android/bluetooth/BluetoothUuid.java +++ b/core/java/android/bluetooth/BluetoothUuid.java @@ -79,9 +79,8 @@ public final class BluetoothUuid { ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid SAP = ParcelUuid.fromString("0000112D-0000-1000-8000-00805F9B34FB"); - /* TODO: b/69623109 update this value. It will change to 16bit UUID!! */ public static final ParcelUuid HearingAid = - ParcelUuid.fromString("7312C48F-22CC-497F-85FD-A0616A3B9E05"); + ParcelUuid.fromString("0000FDF0-0000-1000-8000-00805f9b34fb"); public static final ParcelUuid BASE_UUID = ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB"); diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index f184380fd36c181731ad4cb77906b510d35be9db..e1a00b146576750e1b37b01f025b004787a64db5 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3370,7 +3370,11 @@ public abstract class Context { * Use with {@link #getSystemService(String)} to retrieve a {@link * android.app.SearchManager} for handling searches. * - * @see #getSystemService(String) + *

    + * {@link Configuration#UI_MODE_TYPE_WATCH} does not support + * {@link android.app.SearchManager}. + * + * @see #getSystemService * @see android.app.SearchManager */ public static final String SEARCH_SERVICE = "search"; diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 0e50002288cd00e97dc29e54a0a5e1d06fe47b8f..e07fc86d697ac4e68dfd2871fd72f2452332b08e 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -39,6 +39,7 @@ import android.util.SparseArray; import android.util.proto.ProtoOutputStream; import com.android.internal.util.ArrayUtils; +import com.android.server.SystemConfig; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -1408,6 +1409,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { classLoaderName = orig.classLoaderName; splitClassLoaderNames = orig.splitClassLoaderNames; appComponentFactory = orig.appComponentFactory; + compileSdkVersion = orig.compileSdkVersion; + compileSdkVersionCodename = orig.compileSdkVersionCodename; } public String toString() { @@ -1631,7 +1634,10 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * @hide */ public boolean isAllowedToUseHiddenApi() { - return isSystemApp() || isUpdatedSystemApp(); + boolean whitelisted = + SystemConfig.getInstance().getHiddenApiWhitelistedApps().contains(packageName); + return isSystemApp() || // TODO get rid of this once the whitelist has been populated + (whitelisted && (isSystemApp() || isUpdatedSystemApp())); } /** diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 379bff49c9116a979baa3614798844fcbf1d440a..36a74a489890f802c71453a91fa5db85d8aa87ac 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -660,4 +660,6 @@ interface IPackageManager { boolean hasSigningCertificate(String packageName, in byte[] signingCertificate, int flags); boolean hasUidSigningCertificate(int uid, in byte[] signingCertificate, int flags); + + String getSystemTextClassifierPackageName(); } diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index d0be6c854020994db2d8127932a2ca415caf58f7..25af1a76700ff0be81eae4b2879634c0c50b0dff 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -448,11 +448,17 @@ public class PackageInstaller { /** * Uninstall the given package, removing it completely from the device. This - * method is only available to the current "installer of record" for the - * package. + * method is available to: + *

      + *
    • the current "installer of record" for the package + *
    • the device owner + *
    • the affiliated profile owner + *
    * * @param packageName The package to uninstall. * @param statusReceiver Where to deliver the result. + * + * @see android.app.admin.DevicePolicyManager */ @RequiresPermission(anyOf = { Manifest.permission.DELETE_PACKAGES, @@ -480,14 +486,22 @@ public class PackageInstaller { /** * Uninstall the given package with a specific version code, removing it - * completely from the device. This method is only available to the current - * "installer of record" for the package. If the version code of the package + * completely from the device. If the version code of the package * does not match the one passed in the versioned package argument this * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to * uninstall the latest version of the package. + *

    + * This method is available to: + *

      + *
    • the current "installer of record" for the package + *
    • the device owner + *
    • the affiliated profile owner + *
    * * @param versionedPackage The versioned package to uninstall. * @param statusReceiver Where to deliver the result. + * + * @see android.app.admin.DevicePolicyManager */ @RequiresPermission(anyOf = { Manifest.permission.DELETE_PACKAGES, @@ -941,9 +955,14 @@ public class PackageInstaller { * Once this method is called, the session is sealed and no additional * mutations may be performed on the session. If the device reboots * before the session has been finalized, you may commit the session again. + *

    + * If the installer is the device owner or the affiliated profile owner, there will be no + * user intervention. * * @throws SecurityException if streams opened through * {@link #openWrite(String, long, long)} are still open. + * + * @see android.app.admin.DevicePolicyManager */ public void commit(@NonNull IntentSender statusReceiver) { try { diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 07a991188a490ae5e58dd01aed7e09d2920b3377..bd7961fffca8dfe26a75fcbd1a212ff95a1ff8a0 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -6022,4 +6022,14 @@ public abstract class PackageManager { throw new UnsupportedOperationException( "hasSigningCertificate not implemented in subclass"); } + + /** + * @return the system defined text classifier package name, or null if there's none. + * + * @hide + */ + public String getSystemTextClassifierPackageName() { + throw new UnsupportedOperationException( + "getSystemTextClassifierPackageName not implemented in subclass"); + } } diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 6f093ba8d005c2d60a06d81a1aba672b9ab546ff..41aa9c374978a0514b741e6dd094d0d954fb2906 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -43,12 +43,14 @@ public abstract class PackageManagerInternal { public static final int PACKAGE_INSTALLER = 2; public static final int PACKAGE_VERIFIER = 3; public static final int PACKAGE_BROWSER = 4; + public static final int PACKAGE_SYSTEM_TEXT_CLASSIFIER = 5; @IntDef(value = { PACKAGE_SYSTEM, PACKAGE_SETUP_WIZARD, PACKAGE_INSTALLER, PACKAGE_VERIFIER, PACKAGE_BROWSER, + PACKAGE_SYSTEM_TEXT_CLASSIFIER, }) @Retention(RetentionPolicy.SOURCE) public @interface KnownPackage {} diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 9e4166eaec1b17c0ec188e5bef34dd74f0fcc0b2..2420b639d678b05eab74970f9fd4cee465b1662a 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -3185,7 +3185,7 @@ public class PackageParser { perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel); - if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_FLAGS) != 0) { + if (perm.info.getProtectionFlags() != 0) { if ( (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_INSTANT) == 0 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) == 0 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) != diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java index 21bd7f0ce7634580feb0d1d5e52c6ec32024b4dc..938409af90e9b09ab46ec3d802b16216561c2763 100644 --- a/core/java/android/content/pm/PermissionInfo.java +++ b/core/java/android/content/pm/PermissionInfo.java @@ -16,12 +16,16 @@ package android.content.pm; +import android.annotation.IntDef; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Information you can retrieve about a particular security permission * known to the system. This corresponds to information collected from the @@ -56,6 +60,16 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { @Deprecated public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3; + /** @hide */ + @IntDef(flag = false, prefix = { "PROTECTION_" }, value = { + PROTECTION_NORMAL, + PROTECTION_DANGEROUS, + PROTECTION_SIGNATURE, + PROTECTION_SIGNATURE_OR_SYSTEM, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Protection {} + /** * Additional flag for {@link #protectionLevel}, corresponding * to the privileged value of @@ -154,31 +168,72 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { @TestApi public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 0x8000; + /** + * Additional flag for {@link #protectionLevel}, corresponding + * to the text_classifier value of + * {@link android.R.attr#protectionLevel}. + * + * @hide + */ + @SystemApi + @TestApi + public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 0x10000; + + /** @hide */ + @IntDef(flag = true, prefix = { "PROTECTION_FLAG_" }, value = { + PROTECTION_FLAG_PRIVILEGED, + PROTECTION_FLAG_SYSTEM, + PROTECTION_FLAG_DEVELOPMENT, + PROTECTION_FLAG_APPOP, + PROTECTION_FLAG_PRE23, + PROTECTION_FLAG_INSTALLER, + PROTECTION_FLAG_VERIFIER, + PROTECTION_FLAG_PREINSTALLED, + PROTECTION_FLAG_SETUP, + PROTECTION_FLAG_INSTANT, + PROTECTION_FLAG_RUNTIME_ONLY, + PROTECTION_FLAG_OEM, + PROTECTION_FLAG_VENDOR_PRIVILEGED, + PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ProtectionFlags {} + /** * Mask for {@link #protectionLevel}: the basic protection type. + * + * @deprecated Use #getProtection() instead. */ + @Deprecated public static final int PROTECTION_MASK_BASE = 0xf; /** * Mask for {@link #protectionLevel}: additional flag bits. + * + * @deprecated Use #getProtectionFlags() instead. */ + @Deprecated public static final int PROTECTION_MASK_FLAGS = 0xfff0; /** * The level of access this permission is protecting, as per * {@link android.R.attr#protectionLevel}. Consists of - * a base permission type and zero or more flags: + * a base permission type and zero or more flags. Use the following functions + * to extract them. * *

    -     * int basePermissionType = protectionLevel & {@link #PROTECTION_MASK_BASE};
    -     * int permissionFlags = protectionLevel & {@link #PROTECTION_MASK_FLAGS};
    +     * int basePermissionType = permissionInfo.getProtection();
    +     * int permissionFlags = permissionInfo.getProtectionFlags();
          * 
    * *

    Base permission types are {@link #PROTECTION_NORMAL}, * {@link #PROTECTION_DANGEROUS}, {@link #PROTECTION_SIGNATURE} * and the deprecated {@link #PROTECTION_SIGNATURE_OR_SYSTEM}. * Flags are listed under {@link android.R.attr#protectionLevel}. + * + * @deprecated Use #getProtection() and #getProtectionFlags() instead. */ + @Deprecated public int protectionLevel; /** @@ -304,6 +359,9 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { if ((level & PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0) { protLevel += "|vendorPrivileged"; } + if ((level & PermissionInfo.PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER) != 0) { + protLevel += "|textClassifier"; + } return protLevel; } @@ -344,6 +402,22 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { return null; } + /** + * Return the base permission type. + */ + @Protection + public int getProtection() { + return protectionLevel & PROTECTION_MASK_BASE; + } + + /** + * Return the additional flags in {@link #protectionLevel}. + */ + @ProtectionFlags + public int getProtectionFlags() { + return protectionLevel & ~PROTECTION_MASK_BASE; + } + @Override public String toString() { return "PermissionInfo{" diff --git a/core/java/android/content/pm/dex/ArtManagerInternal.java b/core/java/android/content/pm/dex/ArtManagerInternal.java new file mode 100644 index 0000000000000000000000000000000000000000..62ab9e02f85804f8fbcba447a245cd875559cd4c --- /dev/null +++ b/core/java/android/content/pm/dex/ArtManagerInternal.java @@ -0,0 +1,34 @@ +/** + * 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.content.pm.dex; + +import android.content.pm.ApplicationInfo; + +/** + * Art manager local system service interface. + * + * @hide Only for use within the system server. + */ +public abstract class ArtManagerInternal { + + /** + * Return optimization information about the application {@code info} when + * in executes using the specified {@code abi}. + */ + public abstract PackageOptimizationInfo getPackageOptimizationInfo( + ApplicationInfo info, String abi); +} diff --git a/core/java/android/content/pm/dex/PackageOptimizationInfo.java b/core/java/android/content/pm/dex/PackageOptimizationInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..b65045794d35127bc3988d76623aa54d0c185c18 --- /dev/null +++ b/core/java/android/content/pm/dex/PackageOptimizationInfo.java @@ -0,0 +1,47 @@ +/** + * 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.content.pm.dex; + +/** + * Encapsulates information about the optimizations performed on a package. + * + * @hide + */ +public class PackageOptimizationInfo { + private final String mCompilationFilter; + private final String mCompilationReason; + + public PackageOptimizationInfo(String compilerFilter, String compilationReason) { + this.mCompilationReason = compilationReason; + this.mCompilationFilter = compilerFilter; + } + + public String getCompilationReason() { + return mCompilationReason; + } + + public String getCompilationFilter() { + return mCompilationFilter; + } + + /** + * Create a default optimization info object for the case when we have no information. + */ + public static PackageOptimizationInfo createWithNoInfo() { + return new PackageOptimizationInfo("no-info", "no-info"); + } +} diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index eb309799fe0f5a5c5295b8d27e0b89e26e5031bc..93690bf3aef9d93e2e768c1250c9c97bbb10b6ef 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -18,13 +18,27 @@ package android.content.res; import static android.content.ConfigurationProto.DENSITY_DPI; import static android.content.ConfigurationProto.FONT_SCALE; +import static android.content.ConfigurationProto.HARD_KEYBOARD_HIDDEN; +import static android.content.ConfigurationProto.HDR_COLOR_MODE; +import static android.content.ConfigurationProto.KEYBOARD_HIDDEN; +import static android.content.ConfigurationProto.LOCALES; +import static android.content.ConfigurationProto.MCC; +import static android.content.ConfigurationProto.MNC; +import static android.content.ConfigurationProto.NAVIGATION; +import static android.content.ConfigurationProto.NAVIGATION_HIDDEN; import static android.content.ConfigurationProto.ORIENTATION; import static android.content.ConfigurationProto.SCREEN_HEIGHT_DP; import static android.content.ConfigurationProto.SCREEN_LAYOUT; import static android.content.ConfigurationProto.SCREEN_WIDTH_DP; import static android.content.ConfigurationProto.SMALLEST_SCREEN_WIDTH_DP; +import static android.content.ConfigurationProto.TOUCHSCREEN; import static android.content.ConfigurationProto.UI_MODE; +import static android.content.ConfigurationProto.WIDE_COLOR_GAMUT; import static android.content.ConfigurationProto.WINDOW_CONFIGURATION; +import static android.content.ResourcesConfigurationProto.CONFIGURATION; +import static android.content.ResourcesConfigurationProto.SCREEN_HEIGHT_PX; +import static android.content.ResourcesConfigurationProto.SCREEN_WIDTH_PX; +import static android.content.ResourcesConfigurationProto.SDK_VERSION; import android.annotation.IntDef; import android.annotation.NonNull; @@ -38,6 +52,7 @@ import android.os.LocaleList; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import android.util.DisplayMetrics; import android.util.proto.ProtoOutputStream; import android.view.View; @@ -1076,7 +1091,19 @@ public final class Configuration implements Parcelable, Comparable> COLOR_MODE_HDR_SHIFT); + protoOutputStream.write(WIDE_COLOR_GAMUT, + colorMode & Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_MASK); + protoOutputStream.write(TOUCHSCREEN, touchscreen); + protoOutputStream.write(KEYBOARD_HIDDEN, keyboardHidden); + protoOutputStream.write(HARD_KEYBOARD_HIDDEN, hardKeyboardHidden); + protoOutputStream.write(NAVIGATION, navigation); + protoOutputStream.write(NAVIGATION_HIDDEN, navigationHidden); protoOutputStream.write(ORIENTATION, orientation); protoOutputStream.write(UI_MODE, uiMode); protoOutputStream.write(SCREEN_WIDTH_DP, screenWidthDp); @@ -1087,6 +1114,36 @@ public final class Configuration implements Parcelable, Comparable= metrics.heightPixels) { + width = metrics.widthPixels; + height = metrics.heightPixels; + } else { + //noinspection SuspiciousNameCombination + width = metrics.heightPixels; + //noinspection SuspiciousNameCombination + height = metrics.widthPixels; + } + + final long token = protoOutputStream.start(fieldId); + writeToProto(protoOutputStream, CONFIGURATION); + protoOutputStream.write(SDK_VERSION, Build.VERSION.RESOURCES_SDK_INT); + protoOutputStream.write(SCREEN_WIDTH_PX, width); + protoOutputStream.write(SCREEN_HEIGHT_PX, height); + protoOutputStream.end(token); + } + /** * Convert the UI mode to a human readable format. * @hide @@ -1925,11 +1982,21 @@ public final class Configuration implements Parcelable, Comparable parts = new ArrayList(); if (config.mcc != 0) { @@ -2177,6 +2244,20 @@ public final class Configuration implements Parcelable, Comparable= metrics.heightPixels) { + width = metrics.widthPixels; + height = metrics.heightPixels; + } else { + //noinspection SuspiciousNameCombination + width = metrics.heightPixels; + //noinspection SuspiciousNameCombination + height = metrics.widthPixels; + } + parts.add(width + "x" + height); + } + parts.add("v" + Build.VERSION.RESOURCES_SDK_INT); return TextUtils.join("-", parts); } diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index e558b7e29a20567ec378206acf0b9899477e35f0..52aefcc4830451fac642b70cf8dd9c55aae119b3 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -2646,6 +2646,10 @@ public abstract class CameraMetadata { /** *

    Include OIS data in the capture result.

    + *

    {@link CaptureResult#STATISTICS_OIS_SAMPLES android.statistics.oisSamples} provides OIS sample data in the + * output result metadata.

    + * + * @see CaptureResult#STATISTICS_OIS_SAMPLES * @see CaptureRequest#STATISTICS_OIS_DATA_MODE */ public static final int STATISTICS_OIS_DATA_MODE_ON = 1; diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index 3ed533a4efcbd89efa7aca22ab1ed5a6842aefa6..ada7ebf0f5dacdf1f5050d3e7f59faa8ec148d84 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -24,6 +24,7 @@ import android.hardware.camera2.impl.SyntheticKey; import android.hardware.camera2.params.OutputConfiguration; import android.hardware.camera2.utils.HashCodeHelpers; import android.hardware.camera2.utils.TypeReference; +import android.hardware.camera2.utils.SurfaceUtils; import android.os.Parcel; import android.os.Parcelable; import android.util.ArraySet; @@ -643,6 +644,30 @@ public final class CaptureRequest extends CameraMetadata> break; } } + + if (!streamFound) { + // Check if we can match s by native object ID + long reqSurfaceId = SurfaceUtils.getSurfaceId(s); + for (int j = 0; j < configuredOutputs.size(); ++j) { + int streamId = configuredOutputs.keyAt(j); + OutputConfiguration outConfig = configuredOutputs.valueAt(j); + int surfaceId = 0; + for (Surface outSurface : outConfig.getSurfaces()) { + if (reqSurfaceId == SurfaceUtils.getSurfaceId(outSurface)) { + streamFound = true; + mStreamIdxArray[i] = streamId; + mSurfaceIdxArray[i] = surfaceId; + i++; + break; + } + surfaceId++; + } + if (streamFound) { + break; + } + } + } + if (!streamFound) { mStreamIdxArray = null; mSurfaceIdxArray = null; @@ -2759,9 +2784,6 @@ public final class CaptureRequest extends CameraMetadata> /** *

    A control for selecting whether OIS position information is included in output * result metadata.

    - *

    When set to ON, - * {@link CaptureResult#STATISTICS_OIS_TIMESTAMPS android.statistics.oisTimestamps}, android.statistics.oisShiftPixelX, - * and android.statistics.oisShiftPixelY provide OIS data in the output result metadata.

    *

    Possible values: *